From ead0c812d142bef8b1824877a290960e93961cca Mon Sep 17 00:00:00 2001 From: MistPhizzle Date: Tue, 24 Jun 2014 18:39:33 -0400 Subject: [PATCH] Tornado and AirBlast --- .classpath | 2 - .../ProjectKorra/BendingManager.java | 6 + .../ProjectKorra/ConfigManager.java | 35 +- src/com/projectkorra/ProjectKorra/Flight.java | 1 + .../projectkorra/ProjectKorra/Methods.java | 11 +- .../projectkorra/ProjectKorra/PKListener.java | 42 +- .../ProjectKorra/airbending/AirBlast.java | 358 ++++++++++++++++++ .../ProjectKorra/airbending/Tornado.java | 214 +++++++++++ src/config.yml | 18 + 9 files changed, 677 insertions(+), 10 deletions(-) create mode 100644 src/com/projectkorra/ProjectKorra/airbending/AirBlast.java create mode 100644 src/com/projectkorra/ProjectKorra/airbending/Tornado.java diff --git a/.classpath b/.classpath index 4cb7da63..e713abef 100644 --- a/.classpath +++ b/.classpath @@ -4,7 +4,5 @@ - - diff --git a/src/com/projectkorra/ProjectKorra/BendingManager.java b/src/com/projectkorra/ProjectKorra/BendingManager.java index 27a14280..4b15148f 100644 --- a/src/com/projectkorra/ProjectKorra/BendingManager.java +++ b/src/com/projectkorra/ProjectKorra/BendingManager.java @@ -12,7 +12,9 @@ import org.bukkit.block.Block; import org.bukkit.entity.Player; import com.projectkorra.ProjectKorra.Ability.AvatarState; +import com.projectkorra.ProjectKorra.airbending.AirBlast; import com.projectkorra.ProjectKorra.airbending.AirPassive; +import com.projectkorra.ProjectKorra.airbending.Tornado; import com.projectkorra.ProjectKorra.chiblocking.ChiPassive; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; import com.projectkorra.ProjectKorra.firebending.FirePassive; @@ -48,6 +50,7 @@ public class BendingManager implements Runnable { ProjectKorra.time_step = interval; AvatarState.manageAvatarStates(); + AirBlast.progressAll(); AirPassive.handlePassive(Bukkit.getServer()); ChiPassive.handlePassive(); WaterPassive.handlePassive(); @@ -55,6 +58,9 @@ public class BendingManager implements Runnable { EarthPassive.revertSands(); Plantbending.regrow(); handleDayNight(); + for (int ID: Tornado.instances.keySet()) { + Tornado.progress(ID); + } for (int id: FireStream.instances.keySet()) { FireStream.progress(id); diff --git a/src/com/projectkorra/ProjectKorra/ConfigManager.java b/src/com/projectkorra/ProjectKorra/ConfigManager.java index ea1b4073..2ce93e9a 100644 --- a/src/com/projectkorra/ProjectKorra/ConfigManager.java +++ b/src/com/projectkorra/ProjectKorra/ConfigManager.java @@ -2,6 +2,8 @@ package com.projectkorra.ProjectKorra; import java.util.ArrayList; +import org.bukkit.configuration.file.FileConfiguration; + public class ConfigManager { static ProjectKorra plugin; @@ -12,7 +14,9 @@ public class ConfigManager { } public static void configCheck() { - + + FileConfiguration config = ProjectKorra.plugin.getConfig(); + ArrayList earthbendable = new ArrayList(); earthbendable.add("STONE"); earthbendable.add("COAL_ORE"); @@ -56,6 +60,35 @@ public class ConfigManager { plugin.getConfig().addDefault("Abilities.Air.Passive.Speed", 2); plugin.getConfig().addDefault("Abilities.Air.Passive.Jump", 3); + config.addDefault("Abilities.Air.AirBlast.Enabled", true); + config.addDefault("Abilities.Air.AirBlast.Description", "AirBlast is the most fundamental bending technique of an airbender." + + " To use, simply left-click in a direction. A gust of wind will be" + + " created at your fingertips, launching anything in its path harmlessly back." + + " A gust of air can extinguish fires on the ground or on a player, can cool lava, and " + + "can flip levers and activate buttons. Additionally, tapping sneak will change the " + + "origin of your next AirBlast to your targeted location."); + config.addDefault("Abilities.Air.AirBlast.Speed", 25); + config.addDefault("Abilities.Air.AirBlast.Range", 20); + config.addDefault("Abilities.Air.AirBlast.Radius", 2); + config.addDefault("Abilities.Air.AirBlast.Push", 3.5); + + 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. " + + "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 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's looking. Skilled airbenders can scale anything " + + "with this ability."); + config.addDefault("Abilities.Air.Tornado.Radius", 10); + config.addDefault("Abilities.Air.Tornado.Height", 25); + config.addDefault("Abilities.Air.Tornado.Range", 25); + config.addDefault("Abilities.Air.Tornado.MobPushFactor", 1); + config.addDefault("Abilities.Air.Tornado.PlayerPushFactor", 1); + plugin.getConfig().addDefault("Abilities.Water.Passive.SwimSpeedFactor", 0.7); plugin.getConfig().addDefault("Abilities.Water.Plantbending.RegrowTime", 180000); diff --git a/src/com/projectkorra/ProjectKorra/Flight.java b/src/com/projectkorra/ProjectKorra/Flight.java index e8365f68..c36429fd 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.Tornado; public class Flight { diff --git a/src/com/projectkorra/ProjectKorra/Methods.java b/src/com/projectkorra/ProjectKorra/Methods.java index f6cba5ba..50de24af 100644 --- a/src/com/projectkorra/ProjectKorra/Methods.java +++ b/src/com/projectkorra/ProjectKorra/Methods.java @@ -346,7 +346,7 @@ public class Methods { /* * TODO : Checks for WaterManip and other abilities. */ - + if (isWater(block) && blocki.getData() == full) { sources++; } @@ -572,12 +572,11 @@ public class Methods { if (block.getType() == Material.SANDSTONE && info.getType() == Material.SAND) block.setType(Material.SAND); - if (isAbilityInstalled("RaiseEarth", "orion304")) { - if (EarthColumn.blockInAllAffectedBlocks(block)) - EarthColumn.revertBlock(block); + if (EarthColumn.blockInAllAffectedBlocks(block)) + EarthColumn.revertBlock(block); + + EarthColumn.resetBlock(block); - EarthColumn.resetBlock(block); - } movedearth.remove(block); } } diff --git a/src/com/projectkorra/ProjectKorra/PKListener.java b/src/com/projectkorra/ProjectKorra/PKListener.java index 0d5f93f2..5bb1b822 100644 --- a/src/com/projectkorra/ProjectKorra/PKListener.java +++ b/src/com/projectkorra/ProjectKorra/PKListener.java @@ -24,9 +24,12 @@ import org.bukkit.event.player.PlayerAnimationEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerToggleFlightEvent; +import org.bukkit.event.player.PlayerToggleSneakEvent; import org.kitteh.tag.AsyncPlayerReceiveNameTagEvent; import com.projectkorra.ProjectKorra.Ability.AvatarState; +import com.projectkorra.ProjectKorra.airbending.AirBlast; +import com.projectkorra.ProjectKorra.airbending.Tornado; import com.projectkorra.ProjectKorra.chiblocking.ChiPassive; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; import com.projectkorra.ProjectKorra.firebending.Enflamed; @@ -82,6 +85,35 @@ public class PKListener implements Listener { BendingPlayer.players.remove(e.getPlayer().getName()); } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerSneak(PlayerToggleSneakEvent event) { + Player player = event.getPlayer(); + + if (Paralyze.isParaylzed(player) || Bloodbending.isBloodbended(player)) { + event.setCancelled(true); + } + + AirScooter.check(player); + + String abil = Methods.getBoundAbility(player); + if (abil == null) { + return; + } + + if (!player.isSneaking() && Methods.canBend(player.getName(), abil)) { + if (Methods.isAirAbility(abil)) { + if (Methods.isWeapon(player.getItemInHand().getType()) && !plugin.getConfig().getBoolean("Properties.Air.CanBendWithWeapons")) { + return; + } + if (abil == "Tornado") { + new Tornado(player); + } + if (abil == "AirBlast") { + AirBlast.setOrigin(player); + } + } + } + } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onPlayerSwing(PlayerAnimationEvent event) { Player player = event.getPlayer(); @@ -96,12 +128,20 @@ public class PKListener implements Listener { if (abil == "AvatarState") { new AvatarState(player); } + if (Methods.isAirAbility(abil)) { + if (Methods.isWeapon(player.getItemInHand().getType()) && !plugin.getConfig().getBoolean("Properties.Air.CanBendWithWeapons")) { + return; + } + if (abil == "AirBlast") { + new AirBlast(player); + } + } } } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onPlayerToggleFlight(PlayerToggleFlightEvent event) { Player p = event.getPlayer(); - if (Tornado.getplayers().contains(p) || Bloodbending.isBloodbended(p) + if (Tornado.getPlayers().contains(p) || Bloodbending.isBloodbended(p) || FireJet.getPlayers().contains(p) || AvatarState.getPlayers().contains(p)) { event.setCancelled(p.getGameMode() != GameMode.CREATIVE); diff --git a/src/com/projectkorra/ProjectKorra/airbending/AirBlast.java b/src/com/projectkorra/ProjectKorra/airbending/AirBlast.java new file mode 100644 index 00000000..fe71222a --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/airbending/AirBlast.java @@ -0,0 +1,358 @@ +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.Material; +import org.bukkit.block.Block; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.Flight; +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.Ability.AvatarState; + +public class AirBlast { + + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + private static ConcurrentHashMap origins = new ConcurrentHashMap(); + public static ConcurrentHashMap cooldowns = new ConcurrentHashMap(); + // private static ConcurrentHashMap timers = new + // ConcurrentHashMap(); + // static final long soonesttime = Methods.timeinterval; + + private static int ID = Integer.MIN_VALUE; + static final int maxticks = 10000; + + static FileConfiguration config = ProjectKorra.plugin.getConfig(); + + public static double speed = config.getDouble("Abilities.Air.AirBlast.Speed"); + public static double defaultrange = config.getDouble("Abilities.Air.AirBlast.Range"); + public static double affectingradius = config.getDouble("Abilities.Air.AirBlast.Radius"); + public static double defaultpushfactor = config.getDouble("Abilities.Air.AirBlast.Push"); + private static double originselectrange = 10; + static final double maxspeed = 1. / defaultpushfactor; + // public static long interval = 2000; + public static byte full = 0x0; + + private Location location; + private Location origin; + private Vector direction; + private Player player; + private int id; + private double speedfactor; + private double range = defaultrange; + private double pushfactor = defaultpushfactor; + private boolean otherorigin = false; + private int ticks = 0; + + private ArrayList affectedlevers = new ArrayList(); + private ArrayList affectedentities = new ArrayList(); + + private AirBurst source = null; + + // private long time; + + public AirBlast(Player player) { + // if (timers.containsKey(player)) { + // if (System.currentTimeMillis() < timers.get(player) + soonesttime) { + // return; + // } + // } + + if (cooldowns.containsKey(player.getName())) { + if (cooldowns.get(player.getName()) + config.getLong("Properties.GlobalCooldown") >= System.currentTimeMillis()) { + return; + } else { + cooldowns.remove(player.getName()); + } + } + + if (player.getEyeLocation().getBlock().isLiquid()) { + return; + } + // timers.put(player, System.currentTimeMillis()); + this.player = player; + if (origins.containsKey(player)) { + otherorigin = true; + origin = origins.get(player); + origins.remove(player); + Entity entity = Methods.getTargetedEntity(player, range, new ArrayList()); + if (entity != null) { + direction = Methods.getDirection(origin, entity.getLocation()) + .normalize(); + } else { + direction = Methods.getDirection(origin, + Methods.getTargetedLocation(player, range)).normalize(); + } + } else { + origin = player.getEyeLocation(); + direction = player.getEyeLocation().getDirection().normalize(); + } + location = origin.clone(); + id = ID; + instances.put(id, this); + cooldowns.put(player.getName(), System.currentTimeMillis()); + if (ID == Integer.MAX_VALUE) + ID = Integer.MIN_VALUE; + ID++; + // time = System.currentTimeMillis(); + // timers.put(player, System.currentTimeMillis()); + } + + public AirBlast(Location location, Vector direction, Player player, + double factorpush, AirBurst burst) { + if (location.getBlock().isLiquid()) { + return; + } + + source = burst; + + this.player = player; + origin = location.clone(); + this.direction = direction.clone(); + this.location = location.clone(); + id = ID; + pushfactor *= factorpush; + instances.put(id, this); + if (ID == Integer.MAX_VALUE) + ID = Integer.MIN_VALUE; + ID++; + } + + public static void setOrigin(Player player) { + Location location = Methods.getTargetedLocation(player, + originselectrange, Methods.nonOpaque); + if (location.getBlock().isLiquid() + || Methods.isSolid(location.getBlock())) + return; + +// if (Methods.isRegionProtectedFromBuild(player, Abilities.AirBlast, +// location)) +// return; + + if (origins.containsKey(player)) { + origins.replace(player, location); + } else { + origins.put(player, location); + } + } + + public boolean progress() { + if (player.isDead() || !player.isOnline()) { + instances.remove(id); + return false; + } + +// if (Methods.isRegionProtectedFromBuild(player, Abilities.AirBlast, +// location)) { +// instances.remove(id); +// return false; +// } + + speedfactor = speed * (ProjectKorra.time_step / 1000.); + + ticks++; + + if (ticks > maxticks) { + instances.remove(id); + return false; + } + + // if (player.isSneaking() + // && Methods.getBendingAbility(player) == Abilities.AirBlast) { + // new AirBlast(player); + // } + + Block block = location.getBlock(); + for (Block testblock : Methods.getBlocksAroundPoint(location, + affectingradius)) { + if (testblock.getType() == Material.FIRE) { + testblock.setType(Material.AIR); + testblock.getWorld().playEffect(testblock.getLocation(), + Effect.EXTINGUISH, 0); + } + if (((block.getType() == Material.LEVER) || (block.getType() == Material.STONE_BUTTON)) + && !affectedlevers.contains(block)) { + // BlockState state = block.getState(); + // Lever lever = (Lever) (state.getData()); + // lever.setPowered(!lever.isPowered()); + // state.setData(lever); + // state.update(true, true); + // + // Block relative = block.getRelative(((Attachable) block + // .getState().getData()).getFacing(), -1); + // relative.getState().update(true, true); + // + // for (Block block2 : Methods.getBlocksAroundPoint( + // relative.getLocation(), 2)) + // block2.getState().update(true, true); + + affectedlevers.add(block); + } + } + if ((Methods.isSolid(block) || block.isLiquid()) + && !affectedlevers.contains(block)) { + if (block.getType() == Material.LAVA + || block.getType() == Material.STATIONARY_LAVA) { + if (block.getData() == full) { + block.setType(Material.OBSIDIAN); + } else { + block.setType(Material.COBBLESTONE); + } + } + instances.remove(id); + return false; + } + + // Methods.verbose(location.distance(origin)); + if (location.distance(origin) > range) { + // Methods.verbose(id); + instances.remove(id); + return false; + } + + for (Entity entity : Methods.getEntitiesAroundPoint(location, + affectingradius)) { + // if (source == null) { + // if (affectedentities.contains(entity)) + // continue; + // } else { + // if (source.isAffectedEntity(entity)) + // continue; + // } + affect(entity); + } + + advanceLocation(); + + return true; + } + + private void advanceLocation() { + location.getWorld().playEffect(location, Effect.SMOKE, 4, (int) range); + location = location.add(direction.clone().multiply(speedfactor)); + } + + private void affect(Entity entity) { + // if (source == null) + // affectedentities.add(entity); + // else + // source.addAffectedEntity(entity); + boolean isUser = entity.getEntityId() == player.getEntityId(); + + if (!isUser || otherorigin) { + Vector velocity = entity.getVelocity(); + // double mag = Math.abs(velocity.getY()); + double max = maxspeed; + double factor = pushfactor; + if (AvatarState.isAvatarState(player)) { + max = AvatarState.getValue(maxspeed); + factor = AvatarState.getValue(factor); + } + + Vector push = direction.clone(); + if (Math.abs(push.getY()) > max && !isUser) { + if (push.getY() < 0) + push.setY(-max); + else + push.setY(max); + } + + factor *= 1 - location.distance(origin) / (2 * range); + + if (isUser + && Methods.isSolid(player.getLocation().add(0, -.5, 0) + .getBlock())) { + factor *= .5; + } + + double comp = velocity.dot(push.clone().normalize()); + if (comp > factor) { + velocity.multiply(.5); + velocity.add(push + .clone() + .normalize() + .multiply( + velocity.clone().dot(push.clone().normalize()))); + } else if (comp + factor * .5 > factor) { + velocity.add(push.clone().multiply(factor - comp)); + } else { + velocity.add(push.clone().multiply(factor * .5)); + } + + // velocity = + // velocity.clone().add(direction.clone().multiply(factor)); + // double newmag = Math.abs(velocity.getY()); + // if (newmag > mag) { + // if (mag > max) { + // velocity = velocity.clone().multiply(mag / newmag); + // } else if (newmag > max) { + // velocity = velocity.clone().multiply(max / newmag); + // } + // } + // + // velocity.multiply(1 - location.distance(origin) / (2 * range)); + // + // if (entity instanceof Player) + // velocity.multiply(2); + + entity.setVelocity(velocity); + entity.setFallDistance(0); + if (!isUser && entity instanceof Player) { + new Flight((Player) entity, player); + } + if (entity.getFireTicks() > 0) + entity.getWorld().playEffect(entity.getLocation(), + Effect.EXTINGUISH, 0); + entity.setFireTicks(0); + } + } + + public static void progressAll() { + for (int id : instances.keySet()) + instances.get(id).progress(); + for (Player player : origins.keySet()) { + playOriginEffect(player); + } + } + + private static void playOriginEffect(Player player) { + if (!origins.containsKey(player)) + return; + Location origin = origins.get(player); + if (!origin.getWorld().equals(player.getWorld())) { + origins.remove(player); + return; + } + + if (Methods.getBoundAbility(player) == null) { + origins.remove(player); + return; + } + + if (!Methods.getBoundAbility(player).equalsIgnoreCase("AirBlast") || !Methods.canBend(player.getName(), "AirBlast")) { + origins.remove(player); + return; + } + + if (origin.distance(player.getEyeLocation()) > originselectrange) { + origins.remove(player); + return; + } + + origin.getWorld().playEffect(origin, Effect.SMOKE, 4, + (int) originselectrange); + } + + public static void removeAll() { + for (int id : instances.keySet()) { + instances.remove(id); + } + } +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/airbending/Tornado.java b/src/com/projectkorra/ProjectKorra/airbending/Tornado.java new file mode 100644 index 00000000..e39747c8 --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/airbending/Tornado.java @@ -0,0 +1,214 @@ +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.Material; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.Flight; +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.ProjectKorra; + +public class Tornado { + + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + + static FileConfiguration config = ProjectKorra.plugin.getConfig(); + + private static double maxradius = config.getDouble("Abilities.Air.Tornado.Radius"); + private static double maxheight = config.getDouble("Abilities.Air.Tornado.Height"); + private static double range = config.getDouble("Abilities.Air.Tornado.Range"); + private static int numberOfStreams = (int) (.3 * (double) maxheight); + private static double NPCpushfactor = config.getDouble("Abilities.Air.Tornado.MobPushFactor"); + private static double PCpushfactor = config.getDouble("Abilities.Air.Tornado.PlayerPushFactor"); + // private static double speed = .75; + + private double height = 2; + private double radius = height / maxheight * maxradius; + + // private static double speedfactor = 1000 * speed + // * (Bending.time_step / 1000.); + private static double speedfactor = 1; + + private ConcurrentHashMap angles = new ConcurrentHashMap(); + private Location origin; + private Player player; + + // private boolean canfly; + + public Tornado(Player player) { + this.player = player; + // canfly = player.getAllowFlight(); + // player.setAllowFlight(true); + origin = player.getTargetBlock(null, (int) range).getLocation(); + origin.setY(origin.getY() - 1. / 10. * height); + + int angle = 0; + for (int i = 0; i <= maxheight; i += (int) maxheight / numberOfStreams) { + angles.put(i, angle); + angle += 90; + if (angle == 360) + angle = 0; + } + + new Flight(player); + player.setAllowFlight(true); + instances.put(player.getEntityId(), this); + + } + + public boolean progress() { + if (player.isDead() || !player.isOnline()) { + // player.setAllowFlight(canfly); + instances.remove(player.getEntityId()); + return false; + } + if (!Methods.canBend(player.getName(), "Tornado") + || player.getEyeLocation().getBlock().isLiquid()) { + // player.setAllowFlight(canfly); + instances.remove(player.getEntityId()); + return false; + } + String abil = Methods.getBoundAbility(player); + if (abil == null) { + instances.remove(player.getEntityId()); + return false; + } + if (!abil.equalsIgnoreCase("Tornado") || !player.isSneaking()) { + instances.remove(player.getEntityId()); + return false; + } + +// if (Methods +// .isRegionProtectedFromBuild(player, Abilities.AirBlast, origin)) { +// instances.remove(player.getEntityId()); +// return false; +// } + rotateTornado(); + return true; + } + + private void rotateTornado() { + origin = player.getTargetBlock(null, (int) range).getLocation(); + + double timefactor = height / maxheight; + radius = timefactor * maxradius; + + if (origin.getBlock().getType() != Material.AIR) { + origin.setY(origin.getY() - 1. / 10. * height); + + for (Entity entity : Methods.getEntitiesAroundPoint(origin, height)) { +// if (Methods.isRegionProtectedFromBuild(player, +// Abilities.AirBlast, entity.getLocation())) +// continue; + double y = entity.getLocation().getY(); + double factor; + if (y > origin.getY() && y < origin.getY() + height) { + factor = (y - origin.getY()) / height; + Location testloc = new Location(origin.getWorld(), + origin.getX(), y, origin.getZ()); + if (testloc.distance(entity.getLocation()) < radius + * factor) { + double x, z, vx, vz, mag; + double angle = 100; + double vy = 0.7 * NPCpushfactor; + angle = Math.toRadians(angle); + + x = entity.getLocation().getX() - origin.getX(); + z = entity.getLocation().getZ() - origin.getZ(); + + mag = Math.sqrt(x * x + z * z); + + 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 * PCpushfactor; + } + + if (entity.getEntityId() == player.getEntityId()) { + Vector direction = player.getEyeLocation() + .getDirection().clone().normalize(); + vx = direction.getX(); + vz = direction.getZ(); + Location playerloc = player.getLocation(); + double py = playerloc.getY(); + double oy = origin.getY(); + double dy = py - oy; + if (dy >= height * .95) { + vy = 0; + } else if (dy >= height * .85) { + vy = 6.0 * (.95 - dy / height); + } else { + vy = .6; + } + } + + Vector velocity = entity.getVelocity(); + velocity.setX(vx); + velocity.setZ(vz); + velocity.setY(vy); + velocity.multiply(timefactor); + entity.setVelocity(velocity); + entity.setFallDistance(0); + + if (entity instanceof Player) { + new Flight((Player) entity); + } + } + } + } + + for (int i : angles.keySet()) { + double x, y, z; + double angle = (double) angles.get(i); + angle = Math.toRadians(angle); + double factor; + + y = origin.getY() + timefactor * (double) i; + factor = (double) i / height; + + x = origin.getX() + timefactor * factor * radius + * Math.cos(angle); + z = origin.getZ() + timefactor * factor * radius + * Math.sin(angle); + + Location effect = new Location(origin.getWorld(), x, y, z); + // if (!Methods.isRegionProtectedFromBuild(player, + // Abilities.AirBlast, effect)) + origin.getWorld().playEffect(effect, Effect.SMOKE, 4, + (int) AirBlast.defaultrange); + + angles.put(i, angles.get(i) + 25 * (int) speedfactor); + } + } + + if (height < maxheight) { + height += 1; + } + + if (height > maxheight) { + height = maxheight; + } + + } + + public static boolean progress(int ID) { + return instances.get(ID).progress(); + } + + public static ArrayList getPlayers() { + ArrayList players = new ArrayList(); + for (int id : instances.keySet()) { + players.add(instances.get(id).player); + } + return players; + } + +} \ No newline at end of file diff --git a/src/config.yml b/src/config.yml index 85caf24f..4bdc6c1f 100644 --- a/src/config.yml +++ b/src/config.yml @@ -36,11 +36,29 @@ Properties: Chi: CanBendWithWeapons: false Abilities: + AvatarState: + Enabled: true + Description: "The signature ability of the Avatar, this is a toggle. Click to activate to become nearly unstoppable. While in the Avatar State, the user takes severely reduced damage from all sources, regenreates health rapidly, and is granted extreme speed. Nearly all abilities are incredibly amplified in this state. Additionally, AirShield and FireJet become toggle-able abilities and last until you deactivate them or the Avatar State. Click again with the Avatar State selected to deactivate it." Air: Passive: Factor: 0.3 Speed: 2 Jump: 3 + AirBlast: + Enabled: true + Description: "AirBlast is the most fundamental bending technique of an airbender. To use, simply left-click in a direction. A gust of wind will be created at your fingertips, launching anything in its path harmlessly back. A gust of air can extinguish fires on the ground or on a player, can cool lava, and can flip levers and activate buttons. Additionally, tapping sneak will change the original of your next AirBlast to your targeted location." + Speed: 25 + Range: 20 + Radius: 2 + Push: 3.5 + 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." + Radius: 10 + Height: 25 + Range: 25 + MobPushFactor: 1 + PlayerPushFactor: 1 Water: Passive: SwimSpeedFactor: 0.7