diff --git a/src/com/projectkorra/ProjectKorra/BendingManager.java b/src/com/projectkorra/ProjectKorra/BendingManager.java index 64a3cfe3..b8d45abc 100644 --- a/src/com/projectkorra/ProjectKorra/BendingManager.java +++ b/src/com/projectkorra/ProjectKorra/BendingManager.java @@ -15,6 +15,7 @@ import com.projectkorra.ProjectKorra.Ability.AvatarState; import com.projectkorra.ProjectKorra.airbending.AirBlast; import com.projectkorra.ProjectKorra.airbending.AirBurst; import com.projectkorra.ProjectKorra.airbending.AirPassive; +import com.projectkorra.ProjectKorra.airbending.AirScooter; import com.projectkorra.ProjectKorra.airbending.Tornado; import com.projectkorra.ProjectKorra.chiblocking.ChiPassive; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; @@ -65,6 +66,7 @@ public class BendingManager implements Runnable { handleDayNight(); Bloodbending.progressAll(); FireJet.progressAll(); + AirScooter.progressAll(); for (int ID: Tornado.instances.keySet()) { Tornado.progress(ID); diff --git a/src/com/projectkorra/ProjectKorra/ConfigManager.java b/src/com/projectkorra/ProjectKorra/ConfigManager.java index 78cea93a..5433900e 100644 --- a/src/com/projectkorra/ProjectKorra/ConfigManager.java +++ b/src/com/projectkorra/ProjectKorra/ConfigManager.java @@ -81,6 +81,14 @@ public class ConfigManager { + "Additionally, having this ability selected when you land on the ground from a " + "large enough fall will create a burst of air around you."); + config.addDefault("Abilities.Air.AirScooter.Enabled", true); + config.addDefault("Abilities.Air.AirScooter.Description", "AirScooter is a fast means of transportation. To use, sprint, jump then click with " + + "this ability selected. You will hop on a scooter of air and be propelled forward " + + "in the direction you're looking (you don't need to press anything). " + + "This ability can be used to levitate above liquids, but it cannot go up steep slopes. " + + "Any other actions will deactivate this ability."); + config.addDefault("Abilities.Air.AirScooter.Speed", .675); + plugin.getConfig().addDefault("Abilities.Air.Tornado.Enabled", true); plugin.getConfig().addDefault("Abilities.Air.Tornado.Description", "To use, simply sneak (default: shift). " + "This will create a swirling vortex at the targeted location. " diff --git a/src/com/projectkorra/ProjectKorra/Flight.java b/src/com/projectkorra/ProjectKorra/Flight.java index 15462499..4dee471e 100644 --- a/src/com/projectkorra/ProjectKorra/Flight.java +++ b/src/com/projectkorra/ProjectKorra/Flight.java @@ -7,6 +7,7 @@ import org.bukkit.GameMode; import org.bukkit.entity.Player; import com.projectkorra.ProjectKorra.Ability.AvatarState; +import com.projectkorra.ProjectKorra.airbending.AirScooter; import com.projectkorra.ProjectKorra.airbending.Tornado; import com.projectkorra.ProjectKorra.firebending.FireJet; import com.projectkorra.ProjectKorra.waterbending.Bloodbending; diff --git a/src/com/projectkorra/ProjectKorra/PKListener.java b/src/com/projectkorra/ProjectKorra/PKListener.java index 5a10d483..b10c5f5f 100644 --- a/src/com/projectkorra/ProjectKorra/PKListener.java +++ b/src/com/projectkorra/ProjectKorra/PKListener.java @@ -44,6 +44,7 @@ import org.kitteh.tag.AsyncPlayerReceiveNameTagEvent; import com.projectkorra.ProjectKorra.Ability.AvatarState; import com.projectkorra.ProjectKorra.airbending.AirBlast; import com.projectkorra.ProjectKorra.airbending.AirBurst; +import com.projectkorra.ProjectKorra.airbending.AirScooter; import com.projectkorra.ProjectKorra.airbending.Tornado; import com.projectkorra.ProjectKorra.chiblocking.ChiPassive; import com.projectkorra.ProjectKorra.chiblocking.Paralyze; @@ -273,6 +274,9 @@ public class PKListener implements Listener { if (abil.equalsIgnoreCase("AirBurst")) { AirBurst.coneBurst(player); } + if (abil.equalsIgnoreCase("AirScooter")) { + new AirScooter(player); + } } if (Methods.isWaterAbility(abil)) { if (Methods.isWeapon(player.getItemInHand().getType()) && !plugin.getConfig().getBoolean("Properties.Water.CanBendWithWeapons")) { diff --git a/src/com/projectkorra/ProjectKorra/airbending/AirScooter.java b/src/com/projectkorra/ProjectKorra/airbending/AirScooter.java new file mode 100644 index 00000000..b9a9c16e --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/airbending/AirScooter.java @@ -0,0 +1,182 @@ +package com.projectkorra.ProjectKorra.airbending; + +import java.util.ArrayList; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.Flight; +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.ProjectKorra; + +public class AirScooter { + + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + + private static final double speed = ProjectKorra.plugin.getConfig().getDouble("Abilities.Air.AirScooter.Speed"); + private static final long interval = 100; + private static final double scooterradius = 1; + + private Player player; + private Block floorblock; + private long time; + // private boolean canfly, wasflying; + private ArrayList angles = new ArrayList(); + + public AirScooter(Player player) { +// if (BendingPlayer.getBendingPlayer(player).isOnCooldown( +// Abilities.AirScooter)) +// return; + + if (instances.containsKey(player)) { + instances.get(player).remove(); + return; + } + if (!player.isSprinting() + || Methods.isSolid(player.getEyeLocation().getBlock()) + || player.getEyeLocation().getBlock().isLiquid()) + return; + if (Methods.isSolid(player.getLocation().add(0, -.5, 0).getBlock())) + return; + this.player = player; + // wasflying = player.isFlying(); + // canfly = player.getAllowFlight(); + new Flight(player); + player.setAllowFlight(true); + player.setFlying(true); + player.setSprinting(false); + time = System.currentTimeMillis(); + for (int i = 0; i < 5; i++) { + angles.add((double) (60 * i)); + } + instances.put(player, this); + progress(); + } + + private void progress() { + getFloor(); + // Methods.verbose(player); + if (floorblock == null) { + remove(); + return; + } + if (!Methods.canBend(player.getName(), "AirScooter")) { + remove(); + return; + } + if (!player.isOnline() || player.isDead() || !player.isFlying()) { + remove(); + return; + } + +// if (Methods.isRegionProtectedFromBuild(player, Abilities.AirScooter, +// player.getLocation())) { +// remove(); +// return; +// } + + // if (Methods + // .isSolid(player + // .getEyeLocation() + // .clone() + // .add(player.getEyeLocation().getDirection().clone() + // .normalize()).getBlock())) { + // remove(); + // return; + // } + // player.sendBlockChange(floorblock.getLocation(), 89, (byte) 1); + // player.getLocation().setY((double) floorblock.getY() + 2.5); + + Vector velocity = player.getEyeLocation().getDirection().clone(); + velocity.setY(0); + velocity = velocity.clone().normalize().multiply(speed); + if (System.currentTimeMillis() > time + interval) { + time = System.currentTimeMillis(); + if (player.getVelocity().length() < speed * .5) { + remove(); + return; + } + spinScooter(); + } + double distance = player.getLocation().getY() + - (double) floorblock.getY(); + double dx = Math.abs(distance - 2.4); + if (distance > 2.75) { + velocity.setY(-.25 * dx * dx); + } else if (distance < 2) { + velocity.setY(.25 * dx * dx); + } else { + velocity.setY(0); + } + Location loc = player.getLocation(); + loc.setY((double) floorblock.getY() + 1.5); + // player.setFlying(true); + // player.teleport(loc.add(velocity)); + player.setSprinting(false); + player.removePotionEffect(PotionEffectType.SPEED); + player.setVelocity(velocity); + } + + private void spinScooter() { + Location origin = player.getLocation().clone(); + origin.add(0, -scooterradius, 0); + for (int i = 0; i < 5; i++) { + double x = Math.cos(Math.toRadians(angles.get(i))) * scooterradius; + double y = ((double) i) / 2 * scooterradius - scooterradius; + double z = Math.sin(Math.toRadians(angles.get(i))) * scooterradius; + player.getWorld().playEffect(origin.clone().add(x, y, z), + Effect.SMOKE, 4, (int) AirBlast.defaultrange); + } + for (int i = 0; i < 5; i++) { + angles.set(i, angles.get(i) + 10); + } + } + + private void getFloor() { + floorblock = null; + for (int i = 0; i <= 7; i++) { + Block block = player.getEyeLocation().getBlock() + .getRelative(BlockFace.DOWN, i); + if (Methods.isSolid(block) || block.isLiquid()) { + floorblock = block; + return; + } + } + } + + private void remove() { + instances.remove(player); + } + + public static void check(Player player) { + if (instances.containsKey(player)) { + instances.get(player).remove(); + } + } + + public static void progressAll() { + for (Player player : instances.keySet()) { + instances.get(player).progress(); + } + } + + public static void removeAll() { + for (Player player : instances.keySet()) { + instances.get(player).remove(); + } + } + + public static ArrayList getPlayers() { + ArrayList players = new ArrayList(); + for (Player player : instances.keySet()) { + players.add(player); + } + return players; + } +} \ No newline at end of file diff --git a/src/config.yml b/src/config.yml index 7f9edfd8..0f3e3d09 100644 --- a/src/config.yml +++ b/src/config.yml @@ -54,6 +54,10 @@ Abilities: AirBurst: Enabled: true Description: "AirBurst is one of the most powerful abilities in an airbender's arsenal. To use, press and hold sneak to charge your burst. Once charged, you can either release sneak to launch a cone-shaped burst of air in front of you, or click to release theb urst in a sphere around you. Additionally, having this ability selected when you land on the ground from a large enough fall will create a burst of air around you." + AirScooter: + Enabled: true + Description: "AirScooter is a fast means of transportation. To use, sprint, jump then click with this ability selected. YOu will hop on a scooter of air and be propelled forward in the direction you're looking (you don't need to press anything). This ability can be used to levitate above liquids, but it cannot go up steep slopes. Any other actions will deactivate this ability." + Speed: 0.675 Tornado: Enabled: true Description: "To use, simply sneak (default: shift). This will create a swirling vortex at the targeted lcoation. Any creature or object caught in the vortex will be launched up and out in some random direction. If another player gets caught in the vortex, the launching effect is minimal. Tornado can also be used to transport the user. If the user gets caught in his/her own tornado, his/her movements are much more manageable. Provided the user doesn't fall out of the vortex, it will take him to a maximum height and move him in the general direction he/she is looking. Skilled airbenders can scale anything with this ability."