feat: disable invuln for plugin damage + DamageUtil + DiamondTri/Barrage/Overhead nerf

This commit is contained in:
SashegDev
2026-08-28 14:17:21 +03:00
parent a8ce2375c0
commit e227ad63bd
8 changed files with 244 additions and 21 deletions
@@ -25,7 +25,7 @@ public class BlackKnifeListener implements Listener {
private final java.util.Map<java.util.UUID, BukkitRunnable> previewTasks = new java.util.HashMap<>(); private final java.util.Map<java.util.UUID, BukkitRunnable> previewTasks = new java.util.HashMap<>();
private final java.util.Map<java.util.UUID, BukkitRunnable> lungeHighlightTasks = new java.util.HashMap<>(); private final java.util.Map<java.util.UUID, BukkitRunnable> lungeHighlightTasks = new java.util.HashMap<>();
private final java.util.Map<java.util.UUID, Integer> swordCombo = new java.util.HashMap<>(); private final java.util.Map<java.util.UUID, Integer> swordCombo = new java.util.HashMap<>();
private static final String[] MODES = {"STARS", "SWORD", "DIAMOND", "LUNGE", "SNIPE", "TRI", "OVERHEAD"}; private static final String[] MODES = {"STARS", "SWORD", "DIAMOND", "DIAMOND_TRI", "BARRAGE", "LUNGE", "SNIPE", "TRI", "OVERHEAD"};
public BlackKnifeListener(BlackKnifePlugin plugin) { this.plugin = plugin; } public BlackKnifeListener(BlackKnifePlugin plugin) { this.plugin = plugin; }
@@ -119,6 +119,14 @@ public class BlackKnifeListener implements Listener {
p.setCooldown(item.getType(), 15); p.setCooldown(item.getType(), 15);
p.getWorld().playSound(p.getLocation(), Sound.BLOCK_AMETHYST_BLOCK_PLACE, 1f, 0.9f); p.getWorld().playSound(p.getLocation(), Sound.BLOCK_AMETHYST_BLOCK_PLACE, 1f, 0.9f);
} }
} else if (m.equals("DIAMOND_TRI")) {
if (DiamondTripleAttack.tryUse(p, tm)) {
p.setCooldown(item.getType(), 40);
}
} else if (m.equals("BARRAGE")) {
if (PhantomBarrageAttack.tryUse(p, tm)) {
p.setCooldown(item.getType(), 50);
}
} else if (m.equals("LUNGE")) { } else if (m.equals("LUNGE")) {
LivingEntity target = getLungeTarget(p); LivingEntity target = getLungeTarget(p);
if (LungeAttack.tryUse(p, tm, target)) { if (LungeAttack.tryUse(p, tm, target)) {
@@ -138,7 +146,7 @@ public class BlackKnifeListener implements Listener {
} else if (m.equals("OVERHEAD")) { } else if (m.equals("OVERHEAD")) {
Location gaze = getGazePoint(p); Location gaze = getGazePoint(p);
if (LungeAttack.tryOverhead(p, tm, gaze)) { if (LungeAttack.tryOverhead(p, tm, gaze)) {
p.setCooldown(item.getType(), 30); p.setCooldown(item.getType(), 50);
} }
} }
e.setCancelled(true); e.setCancelled(true);
@@ -229,7 +237,7 @@ public class BlackKnifeListener implements Listener {
Location gp = getGazePoint(p); Location gp = getGazePoint(p);
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
double a = (double) i / 16 * Math.PI * 2; double a = (double) i / 16 * Math.PI * 2;
Location ring = gp.clone().add(Math.cos(a) * 2, 0.1, Math.sin(a) * 2); Location ring = gp.clone().add(Math.cos(a) * 1.8, 0.1, Math.sin(a) * 1.8);
p.spawnParticle(Particle.DUST, ring, 1, 0, 0, 0, 0, new Particle.DustOptions(Color.fromRGB(20, 20, 20), 1.2f)); p.spawnParticle(Particle.DUST, ring, 1, 0, 0, 0, 0, new Particle.DustOptions(Color.fromRGB(20, 20, 20), 1.2f));
p.spawnParticle(Particle.ASH, ring, 1, 0, 0, 0, 0); p.spawnParticle(Particle.ASH, ring, 1, 0, 0, 0, 0);
} }
@@ -243,6 +251,30 @@ public class BlackKnifeListener implements Listener {
}; };
r.runTaskTimer(plugin, 1L, 4L); r.runTaskTimer(plugin, 1L, 4L);
lungeHighlightTasks.put(p.getUniqueId(), r); lungeHighlightTasks.put(p.getUniqueId(), r);
} else if (m.equals("DIAMOND_TRI")) {
BukkitRunnable r = new BukkitRunnable() {
@Override public void run() {
if (!p.isOnline() || !getMode(p).equals("DIAMOND_TRI")) { cancel(); return; }
if (p.hasCooldown(Material.NETHERITE_SWORD)) return;
if (!BlackKnifeItem.is(p.getInventory().getItemInMainHand()) && !BlackKnifeItem.is(p.getInventory().getItemInOffHand())) return;
Location base = p.getEyeLocation().add(p.getEyeLocation().getDirection().normalize().multiply(1.5));
for (int i=0;i<3;i++){ double a=(double)i/3*Math.PI*2; Location pp=base.clone().add(Math.cos(a)*0.5, Math.sin(a)*0.3, Math.sin(a)*0.5); p.spawnParticle(Particle.DUST,pp,1,0,0,0,0,new Particle.DustOptions(Color.fromRGB(180,0,255),1f)); p.spawnParticle(Particle.END_ROD,pp,1,0.02,0.02,0.02,0); }
}
};
r.runTaskTimer(plugin, 1L, 5L);
lungeHighlightTasks.put(p.getUniqueId(), r);
} else if (m.equals("BARRAGE")) {
BukkitRunnable r = new BukkitRunnable() {
@Override public void run() {
if (!p.isOnline() || !getMode(p).equals("BARRAGE")) { cancel(); return; }
if (p.hasCooldown(Material.NETHERITE_SWORD)) return;
if (!BlackKnifeItem.is(p.getInventory().getItemInMainHand()) && !BlackKnifeItem.is(p.getInventory().getItemInOffHand())) return;
Location c = p.getLocation().add(0,1,0);
for(int i=0;i<5;i++){ double a=(double)i/5*Math.PI*2 + System.currentTimeMillis()*0.002; Location orb=c.clone().add(Math.cos(a)*1.5, Math.sin(a*2)*0.3, Math.sin(a)*1.5); p.spawnParticle(Particle.SCULK_SOUL,orb,1,0.02,0.02,0.02,0); p.spawnParticle(Particle.ASH,orb,1,0,0,0,0); }
}
};
r.runTaskTimer(plugin, 1L, 4L);
lungeHighlightTasks.put(p.getUniqueId(), r);
} }
} }
@@ -298,8 +330,7 @@ public class BlackKnifeListener implements Listener {
for (var ent : n2.getWorld().getNearbyEntities(n2, 0.7, 0.7, 0.7)) { for (var ent : n2.getWorld().getNearbyEntities(n2, 0.7, 0.7, 0.7)) {
if (ent instanceof Player pl && pl != p) continue; if (ent instanceof Player pl && pl != p) continue;
if (ent instanceof org.bukkit.entity.LivingEntity le && le != p) { if (ent instanceof org.bukkit.entity.LivingEntity le && le != p) {
le.getPersistentDataContainer().set(SwoonHandler.MAGIC_DAMAGE, PersistentDataType.BYTE, (byte) 1); DamageUtil.apply(p, le, 3.0);
le.damage(3.0, p);
shard.remove(); shard.remove();
cancel(); cancel();
break; break;
@@ -0,0 +1,23 @@
package me.sashegdev.blackknife;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataType;
public class DamageUtil {
public static void apply(Player attacker, LivingEntity victim, double amount) {
victim.getPersistentDataContainer().set(SwoonHandler.MAGIC_DAMAGE, PersistentDataType.BYTE, (byte) 1);
victim.damage(amount, attacker);
victim.getPersistentDataContainer().remove(SwoonHandler.MAGIC_DAMAGE);
victim.setNoDamageTicks(0);
victim.setMaximumNoDamageTicks(10);
BlackKnifePlugin.getInstance().getServer().getScheduler().runTaskLater(BlackKnifePlugin.getInstance(), () -> {
if (victim.isValid() && victim.getMaximumNoDamageTicks() == 0) victim.setMaximumNoDamageTicks(10);
}, 1L);
}
public static void applyRaw(Player attacker, LivingEntity victim, double amount) {
if (victim instanceof Player pl && pl.isBlocking()) amount /= 2.5;
apply(attacker, victim, amount);
}
}
@@ -67,8 +67,7 @@ public class DiamondAttack {
n2.getWorld().spawnParticle(Particle.CRIT, n2, 1, 0.05, 0.05, 0.05, 0); n2.getWorld().spawnParticle(Particle.CRIT, n2, 1, 0.05, 0.05, 0.05, 0);
for (var ent : n2.getWorld().getNearbyEntities(n2, 0.7, 0.7, 0.7, e -> e instanceof LivingEntity && e != p)) { for (var ent : n2.getWorld().getNearbyEntities(n2, 0.7, 0.7, 0.7, e -> e instanceof LivingEntity && e != p)) {
LivingEntity le = (LivingEntity) ent; LivingEntity le = (LivingEntity) ent;
le.getPersistentDataContainer().set(SwoonHandler.MAGIC_DAMAGE, PersistentDataType.BYTE, (byte) 1); DamageUtil.apply(p, le, 2.0);
le.damage(2.0, p);
shard.remove(); shard.remove();
cancel(); cancel();
break; break;
@@ -93,8 +92,7 @@ public class DiamondAttack {
boolean hit = false; boolean hit = false;
for (var ent : nl.getWorld().getNearbyEntities(nl, 0.7, 0.7, 0.7, e -> e instanceof LivingEntity && e != p)) { for (var ent : nl.getWorld().getNearbyEntities(nl, 0.7, 0.7, 0.7, e -> e instanceof LivingEntity && e != p)) {
LivingEntity le = (LivingEntity) ent; LivingEntity le = (LivingEntity) ent;
le.getPersistentDataContainer().set(SwoonHandler.MAGIC_DAMAGE, PersistentDataType.BYTE, (byte) 1); DamageUtil.apply(p, le, 5.0);
le.damage(5.0, p);
hit = true; hit = true;
break; break;
} }
@@ -136,8 +134,7 @@ public class DiamondAttack {
shard.getWorld().spawnParticle(Particle.CRIT, n2, 1, 0.05, 0.05, 0.05, 0); shard.getWorld().spawnParticle(Particle.CRIT, n2, 1, 0.05, 0.05, 0.05, 0);
for (var ent : n2.getWorld().getNearbyEntities(n2, 0.7, 0.7, 0.7, e -> e instanceof LivingEntity && e != p)) { for (var ent : n2.getWorld().getNearbyEntities(n2, 0.7, 0.7, 0.7, e -> e instanceof LivingEntity && e != p)) {
LivingEntity le = (LivingEntity) ent; LivingEntity le = (LivingEntity) ent;
le.getPersistentDataContainer().set(SwoonHandler.MAGIC_DAMAGE, PersistentDataType.BYTE, (byte) 1); DamageUtil.apply(p, le, 2.0); shard.remove(); cancel(); break;
le.damage(2.0, p); shard.remove(); cancel(); break;
} }
for (Player pl : n2.getWorld().getNearbyPlayers(n2, 0.9)) { for (Player pl : n2.getWorld().getNearbyPlayers(n2, 0.9)) {
if (pl == p) continue; if (pl == p) continue;
@@ -0,0 +1,85 @@
package me.sashegdev.blackknife;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.entity.BlockDisplay;
import org.bukkit.entity.Display;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
public class DiamondTripleAttack {
public static boolean tryUse(Player p, TensionManager tension) {
if (tension.getTP(p) < 87.5f) { p.sendActionBar(Component.text("Need 35% TP").color(NamedTextColor.RED)); return false; }
tension.setTP(p, tension.getTP(p) - 87.5f);
Location target = getGazeTarget(p);
if (target == null) target = p.getEyeLocation().add(p.getEyeLocation().getDirection().normalize().multiply(20));
double baseAngle = p.getEyeLocation().getYaw();
for (int i = 0; i < 3; i++) {
double angle = (baseAngle + i * 120) % 360;
Vector dir = Vector.getRandom().normalize();
double yawRad = Math.toRadians(angle);
Vector offset = new Vector(Math.cos(yawRad), 0, Math.sin(yawRad)).multiply(0.7);
Location spawn = p.getEyeLocation().clone().add(offset).add(p.getEyeLocation().getDirection().normalize().multiply(1.5));
launch(p, target.clone(), spawn);
}
p.getWorld().playSound(p.getLocation(), Sound.BLOCK_AMETHYST_BLOCK_PLACE, 1f, 1.1f);
return true;
}
private static Location getGazeTarget(Player p) {
var ray = p.getWorld().rayTraceBlocks(p.getEyeLocation(), p.getEyeLocation().getDirection(), 40);
if (ray != null && ray.getHitPosition() != null) return new Location(p.getWorld(), ray.getHitPosition().getX(), ray.getHitPosition().getY(), ray.getHitPosition().getZ());
return null;
}
private static void launch(Player p, Location target, Location spawn) {
BlockDisplay shard = p.getWorld().spawn(spawn, BlockDisplay.class, d -> {
d.setBlock(Material.AMETHYST_BLOCK.createBlockData());
d.setBrightness(new Display.Brightness(15, 15));
d.setViewRange(64);
d.setTransformation(new org.bukkit.util.Transformation(new org.joml.Vector3f(-0.45f, -0.45f, -0.45f), new org.joml.AxisAngle4f(), new org.joml.Vector3f(0.9f, 0.9f, 0.9f), new org.joml.AxisAngle4f()));
});
EntityTracker.mark(shard);
BlackKnifePlugin plugin = BlackKnifePlugin.getPlugin(BlackKnifePlugin.class);
Vector initDir = target.clone().subtract(spawn).toVector().normalize().multiply(1.4);
new BukkitRunnable() {
Vector vel = initDir.clone();
@Override public void run() {
if (!shard.isValid() || shard.isDead()) { cancel(); return; }
Location cur = shard.getLocation();
Vector toTarget = target.clone().subtract(cur).toVector().normalize().multiply(1.4);
vel = vel.multiply(0.88).add(toTarget.multiply(0.12)).normalize().multiply(1.4);
Location nl = cur.clone().add(vel);
int steps = Math.max(1, (int)Math.ceil(vel.length()/0.5));
for (int s=0;s<=steps;s++) {
Location check = cur.clone().add(vel.clone().multiply((double)s/steps));
if (check.getBlock().isSolid()) { shard.remove(); cancel(); return; }
}
shard.teleport(nl);
nl.getWorld().spawnParticle(Particle.DUST, nl,1,0,0,0,0,new Particle.DustOptions(Color.fromRGB(180,0,255),1f));
nl.getWorld().spawnParticle(Particle.END_ROD, nl,1,0.05,0.05,0.05,0);
for (LivingEntity le : nl.getWorld().getNearbyLivingEntities(nl,0.8)) {
if (le == p) continue;
DamageUtil.apply(p, le, 7.0);
le.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.SLOWNESS,20,0,false,false,true));
nl.getWorld().spawnParticle(Particle.CRIT, le.getLocation().add(0,1,0),8,0.3,0.3,0.3,0.1);
shard.remove(); cancel(); return;
}
for (Player pl : nl.getWorld().getNearbyPlayers(nl,0.9)) {
if (pl==p) continue;
double d2 = pl.getLocation().add(0,1,0).distanceSquared(nl);
if (d2>0.25 && d2<0.81) plugin.getTension().addTP(pl,2.5f,"DODGE +1%");
}
if (nl.distanceSquared(spawn) > 1600 || shard.getTicksLived() > 80) { shard.remove(); cancel(); }
}
}.runTaskTimer(plugin,1L,1L);
}
}
@@ -196,11 +196,11 @@ public class LungeAttack {
p.sendActionBar(Component.text("Look at ground within 120 blocks!").color(NamedTextColor.RED)); p.sendActionBar(Component.text("Look at ground within 120 blocks!").color(NamedTextColor.RED));
return false; return false;
} }
if (tension.getTP(p) < 50f) { if (tension.getTP(p) < 62.5f) {
p.sendActionBar(Component.text("Need 20% TP").color(NamedTextColor.RED)); p.sendActionBar(Component.text("Need 25% TP").color(NamedTextColor.RED));
return false; return false;
} }
tension.setTP(p, tension.getTP(p) - 50f); tension.setTP(p, tension.getTP(p) - 62.5f);
BlackKnifePlugin plugin = BlackKnifePlugin.getPlugin(BlackKnifePlugin.class); BlackKnifePlugin plugin = BlackKnifePlugin.getPlugin(BlackKnifePlugin.class);
Location above = gazePoint.clone().add(0, 10, 0); Location above = gazePoint.clone().add(0, 10, 0);
BlockDisplay sword = p.getWorld().spawn(above, BlockDisplay.class, d -> { BlockDisplay sword = p.getWorld().spawn(above, BlockDisplay.class, d -> {
@@ -213,13 +213,22 @@ public class LungeAttack {
new org.joml.Vector3f(1.5f, 1.5f, 1.5f), new org.joml.Vector3f(1.5f, 1.5f, 1.5f),
new org.joml.AxisAngle4f())); new org.joml.AxisAngle4f()));
}); });
EntityTracker.mark(sword);
p.getWorld().playSound(gazePoint, Sound.ENTITY_PLAYER_ATTACK_SWEEP, 1f, 0.5f); p.getWorld().playSound(gazePoint, Sound.ENTITY_PLAYER_ATTACK_SWEEP, 1f, 0.5f);
p.getWorld().playSound(gazePoint, Sound.BLOCK_ANVIL_LAND, 0.6f, 1.4f); p.getWorld().playSound(gazePoint, Sound.BLOCK_ANVIL_LAND, 0.6f, 1.4f);
Vector vel = new Vector(0, -1.8, 0); Vector vel = new Vector(0, -1.2, 0);
new BukkitRunnable() { new BukkitRunnable() {
int hold = 8;
@Override public void run() { @Override public void run() {
if (!sword.isValid()) { cancel(); return; } if (!sword.isValid()) { cancel(); return; }
Location cur = sword.getLocation(); Location cur = sword.getLocation();
if (hold > 0) {
hold--;
cur.getWorld().spawnParticle(Particle.SMOKE, cur, 2, 0.15, 0.15, 0.15, 0);
cur.getWorld().spawnParticle(Particle.SCULK_SOUL, cur, 1, 0.05, 0.05, 0.05, 0);
cur.getWorld().spawnParticle(Particle.ASH, cur, 1, 0, 0, 0, 0);
return;
}
Location nl = cur.clone().add(vel); Location nl = cur.clone().add(vel);
sword.teleport(nl); sword.teleport(nl);
nl.getWorld().spawnParticle(Particle.DUST, nl, 2, 0.15, 0.15, 0.15, 0, new Particle.DustOptions(Color.fromRGB(0, 0, 0), 1.5f)); nl.getWorld().spawnParticle(Particle.DUST, nl, 2, 0.15, 0.15, 0.15, 0, new Particle.DustOptions(Color.fromRGB(0, 0, 0), 1.5f));
@@ -265,6 +274,7 @@ public class LungeAttack {
if (ent instanceof Player pl && pl.isBlocking()) amount /= 2.5; if (ent instanceof Player pl && pl.isBlocking()) amount /= 2.5;
ent.getPersistentDataContainer().set(SwoonHandler.MAGIC_DAMAGE, PersistentDataType.BYTE, (byte) 1); ent.getPersistentDataContainer().set(SwoonHandler.MAGIC_DAMAGE, PersistentDataType.BYTE, (byte) 1);
ent.damage(amount, attacker); ent.damage(amount, attacker);
ent.setNoDamageTicks(0);
} }
private static void startPhase1(Player p, Location epicenter, LivingEntity target, BlackKnifePlugin plugin) { private static void startPhase1(Player p, Location epicenter, LivingEntity target, BlackKnifePlugin plugin) {
@@ -166,8 +166,7 @@ public class MagicListener implements Listener {
marker.teleport(nl); marker.teleport(nl);
for(var ent: nl.getWorld().getNearbyEntities(nl,0.7,0.7,0.7, en->en instanceof LivingEntity && en!=p)) { for(var ent: nl.getWorld().getNearbyEntities(nl,0.7,0.7,0.7, en->en instanceof LivingEntity && en!=p)) {
LivingEntity le=(LivingEntity)ent; LivingEntity le=(LivingEntity)ent;
le.getPersistentDataContainer().set(SwoonHandler.MAGIC_DAMAGE,PersistentDataType.BYTE,(byte)1); DamageUtil.apply(p, le, 15.0);
le.damage(15.0,p);
Location hit=le.getLocation().add(0,1,0); Location hit=le.getLocation().add(0,1,0);
for(int k=0;k<12;k++){ double a=(double)k/12*Math.PI*2; for(int h=-1;h<=1;h++){ Location s=hit.clone().add(Math.cos(a)*0.5,h*0.25,Math.sin(a)*0.5); s.getWorld().spawnParticle(Particle.DUST,s,1,0,0,0,0,new Particle.DustOptions(Color.fromRGB(200,40,40),0.9f)); } } hit.getWorld().spawnParticle(Particle.CRIT,hit,10,0.3,0.3,0.3,0.1); hit.getWorld().playSound(hit,Sound.ENTITY_PLAYER_ATTACK_CRIT,1f,0.9f); for(int k=0;k<12;k++){ double a=(double)k/12*Math.PI*2; for(int h=-1;h<=1;h++){ Location s=hit.clone().add(Math.cos(a)*0.5,h*0.25,Math.sin(a)*0.5); s.getWorld().spawnParticle(Particle.DUST,s,1,0,0,0,0,new Particle.DustOptions(Color.fromRGB(200,40,40),0.9f)); } } hit.getWorld().spawnParticle(Particle.CRIT,hit,10,0.3,0.3,0.3,0.1); hit.getWorld().playSound(hit,Sound.ENTITY_PLAYER_ATTACK_CRIT,1f,0.9f);
le.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.SLOWNESS,40,1,false,false,true)); le.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.SLOWNESS,40,1,false,false,true));
@@ -205,8 +204,7 @@ public class MagicListener implements Listener {
marker.teleport(nl); marker.teleport(nl);
for(var ent: nl.getWorld().getNearbyEntities(nl,0.7,0.7,0.7, en->en instanceof LivingEntity && en!=p)) { for(var ent: nl.getWorld().getNearbyEntities(nl,0.7,0.7,0.7, en->en instanceof LivingEntity && en!=p)) {
LivingEntity le=(LivingEntity)ent; LivingEntity le=(LivingEntity)ent;
le.getPersistentDataContainer().set(SwoonHandler.MAGIC_DAMAGE,PersistentDataType.BYTE,(byte)1); DamageUtil.apply(p, le, 8.0);
le.damage(8.0,p);
Location hit=le.getLocation().add(0,1,0); Location hit=le.getLocation().add(0,1,0);
for(int k=0;k<12;k++){ double a=(double)k/12*Math.PI*2; for(int h=-1;h<=1;h++){ Location s=hit.clone().add(Math.cos(a)*0.5,h*0.25,Math.sin(a)*0.5); s.getWorld().spawnParticle(Particle.SNOWFLAKE,s,1,0.02,0.02,0.02,0); } } hit.getWorld().spawnParticle(Particle.SNOWFLAKE,hit,8,0.3,0.3,0.3,0.1); hit.getWorld().playSound(hit,Sound.BLOCK_GLASS_BREAK,1f,0.7f); for(int k=0;k<12;k++){ double a=(double)k/12*Math.PI*2; for(int h=-1;h<=1;h++){ Location s=hit.clone().add(Math.cos(a)*0.5,h*0.25,Math.sin(a)*0.5); s.getWorld().spawnParticle(Particle.SNOWFLAKE,s,1,0.02,0.02,0.02,0); } } hit.getWorld().spawnParticle(Particle.SNOWFLAKE,hit,8,0.3,0.3,0.3,0.1); hit.getWorld().playSound(hit,Sound.BLOCK_GLASS_BREAK,1f,0.7f);
le.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.SLOWNESS,40,1,false,false,true)); le.addPotionEffect(new org.bukkit.potion.PotionEffect(org.bukkit.potion.PotionEffectType.SLOWNESS,40,1,false,false,true));
@@ -0,0 +1,80 @@
package me.sashegdev.blackknife;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.entity.BlockDisplay;
import org.bukkit.entity.Display;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
public class PhantomBarrageAttack {
public static boolean tryUse(Player p, TensionManager tension) {
if (tension.getTP(p) < 100f) { p.sendActionBar(Component.text("Need 40% TP").color(NamedTextColor.RED)); return false; }
tension.setTP(p, tension.getTP(p) - 100f);
Location center = p.getLocation().add(0,1,0);
BlackKnifePlugin plugin = BlackKnifePlugin.getPlugin(BlackKnifePlugin.class);
p.getWorld().playSound(center, Sound.ENTITY_PHANTOM_AMBIENT, 1f, 0.6f);
p.getWorld().playSound(center, Sound.BLOCK_BEACON_ACTIVATE, 1f, 1.4f);
for (int i=0;i<5;i++) {
double angle = (double)i/5 * Math.PI*2;
final double fa = angle;
Location spawn = center.clone().add(Math.cos(angle)*2, Math.sin(angle*2)*0.5, Math.sin(angle)*2);
BlockDisplay orb = p.getWorld().spawn(spawn, BlockDisplay.class, d -> {
d.setBlock(Material.SCULK_CATALYST.createBlockData());
d.setBrightness(new Display.Brightness(15,15));
d.setViewRange(64);
d.setTransformation(new org.bukkit.util.Transformation(new org.joml.Vector3f(-0.35f,-0.35f,-0.35f),new org.joml.AxisAngle4f(),new org.joml.Vector3f(0.7f,0.7f,0.7f),new org.joml.AxisAngle4f()));
});
EntityTracker.mark(orb);
new BukkitRunnable() {
int ticks = 0;
Location cur = spawn.clone();
Vector dir = new Vector(-Math.sin(fa), 0, Math.cos(fa)).normalize().multiply(0.35);
@Override public void run() {
if (!orb.isValid() || orb.isDead()) { cancel(); return; }
if (ticks < 30) {
cur = cur.clone().add(dir);
dir = new Vector(-Math.sin(fa + ticks*0.15), 0, Math.cos(fa + ticks*0.15)).normalize().multiply(0.35);
orb.teleport(cur);
cur.getWorld().spawnParticle(Particle.SCULK_SOUL, cur,1,0.05,0.05,0.05,0);
cur.getWorld().spawnParticle(Particle.ASH, cur,1,0,0,0,0);
ticks++;
return;
}
if (ticks == 30) {
cur.getWorld().playSound(cur, Sound.ENTITY_PHANTOM_FLAP, 1f, 1.2f);
}
Location target = getGazeTarget(p);
if (target == null) target = p.getEyeLocation().add(p.getEyeLocation().getDirection().normalize().multiply(25));
Vector toTarget = target.clone().subtract(cur).toVector().normalize().multiply(1.6);
Location nl = cur.clone().add(toTarget);
int steps = Math.max(1,(int)Math.ceil(toTarget.length()/0.5));
for(int s=0;s<=steps;s++){ Location check=cur.clone().add(toTarget.clone().multiply((double)s/steps)); if(check.getBlock().isSolid()){orb.remove();cancel();return;} }
orb.teleport(nl);
cur = nl;
nl.getWorld().spawnParticle(Particle.DUST, nl,1,0,0,0,0,new Particle.DustOptions(Color.fromRGB(30,10,50),1.2f));
nl.getWorld().spawnParticle(Particle.SCULK_SOUL, nl,1,0.05,0.05,0.05,0);
for(LivingEntity le: nl.getWorld().getNearbyLivingEntities(nl,0.9)){ if(le==p) continue; DamageUtil.apply(p, le, 6.0); le.getWorld().spawnParticle(Particle.CRIT, le.getLocation().add(0,1,0),8,0.3,0.3,0.3,0.1); orb.remove(); cancel(); return; }
for(Player pl: nl.getWorld().getNearbyPlayers(nl,0.9)){ if(pl==p) continue; double d2=pl.getLocation().add(0,1,0).distanceSquared(nl); if(d2>0.25 && d2<0.81) plugin.getTension().addTP(pl,2.5f,"DODGE +1%"); }
if(cur.distanceSquared(target) < 1 || orb.getTicksLived() > 100){ orb.remove(); cancel(); }
ticks++;
}
}.runTaskTimer(plugin,1L,1L);
}
return true;
}
private static Location getGazeTarget(Player p){
var ray = p.getWorld().rayTraceBlocks(p.getEyeLocation(), p.getEyeLocation().getDirection(), 40);
if(ray!=null && ray.getHitPosition()!=null) return new Location(p.getWorld(), ray.getHitPosition().getX(), ray.getHitPosition().getY(), ray.getHitPosition().getZ());
return null;
}
}
@@ -70,8 +70,7 @@ public class SwordAttack {
marker.teleport(nl); marker.teleport(nl);
for (var ent : nl.getWorld().getNearbyEntities(nl, 0.7, 0.7, 0.7, e -> e instanceof LivingEntity && e != p)) { for (var ent : nl.getWorld().getNearbyEntities(nl, 0.7, 0.7, 0.7, e -> e instanceof LivingEntity && e != p)) {
LivingEntity le = (LivingEntity) ent; LivingEntity le = (LivingEntity) ent;
le.getPersistentDataContainer().set(SwoonHandler.MAGIC_DAMAGE, PersistentDataType.BYTE, (byte) 1); DamageUtil.apply(p, le, 15.0);
le.damage(15.0, p);
Location hit = le.getLocation().add(0, 1, 0); Location hit = le.getLocation().add(0, 1, 0);
for (int k = 0; k < 12; k++) { for (int k = 0; k < 12; k++) {
double a = (double) k / 12 * Math.PI * 2; double a = (double) k / 12 * Math.PI * 2;