mirror of
https://github.com/TotalFreedomMC/TF-ProjectKorra.git
synced 2024-05-15 17:31:26 +00:00
0b35fb9fda
Created a cancellable event that will fire whenever a bending move would alter the velocity of an entity. ## Additions * Adds 1. > The AbilityVelocityAffectEntityEvent > Adds a new method to GeneralMethods -> setEntityVelocity() > Updates existing setVelocity() calls to use the new method in general methods. > checks to see if anything in the event should be modified or if it should be cancelled. ## Fixes * Fixes 2 > The lack of a way to detect when a bending move pushed a player.
326 lines
9.4 KiB
Java
326 lines
9.4 KiB
Java
package com.projectkorra.projectkorra.airbending;
|
|
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.Random;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.entity.Entity;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.util.Vector;
|
|
|
|
import com.projectkorra.projectkorra.GeneralMethods;
|
|
import com.projectkorra.projectkorra.ability.AirAbility;
|
|
import com.projectkorra.projectkorra.ability.ElementalAbility;
|
|
import com.projectkorra.projectkorra.attribute.Attribute;
|
|
import com.projectkorra.projectkorra.command.Commands;
|
|
|
|
public class Tornado extends AirAbility {
|
|
|
|
@Attribute(Attribute.COOLDOWN)
|
|
private final long cooldown;
|
|
@Attribute(Attribute.DURATION)
|
|
private final long duration;
|
|
private int numberOfStreams;
|
|
private int particleCount;
|
|
@Attribute(Attribute.SPEED)
|
|
private double speed;
|
|
@Attribute(Attribute.HEIGHT)
|
|
private double maxHeight;
|
|
@Attribute(Attribute.KNOCKBACK)
|
|
private double playerPushFactor;
|
|
@Attribute(Attribute.RADIUS)
|
|
private double radius;
|
|
@Attribute(Attribute.RANGE)
|
|
private double range;
|
|
private double npcPushFactor;
|
|
private double currentHeight;
|
|
private double currentRadius;
|
|
private Location origin;
|
|
private final Random random;
|
|
private final Map<Integer, Integer> angles;
|
|
|
|
public Tornado(final Player player) {
|
|
super(player);
|
|
|
|
this.cooldown = getConfig().getLong("Abilities.Air.Tornado.Cooldown");
|
|
this.duration = getConfig().getLong("Abilities.Air.Tornado.Duration");
|
|
this.range = getConfig().getDouble("Abilities.Air.Tornado.Range");
|
|
this.origin = player.getTargetBlock((HashSet<Material>) null, (int) this.range).getLocation();
|
|
this.origin.setY(this.origin.getY() - 1.0 / 10.0 * this.currentHeight);
|
|
this.maxHeight = getConfig().getDouble("Abilities.Air.Tornado.Height");
|
|
this.playerPushFactor = getConfig().getDouble("Abilities.Air.Tornado.PlayerPushFactor");
|
|
this.radius = getConfig().getDouble("Abilities.Air.Tornado.Radius");
|
|
this.npcPushFactor = getConfig().getDouble("Abilities.Air.Tornado.NpcPushFactor");
|
|
this.speed = getConfig().getDouble("Abilities.Air.Tornado.Speed");
|
|
this.numberOfStreams = (int) (.3 * this.maxHeight);
|
|
this.currentHeight = 2;
|
|
this.currentRadius = this.currentHeight / this.maxHeight * this.radius;
|
|
this.random = new Random();
|
|
this.angles = new ConcurrentHashMap<>();
|
|
|
|
int angle = 0;
|
|
for (int i = 0; i <= this.maxHeight; i += (int) this.maxHeight / this.numberOfStreams) {
|
|
this.angles.put(i, angle);
|
|
angle += 90;
|
|
if (angle == 360) {
|
|
angle = 0;
|
|
}
|
|
}
|
|
|
|
this.flightHandler.createInstance(player, this.getName());
|
|
player.setAllowFlight(true);
|
|
this.start();
|
|
}
|
|
|
|
@Override
|
|
public void progress() {
|
|
if (this.player.getEyeLocation().getBlock().isLiquid() || !this.player.isSneaking() || !this.bPlayer.canBend(this)) {
|
|
this.bPlayer.addCooldown(this);
|
|
this.remove();
|
|
return;
|
|
} else if (GeneralMethods.isRegionProtectedFromBuild(this, this.origin)) {
|
|
this.remove();
|
|
return;
|
|
} else if (this.duration != 0) {
|
|
if (this.getStartTime() + this.duration <= System.currentTimeMillis()) {
|
|
this.bPlayer.addCooldown(this);
|
|
this.remove();
|
|
return;
|
|
}
|
|
}
|
|
this.rotateTornado();
|
|
}
|
|
|
|
@Override
|
|
public void remove() {
|
|
super.remove();
|
|
this.flightHandler.removeInstance(this.player, this.getName());
|
|
}
|
|
|
|
private void rotateTornado() {
|
|
this.origin = this.player.getTargetBlock((HashSet<Material>) null, (int) this.range).getLocation();
|
|
final double timefactor = this.currentHeight / this.maxHeight;
|
|
this.currentRadius = timefactor * this.radius;
|
|
|
|
if (!ElementalAbility.isAir(this.origin.getBlock().getType()) && this.origin.getBlock().getType() != Material.BARRIER) {
|
|
this.origin.setY(this.origin.getY() - 1. / 10. * this.currentHeight);
|
|
|
|
for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(this.origin, this.currentHeight)) {
|
|
if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation())) {
|
|
continue;
|
|
}
|
|
final double y = entity.getLocation().getY();
|
|
double factor;
|
|
if (y > this.origin.getY() && y < this.origin.getY() + this.currentHeight) {
|
|
factor = (y - this.origin.getY()) / this.currentHeight;
|
|
final Location testloc = new Location(this.origin.getWorld(), this.origin.getX(), y, this.origin.getZ());
|
|
if (testloc.getWorld().equals(entity.getWorld()) && testloc.distance(entity.getLocation()) < this.currentRadius * factor) {
|
|
double x, z, vx, vz, mag;
|
|
double angle = 100;
|
|
double vy = 0.7 * this.npcPushFactor;
|
|
angle = Math.toRadians(angle);
|
|
|
|
x = entity.getLocation().getX() - this.origin.getX();
|
|
z = entity.getLocation().getZ() - this.origin.getZ();
|
|
|
|
mag = Math.sqrt(x * x + z * z);
|
|
|
|
if (mag == 0.0) {
|
|
vx = 0.0;
|
|
vz = 0.0;
|
|
} else {
|
|
vx = (x * Math.cos(angle) - z * Math.sin(angle)) / mag;
|
|
vz = (x * Math.sin(angle) + z * Math.cos(angle)) / mag;
|
|
}
|
|
|
|
if (entity instanceof Player) {
|
|
vy = 0.05 * this.playerPushFactor;
|
|
}
|
|
|
|
if (entity.getEntityId() == this.player.getEntityId()) {
|
|
final Vector direction = this.player.getEyeLocation().getDirection().clone().normalize();
|
|
vx = direction.getX();
|
|
vz = direction.getZ();
|
|
final Location playerloc = this.player.getLocation();
|
|
final double py = playerloc.getY();
|
|
final double oy = this.origin.getY();
|
|
final double dy = py - oy;
|
|
|
|
if (dy >= this.currentHeight * .95) {
|
|
vy = 0;
|
|
} else if (dy >= this.currentHeight * .85) {
|
|
vy = 6.0 * (.95 - dy / this.currentHeight);
|
|
} else {
|
|
vy = .6;
|
|
}
|
|
}
|
|
|
|
if (entity instanceof Player) {
|
|
if (Commands.invincible.contains(((Player) entity).getName())) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
final Vector velocity = entity.getVelocity().clone();
|
|
velocity.setX(vx);
|
|
velocity.setZ(vz);
|
|
velocity.setY(vy);
|
|
velocity.multiply(timefactor);
|
|
GeneralMethods.setVelocity(this, entity, velocity);
|
|
entity.setFallDistance(0);
|
|
|
|
breakBreathbendingHold(entity);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (final int i : this.angles.keySet()) {
|
|
double x, y, z, factor;
|
|
double angle = this.angles.get(i);
|
|
angle = Math.toRadians(angle);
|
|
|
|
y = this.origin.getY() + timefactor * i;
|
|
factor = i / this.currentHeight;
|
|
|
|
x = this.origin.getX() + timefactor * factor * this.currentRadius * Math.cos(angle);
|
|
z = this.origin.getZ() + timefactor * factor * this.currentRadius * Math.sin(angle);
|
|
|
|
final Location effect = new Location(this.origin.getWorld(), x, y, z);
|
|
if (!GeneralMethods.isRegionProtectedFromBuild(this, effect)) {
|
|
playAirbendingParticles(effect, this.particleCount);
|
|
if (this.random.nextInt(20) == 0) {
|
|
playAirbendingSound(effect);
|
|
}
|
|
}
|
|
this.angles.put(i, this.angles.get(i) + 25 * (int) this.speed);
|
|
}
|
|
}
|
|
this.currentHeight = this.currentHeight > this.maxHeight ? this.maxHeight : this.currentHeight + 1;
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return "Tornado";
|
|
}
|
|
|
|
@Override
|
|
public Location getLocation() {
|
|
return this.player != null ? this.player.getLocation() : null;
|
|
}
|
|
|
|
@Override
|
|
public long getCooldown() {
|
|
return this.cooldown;
|
|
}
|
|
|
|
@Override
|
|
public boolean isSneakAbility() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isHarmlessAbility() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public double getCollisionRadius() {
|
|
return this.getRadius();
|
|
}
|
|
|
|
public Location getOrigin() {
|
|
return this.origin;
|
|
}
|
|
|
|
public void setOrigin(final Location origin) {
|
|
this.origin = origin;
|
|
}
|
|
|
|
public int getNumberOfStreams() {
|
|
return this.numberOfStreams;
|
|
}
|
|
|
|
public void setNumberOfStreams(final int numberOfStreams) {
|
|
this.numberOfStreams = numberOfStreams;
|
|
}
|
|
|
|
public int getParticleCount() {
|
|
return this.particleCount;
|
|
}
|
|
|
|
public void setParticleCount(final int particleCount) {
|
|
this.particleCount = particleCount;
|
|
}
|
|
|
|
public double getSpeed() {
|
|
return this.speed;
|
|
}
|
|
|
|
public void setSpeed(final double speed) {
|
|
this.speed = speed;
|
|
}
|
|
|
|
public double getMaxHeight() {
|
|
return this.maxHeight;
|
|
}
|
|
|
|
public void setMaxHeight(final double maxHeight) {
|
|
this.maxHeight = maxHeight;
|
|
}
|
|
|
|
public double getPlayerPushFactor() {
|
|
return this.playerPushFactor;
|
|
}
|
|
|
|
public void setPlayerPushFactor(final double playerPushFactor) {
|
|
this.playerPushFactor = playerPushFactor;
|
|
}
|
|
|
|
public double getRadius() {
|
|
return this.radius;
|
|
}
|
|
|
|
public void setRadius(final double radius) {
|
|
this.radius = radius;
|
|
}
|
|
|
|
public double getRange() {
|
|
return this.range;
|
|
}
|
|
|
|
public void setRange(final double range) {
|
|
this.range = range;
|
|
}
|
|
|
|
public double getNpcPushFactor() {
|
|
return this.npcPushFactor;
|
|
}
|
|
|
|
public void setNpcPushFactor(final double npcPushFactor) {
|
|
this.npcPushFactor = npcPushFactor;
|
|
}
|
|
|
|
public double getCurrentHeight() {
|
|
return this.currentHeight;
|
|
}
|
|
|
|
public void setCurrentHeight(final double currentHeight) {
|
|
this.currentHeight = currentHeight;
|
|
}
|
|
|
|
public double getCurrentRadius() {
|
|
return this.currentRadius;
|
|
}
|
|
|
|
public void setCurrentRadius(final double currentRadius) {
|
|
this.currentRadius = currentRadius;
|
|
}
|
|
|
|
public Map<Integer, Integer> getAngles() {
|
|
return this.angles;
|
|
}
|
|
}
|