fix DIVE: allow creative, feedback messages, segment hit sampling; tune GRENADE faster flight + 10t cd
This commit is contained in:
@@ -169,7 +169,7 @@ public class BlackKnifeListener implements Listener {
|
||||
}
|
||||
} else if (m.equals("GRENADE")) {
|
||||
if (GrenadeAttack.tryUse(p, tm)) {
|
||||
p.setCooldown(item.getType(), 15);
|
||||
p.setCooldown(item.getType(), 10);
|
||||
}
|
||||
} else if (m.equals("DIVE")) {
|
||||
if (SkyDiveAttack.tryUse(p, tm)) {
|
||||
|
||||
@@ -24,6 +24,8 @@ public class GrenadeAttack {
|
||||
private static final double LETHAL_DAMAGE = 35.0;
|
||||
private static final double CHIP_DAMAGE = 5.5;
|
||||
private static final double MAX_RANGE = 15.0;
|
||||
private static final double TICKS_PER_BLOCK = 2.0;
|
||||
private static final int MIN_DURATION = 8;
|
||||
private static final double ARC_MIN = 1.5;
|
||||
private static final double ARC_PER_BLOCK = 0.25;
|
||||
private static final double ARC_MAX = 4.0;
|
||||
@@ -39,7 +41,7 @@ public class GrenadeAttack {
|
||||
Vector dir = eye.getDirection().normalize();
|
||||
Location target = computeTarget(p, eye, dir);
|
||||
double dist = eye.distance(target);
|
||||
int duration = Math.max(10, (int) (dist * 3));
|
||||
int duration = Math.max(MIN_DURATION, (int) (dist * TICKS_PER_BLOCK));
|
||||
double arcH = Math.max(ARC_MIN, Math.min(ARC_MAX, dist * ARC_PER_BLOCK));
|
||||
Location spawn = eye.clone().add(dir.clone().multiply(1)).add(0, 0.2, 0);
|
||||
Vector throwDir = target.clone().subtract(spawn).toVector().normalize();
|
||||
@@ -133,7 +135,7 @@ public class GrenadeAttack {
|
||||
flightStart = cur.clone();
|
||||
flightTarget = nt.clone();
|
||||
double remaining = Math.max(1.0, cur.distance(nt));
|
||||
flightDuration = Math.max(6, (int) (remaining * 3));
|
||||
flightDuration = Math.max(6, (int) (remaining * TICKS_PER_BLOCK));
|
||||
elapsed = 0;
|
||||
arc = Math.max(ARC_MIN, Math.min(ARC_MAX, remaining * ARC_PER_BLOCK));
|
||||
targetWasSolid = flightTarget.getBlock().isSolid();
|
||||
|
||||
@@ -37,8 +37,14 @@ public class SkyDiveAttack implements Listener {
|
||||
private static final Map<UUID, Boolean> diving = new ConcurrentHashMap<>();
|
||||
|
||||
public static boolean tryUse(Player p, TensionManager tension) {
|
||||
if (SwoonHandler.isSwooned(p)) return false;
|
||||
if (p.getGameMode() == GameMode.CREATIVE || p.getGameMode() == GameMode.SPECTATOR) return false;
|
||||
if (SwoonHandler.isSwooned(p)) {
|
||||
p.sendActionBar(Component.text("SWOONED - can't use DIVE").color(NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
if (p.getGameMode() == GameMode.SPECTATOR) {
|
||||
p.sendActionBar(Component.text("Spectators can't use DIVE").color(NamedTextColor.RED));
|
||||
return false;
|
||||
}
|
||||
if (Boolean.TRUE.equals(diving.get(p.getUniqueId()))) {
|
||||
p.sendActionBar(Component.text("Already diving!").color(NamedTextColor.RED));
|
||||
return false;
|
||||
@@ -60,6 +66,7 @@ public class SkyDiveAttack implements Listener {
|
||||
diving.put(p.getUniqueId(), true);
|
||||
p.getWorld().playSound(p.getLocation(), Sound.ENTITY_FIREWORK_ROCKET_LAUNCH, 1f, 0.8f);
|
||||
p.getWorld().spawnParticle(Particle.CLOUD, p.getLocation(), 10, 0.3, 0.2, 0.3, 0.05);
|
||||
p.sendActionBar(Component.text("SkyDive!").color(NamedTextColor.AQUA));
|
||||
|
||||
new BukkitRunnable() {
|
||||
final double startY = p.getLocation().getY();
|
||||
@@ -88,6 +95,7 @@ public class SkyDiveAttack implements Listener {
|
||||
p.setFallDistance(0);
|
||||
frozen.put(p.getUniqueId(), top);
|
||||
p.getWorld().playSound(top, Sound.BLOCK_BEACON_ACTIVATE, 0.8f, 1.4f);
|
||||
p.sendActionBar(Component.text("Aim with your camera!").color(NamedTextColor.AQUA));
|
||||
|
||||
new BukkitRunnable() {
|
||||
long left = FREEZE_TICKS;
|
||||
@@ -125,10 +133,12 @@ public class SkyDiveAttack implements Listener {
|
||||
p.setFallDistance(0);
|
||||
immuneUntil.put(p.getUniqueId(), System.currentTimeMillis() + FALL_IMMUNE_MS);
|
||||
p.getWorld().playSound(p.getLocation(), Sound.ENTITY_ENDER_DRAGON_FLAP, 1f, 1.2f);
|
||||
p.sendActionBar(Component.text("DIVE!").color(NamedTextColor.DARK_RED));
|
||||
|
||||
new BukkitRunnable() {
|
||||
int ticks = 0;
|
||||
boolean hit = false;
|
||||
Location prev = p.getLocation().add(0, 1, 0).clone();
|
||||
|
||||
@Override public void run() {
|
||||
if (!p.isOnline() || p.isDead()) { cleanup(p); cancel(); return; }
|
||||
@@ -139,19 +149,27 @@ public class SkyDiveAttack implements Listener {
|
||||
new Particle.DustOptions(Color.fromRGB(80, 160, 255), 1.4f));
|
||||
cur.getWorld().spawnParticle(Particle.CLOUD, cur, 1, 0.1, 0.1, 0.1, 0.02);
|
||||
|
||||
for (LivingEntity le : cur.getWorld().getNearbyLivingEntities(cur, 1.2)) {
|
||||
if (le == p) continue;
|
||||
if (!DamageUtil.canHurt(p, le)) continue;
|
||||
DamageUtil.apply(p, le, DAMAGE);
|
||||
Vector kb = dir.clone().multiply(1.2);
|
||||
kb.setY(kb.getY() + 0.4);
|
||||
le.setVelocity(kb);
|
||||
le.getWorld().spawnParticle(Particle.CRIT, le.getLocation().add(0, 1, 0), 12, 0.4, 0.4, 0.4, 0.1);
|
||||
le.getWorld().playSound(le.getLocation(), Sound.ENTITY_PLAYER_ATTACK_CRIT, 1f, 0.8f);
|
||||
plugin.getTension().startBattle(p, le);
|
||||
hit = true;
|
||||
break;
|
||||
// Семплируем весь пройденный за тик отрезок, иначе на скорости 2.8 цель проскакивает между тиками
|
||||
Vector seg = cur.clone().subtract(prev).toVector();
|
||||
double len = seg.length();
|
||||
int steps = Math.max(1, (int) Math.ceil(len / 0.5));
|
||||
for (int s = 0; s <= steps && !hit; s++) {
|
||||
Location check = prev.clone().add(seg.clone().multiply((double) s / steps));
|
||||
for (LivingEntity le : check.getWorld().getNearbyLivingEntities(check, 1.2)) {
|
||||
if (le == p) continue;
|
||||
if (!DamageUtil.canHurt(p, le)) continue;
|
||||
DamageUtil.apply(p, le, DAMAGE);
|
||||
Vector kb = dir.clone().multiply(1.2);
|
||||
kb.setY(kb.getY() + 0.4);
|
||||
le.setVelocity(kb);
|
||||
le.getWorld().spawnParticle(Particle.CRIT, le.getLocation().add(0, 1, 0), 12, 0.4, 0.4, 0.4, 0.1);
|
||||
le.getWorld().playSound(le.getLocation(), Sound.ENTITY_PLAYER_ATTACK_CRIT, 1f, 0.8f);
|
||||
plugin.getTension().startBattle(p, le);
|
||||
hit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prev = cur.clone();
|
||||
if (hit) { finish(); return; }
|
||||
Location ahead = p.getEyeLocation().add(dir.clone().multiply(1.0));
|
||||
if (ahead.getBlock().isSolid()) { finish(); return; }
|
||||
|
||||
Reference in New Issue
Block a user