mirror of
https://github.com/TotalFreedomMC/TF-ProjectKorra.git
synced 2024-05-16 01:41:22 +00:00
102112ffdd
## Fixes * Fixed Combos and possibly Passives appearing in `/pk b <Ability>` auto-tabbing. * Fixed Combos not loading properly on certain servers. * Fixed issue with `PreciousStones` by updating to the latest version to resolve API change issues. * Fixed `RapidPunch` damage. * Fixed incorrect summation of chiblocking chance. * Fixed possible issue in PKListener#onPlayerInteraction() * Fixed `Earth.LavaSound`. * Fixed Chi attempting to chiblock targets with any move. * Fixed hitting an entity with `TempArmor` not ignoring armor. * Fixed `Immobilize` config path. ## Additions * Added "Contributing" section to the `README` to help guide active community members. * Added more detail to the `PULL_REQUEST_TEMPLATE` to allow for more uniform pull requests. * Added many new blocks to our ability block interaction. * Added check to combo collisions to discard dead entities. * Added functionality to allow chiblocking abilities to affect all entities. * Added exception handling to the configurable `Sound` options to prevent `IllegalArgumentExcpetions`. * Added sounds and `ActionBar` messages to being Bloodbent, Electrocuted, Immobilized, MetalClipped, and Paralyzed. (Abilities: `Bloodbending`, `Lightning`, `Immobilize`, `MetalClips`, and `Paralyze`) * Added sound and `ActionBar` message for being Chiblocked. * Added interval config option to `RapidPunch`. (time between each punch) ## API Changes * Updated to `Spigot 1.12.1`. * Confirmed to be backward compatible with `Spigot 1.12` and `Spigot 1.11.2`. * Renamed `ElementalAbility#getTransparentMaterial()` to `ElementalAbility#getTransparentMaterials()`. * Converted most `byte`/`int` dependent `Material` logic to use `Material` instead. * `ElementalAbility#getTransparentMaterialSet()` now returns a `HashSet<Material>` instead of a `HashSet<Byte>`. * `ElementalAbility#getTransparentMaterials()` and `GeneralMethods.NON_OPAQUE` now return `Material[]` instead of `Integer[]`. * `GeneralMethods#getTargetedLocation()` now takes a `varargs Material[]` instead of a `varargs Integer[]`. * Removed `ElementalAbility.TRANSPARENT_MATERIAL`. It was outdated and became irrelevent after `GeneralMethods.NON_OPAQUE` was updated. * Removed `Java 7` Travi-CI JDK check. * Updated `pom.xml` to build in `Java 8`. * Added new `MovementHandler` utility class to control entity movement. (currently only capable of stopping movement.
650 lines
21 KiB
Java
650 lines
21 KiB
Java
package com.projectkorra.projectkorra.airbending;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import org.bukkit.Location;
|
|
import org.bukkit.entity.Entity;
|
|
import org.bukkit.entity.LivingEntity;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.potion.PotionEffect;
|
|
import org.bukkit.potion.PotionEffectType;
|
|
import org.bukkit.scheduler.BukkitRunnable;
|
|
|
|
import com.projectkorra.projectkorra.GeneralMethods;
|
|
import com.projectkorra.projectkorra.ProjectKorra;
|
|
import com.projectkorra.projectkorra.ability.AirAbility;
|
|
import com.projectkorra.projectkorra.attribute.Attribute;
|
|
import com.projectkorra.projectkorra.util.DamageHandler;
|
|
|
|
/**
|
|
* Suffocate
|
|
*
|
|
* Suffocate is an air ability that causes entities to be surrounded by a sphere
|
|
* air that causes constant damage after a configurable delay. Suffocate also
|
|
* causes Blinding and Slowing affects to entities depending on how the ability
|
|
* is configured. While in AvatarState this ability can be used on multiple
|
|
* entities within a large radius. If the user is damaged while performing this
|
|
* ability then the ability is removed.
|
|
*/
|
|
public class Suffocate extends AirAbility {
|
|
|
|
public static enum SpiralType {
|
|
HORIZONTAL1, HORIZONTAL2, VERTICAL1, VERTICAL2, DIAGONAL1, DIAGONAL2
|
|
};
|
|
|
|
private boolean started;
|
|
private boolean requireConstantAim;
|
|
private boolean canSuffocateUndead;
|
|
private int particleCount;
|
|
@Attribute(Attribute.CHARGE_DURATION)
|
|
private long chargeTime;
|
|
@Attribute(Attribute.COOLDOWN)
|
|
private long cooldown;
|
|
@Attribute(Attribute.RANGE)
|
|
private double range;
|
|
@Attribute(Attribute.RADIUS)
|
|
private double radius;
|
|
@Attribute(Attribute.DAMAGE)
|
|
private double damage;
|
|
private double damageDelay;
|
|
private double damageRepeat;
|
|
private double slow;
|
|
private double slowRepeat;
|
|
private double slowDelay;
|
|
private double constantAimRadius;
|
|
private double blind;
|
|
private double blindDelay;
|
|
private double blindRepeat;
|
|
private double animationSpeed;
|
|
private Suffocate ability;
|
|
private ArrayList<BukkitRunnable> tasks;
|
|
private ArrayList<LivingEntity> targets;
|
|
|
|
public Suffocate(Player player) {
|
|
super(player);
|
|
ability = this;
|
|
if (bPlayer.isOnCooldown(this)) {
|
|
return;
|
|
} else if (hasAbility(player, Suffocate.class)) {
|
|
return;
|
|
}
|
|
|
|
this.started = false;
|
|
this.requireConstantAim = getConfig().getBoolean("Abilities.Air.Suffocate.RequireConstantAim");
|
|
this.canSuffocateUndead = getConfig().getBoolean("Abilities.Air.Suffocate.CanBeUsedOnUndeadMobs");
|
|
this.particleCount = getConfig().getInt("Abilities.Air.Suffocate.AnimationParticleAmount");
|
|
this.animationSpeed = getConfig().getDouble("Abilities.Air.Suffocate.AnimationSpeed");
|
|
this.chargeTime = getConfig().getLong("Abilities.Air.Suffocate.ChargeTime");
|
|
this.cooldown = getConfig().getLong("Abilities.Air.Suffocate.Cooldown");
|
|
this.range = getConfig().getDouble("Abilities.Air.Suffocate.Range");
|
|
this.radius = getConfig().getDouble("Abilities.Air.Suffocate.AnimationRadius");
|
|
this.constantAimRadius = getConfig().getDouble("Abilities.Air.Suffocate.RequireConstantAimRadius");
|
|
this.damage = getConfig().getDouble("Abilities.Air.Suffocate.Damage");
|
|
this.damageDelay = getConfig().getDouble("Abilities.Air.Suffocate.DamageInitialDelay");
|
|
this.damageRepeat = getConfig().getDouble("Abilities.Air.Suffocate.DamageInterval");
|
|
this.slow = getConfig().getInt("Abilities.Air.Suffocate.SlowPotency");
|
|
this.slowRepeat = getConfig().getDouble("Abilities.Air.Suffocate.SlowInterval");
|
|
this.slowDelay = getConfig().getDouble("Abilities.Air.Suffocate.SlowDelay");
|
|
this.blind = getConfig().getInt("Abilities.Air.Suffocate.BlindPotentcy");
|
|
this.blindDelay = getConfig().getDouble("Abilities.Air.Suffocate.BlindDelay");
|
|
this.blindRepeat = getConfig().getDouble("Abilities.Air.Suffocate.BlindInterval");
|
|
this.targets = new ArrayList<>();
|
|
this.tasks = new ArrayList<>();
|
|
|
|
if (bPlayer.isAvatarState()) {
|
|
cooldown = getConfig().getLong("Abilities.Avatar.AvatarState.Air.Suffocate.Cooldown");
|
|
chargeTime = getConfig().getLong("Abilities.Avatar.AvatarState.Air.Suffocate.ChargeTime");
|
|
damage = getConfig().getDouble("Abilities.Avatar.AvatarState.Air.Suffocate.Damage");
|
|
range = getConfig().getDouble("Abilities.Avatar.AvatarState.Air.Suffocate.Range");
|
|
|
|
}
|
|
|
|
if (particleCount < 1) {
|
|
particleCount = 1;
|
|
} else if (particleCount > 2) {
|
|
particleCount = 2;
|
|
}
|
|
|
|
if (bPlayer.isAvatarState()) {
|
|
for (Entity ent : GeneralMethods.getEntitiesAroundPoint(player.getLocation(), range)) {
|
|
if (ent instanceof LivingEntity && !ent.equals(player)) {
|
|
targets.add((LivingEntity) ent);
|
|
}
|
|
}
|
|
} else {
|
|
//Location location = GeneralMethods.getTargetedLocation(player, 6, getTransparentMaterial());
|
|
//List<Entity> entities = GeneralMethods.getEntitiesAroundPoint(location, 1.5);
|
|
List<Entity> entities = new ArrayList<Entity>();
|
|
for (int i = 0; i < 6; i++) {
|
|
Location location = GeneralMethods.getTargetedLocation(player, i, getTransparentMaterials());
|
|
entities = GeneralMethods.getEntitiesAroundPoint(location, 1.7);
|
|
if (entities.contains(player))
|
|
entities.remove(player);
|
|
if (entities != null && !entities.isEmpty() && !entities.contains(player)) {
|
|
break;
|
|
}
|
|
}
|
|
if (entities == null || entities.isEmpty()) {
|
|
return;
|
|
}
|
|
Entity target = entities.get(0);
|
|
if (target != null && target instanceof LivingEntity) {
|
|
targets.add((LivingEntity) target);
|
|
}
|
|
}
|
|
|
|
if (!canSuffocateUndead) {
|
|
for (int i = 0; i < targets.size(); i++) {
|
|
LivingEntity target = targets.get(i);
|
|
if (GeneralMethods.isUndead(target)) {
|
|
targets.remove(i);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
bPlayer.addCooldown(this);
|
|
start();
|
|
}
|
|
|
|
@Override
|
|
public void progress() {
|
|
for (int i = 0; i < targets.size(); i++) {
|
|
LivingEntity target = targets.get(i);
|
|
if (target.isDead() || !target.getWorld().equals(player.getWorld()) || target.getLocation().distanceSquared(player.getEyeLocation()) > range * range || GeneralMethods.isRegionProtectedFromBuild(this, target.getLocation())) {
|
|
breakSuffocateLocal(target);
|
|
i--;
|
|
} else if (target instanceof Player) {
|
|
Player targPlayer = (Player) target;
|
|
if (!targPlayer.isOnline()) {
|
|
breakSuffocateLocal(target);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
if (targets.size() == 0 || !bPlayer.canBendIgnoreCooldowns(this)) {
|
|
remove();
|
|
return;
|
|
}
|
|
|
|
if (requireConstantAim) {
|
|
double dist = 0;
|
|
if (player.getWorld().equals(targets.get(0).getWorld())) {
|
|
dist = player.getEyeLocation().distance(targets.get(0).getEyeLocation());
|
|
}
|
|
Location targetLoc = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().normalize().multiply(dist));
|
|
List<Entity> ents = GeneralMethods.getEntitiesAroundPoint(targetLoc, constantAimRadius);
|
|
|
|
for (int i = 0; i < targets.size(); i++) {
|
|
LivingEntity target = targets.get(i);
|
|
if (!ents.contains(target)) {
|
|
breakSuffocateLocal(target);
|
|
i--;
|
|
}
|
|
}
|
|
if (targets.size() == 0) {
|
|
remove();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (System.currentTimeMillis() - getStartTime() < chargeTime) {
|
|
return;
|
|
} else if (!started) {
|
|
started = true;
|
|
for (LivingEntity targ : targets) {
|
|
final LivingEntity target = targ;
|
|
BukkitRunnable br1 = new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
DamageHandler.damageEntity(target, damage, ability);
|
|
}
|
|
};
|
|
BukkitRunnable br2 = new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
target.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, (int) (slowRepeat * 20), (int) slow));
|
|
}
|
|
};
|
|
BukkitRunnable br3 = new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, (int) (blindRepeat * 20), (int) blind));
|
|
}
|
|
};
|
|
|
|
tasks.add(br1);
|
|
tasks.add(br2);
|
|
tasks.add(br3);
|
|
br1.runTaskTimer(ProjectKorra.plugin, (long) (damageDelay * 20), (long) (damageRepeat * 20));
|
|
br2.runTaskTimer(ProjectKorra.plugin, (long) (slowDelay * 20), (long) (slowRepeat * 20 / 0.25));
|
|
br3.runTaskTimer(ProjectKorra.plugin, (long) (blindDelay * 20), (long) (blindRepeat * 20));
|
|
}
|
|
}
|
|
|
|
animate();
|
|
if (!player.isSneaking()) {
|
|
remove();
|
|
return;
|
|
}
|
|
}
|
|
|
|
/** Stops an entity from being suffocated **/
|
|
public static void breakSuffocate(Entity entity) {
|
|
for (Suffocate suffocate : getAbilities(Suffocate.class)) {
|
|
if (suffocate.targets.contains(entity)) {
|
|
suffocate.breakSuffocateLocal(entity);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Checks if an entity is being suffocated **/
|
|
public static boolean isBreathbent(Entity entity) {
|
|
for (Suffocate suffocate : getAbilities(Suffocate.class)) {
|
|
if (suffocate.targets.contains(entity)) {
|
|
return suffocate.started;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/** Determines if a player is Suffocating entities **/
|
|
public static boolean isChannelingSphere(Player player) {
|
|
return hasAbility(player, Suffocate.class);
|
|
}
|
|
|
|
/**
|
|
* Removes an instance of Suffocate if player is the one suffocating
|
|
* entities
|
|
**/
|
|
public static void remove(Player player) {
|
|
Suffocate suff = getAbility(player, Suffocate.class);
|
|
if (suff != null) {
|
|
suff.remove();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes all instances of Suffocate at loc within the radius threshold.
|
|
* The location of a Suffocate is defined at the benders location, not the
|
|
* location of the entities being suffocated.
|
|
*
|
|
* @param causer The player causing this instance to be removed
|
|
**/
|
|
public static boolean removeAtLocation(Player causer, Location loc, double radius) {
|
|
if (causer == null) {
|
|
return false;
|
|
}
|
|
for (Suffocate suff : getAbilities(Suffocate.class)) {
|
|
if (!suff.player.equals(causer)) {
|
|
Location playerLoc = suff.getPlayer().getLocation();
|
|
if (playerLoc.getWorld().equals(loc.getWorld()) && playerLoc.distanceSquared(loc) <= radius * radius) {
|
|
suff.remove();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Animates this instance of the Suffocate ability. Depending on the
|
|
* specific time (dt) the ability will create a different set of
|
|
* SuffocationSpirals.
|
|
*/
|
|
public void animate() {
|
|
int steps = 8 * particleCount;
|
|
long curTime = System.currentTimeMillis();
|
|
long dt = curTime - getStartTime() - chargeTime;
|
|
long delay = 2 / particleCount;
|
|
long t1 = (long) (1500 * animationSpeed);
|
|
long t2 = (long) (2500 * animationSpeed);
|
|
long t3 = (long) (5000 * animationSpeed);
|
|
long t4 = (long) (6000 * animationSpeed);
|
|
for (LivingEntity lent : targets) {
|
|
final LivingEntity target = lent;
|
|
if (dt < t1) {
|
|
new SuffocateSpiral(target, steps, radius, delay, 0, 0.25 - (0.25 * (double) dt / (double) t1), 0, SpiralType.HORIZONTAL1);
|
|
new SuffocateSpiral(target, steps, radius, delay, 0, 0.25 - (0.25 * (double) dt / (double) t1), 0, SpiralType.HORIZONTAL2);
|
|
} else if (dt < t2) {
|
|
new SuffocateSpiral(target, steps, radius, delay, 0, 0, 0, SpiralType.HORIZONTAL1);
|
|
new SuffocateSpiral(target, steps * 2, radius, delay, 0, 0, 0, SpiralType.VERTICAL1);
|
|
new SuffocateSpiral(target, steps * 2, radius, delay, 0, 0, 0, SpiralType.VERTICAL2);
|
|
} else if (dt < t3) {
|
|
new SuffocateSpiral(target, steps, radius, delay, 0, 0, 0, SpiralType.HORIZONTAL1);
|
|
new SuffocateSpiral(target, steps, radius, delay, 0, 0, 0, SpiralType.VERTICAL1);
|
|
new SuffocateSpiral(target, steps, radius, delay, 0, 0, 0, SpiralType.VERTICAL2);
|
|
} else if (dt < t4) {
|
|
new SuffocateSpiral(target, steps, radius - Math.min(radius * 3 / 4, (radius * 3.0 / 4 * ((double) (dt - t3) / (double) (t4 - t3)))), delay, 0, 0, 0, SpiralType.HORIZONTAL1);
|
|
new SuffocateSpiral(target, steps, radius - Math.min(radius * 3 / 4, (radius * 3.0 / 4 * ((double) (dt - t3) / (double) (t4 - t3)))), delay, 0, 0, 0, SpiralType.VERTICAL1);
|
|
new SuffocateSpiral(target, steps, radius - Math.min(radius * 3 / 4, (radius * 3.0 / 4 * ((double) (dt - t3) / (double) (t4 - t3)))), delay, 0, 0, 0, SpiralType.VERTICAL2);
|
|
} else {
|
|
new SuffocateSpiral(target, steps, radius - (radius * 3.0 / 4.0), delay, 0, 0, 0, SpiralType.HORIZONTAL1);
|
|
new SuffocateSpiral(target, steps, radius - (radius * 3.0 / 4.0), delay, 0, 0, 0, SpiralType.VERTICAL1);
|
|
new SuffocateSpiral(target, steps, radius - (radius * 3.0 / 4.0), delay, 0, 0, 0, SpiralType.VERTICAL2);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Stops an entity from being suffocated **/
|
|
public void breakSuffocateLocal(Entity entity) {
|
|
if (targets.contains(entity)) {
|
|
targets.remove(entity);
|
|
}
|
|
}
|
|
|
|
/** Removes this instance of the ability **/
|
|
@Override
|
|
public void remove() {
|
|
super.remove();
|
|
for (int i = 0; i < tasks.size(); i++) {
|
|
tasks.get(i).cancel();
|
|
tasks.remove(i);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Animates a Spiral of air particles around a location or a targetted
|
|
* entity. The direction of the spiral is determined by SpiralType, and each
|
|
* type is calculated independently from one another.
|
|
*/
|
|
public class SuffocateSpiral extends BukkitRunnable {
|
|
private Location startLoc;
|
|
private Location loc;
|
|
private LivingEntity target;
|
|
private int totalSteps;
|
|
private double radius;
|
|
private double dx, dy, dz;
|
|
private SpiralType type;
|
|
private int i;
|
|
|
|
/**
|
|
* @param lent The entity to animate the spiral around
|
|
* @param totalSteps Amount of times it will be animated
|
|
* @param radius The radius of the spiral
|
|
* @param interval The speed of the animation
|
|
* @param dx x offset
|
|
* @param dy y offset
|
|
* @param dz z offset
|
|
* @param type Spiral animation direction
|
|
*/
|
|
public SuffocateSpiral(LivingEntity lent, int totalSteps, double radius, long interval, double dx, double dy, double dz, SpiralType type) {
|
|
this.target = lent;
|
|
this.totalSteps = totalSteps;
|
|
this.radius = radius;
|
|
this.dx = dx;
|
|
this.dy = dy;
|
|
this.dz = dz;
|
|
this.type = type;
|
|
this.loc = target.getEyeLocation();
|
|
this.i = 0;
|
|
this.runTaskTimer(ProjectKorra.plugin, 0L, interval);
|
|
tasks.add(this);
|
|
}
|
|
|
|
/**
|
|
* @param startLoc Initial location
|
|
* @param totalSteps Amount of times it will be animated
|
|
* @param radius The radius of the spiral
|
|
* @param interval The speed of the animation
|
|
* @param dx x offset
|
|
* @param dy y offset
|
|
* @param dz z offset
|
|
* @param type Spiral animation direction
|
|
*/
|
|
public SuffocateSpiral(Location startLoc, int totalSteps, double radius, long interval, double dx, double dy, double dz, SpiralType type) {
|
|
this.startLoc = startLoc;
|
|
this.totalSteps = totalSteps;
|
|
this.radius = radius;
|
|
this.dx = dx;
|
|
this.dy = dy;
|
|
this.dz = dz;
|
|
this.type = type;
|
|
this.loc = startLoc.clone();
|
|
this.i = 0;
|
|
this.runTaskTimer(ProjectKorra.plugin, 0L, interval);
|
|
tasks.add(this);
|
|
}
|
|
|
|
/**
|
|
* Starts the initial animation, and removes itself when it is finished.
|
|
*/
|
|
public void run() {
|
|
Location tempLoc;
|
|
if (target != null) {
|
|
tempLoc = target.getEyeLocation();
|
|
tempLoc.setY(tempLoc.getY() - 0.5);
|
|
} else {
|
|
tempLoc = startLoc.clone();
|
|
}
|
|
|
|
if (type == SpiralType.HORIZONTAL1) {
|
|
loc.setX(tempLoc.getX() + radius * Math.cos(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
loc.setY(tempLoc.getY() + dy * i);
|
|
loc.setZ(tempLoc.getZ() + radius * Math.sin(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
} else if (type == SpiralType.HORIZONTAL2) {
|
|
loc.setX(tempLoc.getX() + radius * -Math.cos(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
loc.setY(tempLoc.getY() + dy * i);
|
|
loc.setZ(tempLoc.getZ() + radius * -Math.sin(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
} else if (type == SpiralType.VERTICAL1) {
|
|
loc.setX(tempLoc.getX() + radius * Math.sin(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
loc.setY(tempLoc.getY() + radius * Math.cos(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
loc.setZ(tempLoc.getZ() + dz * i);
|
|
} else if (type == SpiralType.VERTICAL2) {
|
|
loc.setX(tempLoc.getX() + dx * i);
|
|
loc.setY(tempLoc.getY() + radius * Math.sin(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
loc.setZ(tempLoc.getZ() + radius * Math.cos(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
} else if (type == SpiralType.DIAGONAL1) {
|
|
loc.setX(tempLoc.getX() + radius * Math.cos(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
loc.setY(tempLoc.getY() + radius * Math.sin(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
loc.setZ(tempLoc.getZ() + radius * -Math.cos(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
} else if (type == SpiralType.DIAGONAL2) {
|
|
loc.setX(tempLoc.getX() + radius * Math.cos(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
loc.setY(tempLoc.getY() + radius * Math.sin(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
loc.setZ(tempLoc.getZ() + radius * Math.cos(Math.toRadians((double) i / (double) totalSteps * 360)));
|
|
}
|
|
|
|
getAirbendingParticles().display(loc, (float) 0, (float) 0, (float) 0, 0, 1);
|
|
if (i == totalSteps + 1) {
|
|
this.cancel();
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return "Suffocate";
|
|
}
|
|
|
|
@Override
|
|
public Location getLocation() {
|
|
if (targets.size() > 0) {
|
|
return targets.get(0).getLocation();
|
|
} else if (player != null) {
|
|
return player.getLocation();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public long getCooldown() {
|
|
return cooldown;
|
|
}
|
|
|
|
@Override
|
|
public boolean isSneakAbility() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isHarmlessAbility() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public List<Location> getLocations() {
|
|
ArrayList<Location> locations = new ArrayList<>();
|
|
locations.add(player.getLocation());
|
|
return locations;
|
|
}
|
|
|
|
public boolean isStarted() {
|
|
return started;
|
|
}
|
|
|
|
public void setStarted(boolean started) {
|
|
this.started = started;
|
|
}
|
|
|
|
public boolean isRequireConstantAim() {
|
|
return requireConstantAim;
|
|
}
|
|
|
|
public void setRequireConstantAim(boolean requireConstantAim) {
|
|
this.requireConstantAim = requireConstantAim;
|
|
}
|
|
|
|
public boolean isCanSuffocateUndead() {
|
|
return canSuffocateUndead;
|
|
}
|
|
|
|
public void setCanSuffocateUndead(boolean canSuffocateUndead) {
|
|
this.canSuffocateUndead = canSuffocateUndead;
|
|
}
|
|
|
|
public int getParticleCount() {
|
|
return particleCount;
|
|
}
|
|
|
|
public void setParticleCount(int particleCount) {
|
|
this.particleCount = particleCount;
|
|
}
|
|
|
|
public long getChargeTime() {
|
|
return chargeTime;
|
|
}
|
|
|
|
public void setChargeTime(long chargeTime) {
|
|
this.chargeTime = chargeTime;
|
|
}
|
|
|
|
public double getRange() {
|
|
return range;
|
|
}
|
|
|
|
public void setRange(double range) {
|
|
this.range = range;
|
|
}
|
|
|
|
public double getRadius() {
|
|
return radius;
|
|
}
|
|
|
|
public void setRadius(double radius) {
|
|
this.radius = radius;
|
|
}
|
|
|
|
public double getDamage() {
|
|
return damage;
|
|
}
|
|
|
|
public void setDamage(double damage) {
|
|
this.damage = damage;
|
|
}
|
|
|
|
public double getDamageDelay() {
|
|
return damageDelay;
|
|
}
|
|
|
|
public void setDamageDelay(double damageDelay) {
|
|
this.damageDelay = damageDelay;
|
|
}
|
|
|
|
public double getDamageRepeat() {
|
|
return damageRepeat;
|
|
}
|
|
|
|
public void setDamageRepeat(double damageRepeat) {
|
|
this.damageRepeat = damageRepeat;
|
|
}
|
|
|
|
public double getSlow() {
|
|
return slow;
|
|
}
|
|
|
|
public void setSlow(double slow) {
|
|
this.slow = slow;
|
|
}
|
|
|
|
public double getSlowRepeat() {
|
|
return slowRepeat;
|
|
}
|
|
|
|
public void setSlowRepeat(double slowRepeat) {
|
|
this.slowRepeat = slowRepeat;
|
|
}
|
|
|
|
public double getSlowDelay() {
|
|
return slowDelay;
|
|
}
|
|
|
|
public void setSlowDelay(double slowDelay) {
|
|
this.slowDelay = slowDelay;
|
|
}
|
|
|
|
public double getConstantAimRadius() {
|
|
return constantAimRadius;
|
|
}
|
|
|
|
public void setConstantAimRadius(double constantAimRadius) {
|
|
this.constantAimRadius = constantAimRadius;
|
|
}
|
|
|
|
public double getBlind() {
|
|
return blind;
|
|
}
|
|
|
|
public void setBlind(double blind) {
|
|
this.blind = blind;
|
|
}
|
|
|
|
public double getBlindDelay() {
|
|
return blindDelay;
|
|
}
|
|
|
|
public void setBlindDelay(double blindDelay) {
|
|
this.blindDelay = blindDelay;
|
|
}
|
|
|
|
public double getBlindRepeat() {
|
|
return blindRepeat;
|
|
}
|
|
|
|
public void setBlindRepeat(double blindRepeat) {
|
|
this.blindRepeat = blindRepeat;
|
|
}
|
|
|
|
public double getAnimationSpeed() {
|
|
return animationSpeed;
|
|
}
|
|
|
|
public void setAnimationSpeed(double animationSpeed) {
|
|
this.animationSpeed = animationSpeed;
|
|
}
|
|
|
|
public ArrayList<BukkitRunnable> getTasks() {
|
|
return tasks;
|
|
}
|
|
|
|
public ArrayList<LivingEntity> getTargets() {
|
|
return targets;
|
|
}
|
|
|
|
public void setCooldown(long cooldown) {
|
|
this.cooldown = cooldown;
|
|
}
|
|
}
|