From 0da85ee86a7d23896f8ce43867517485bb88f778 Mon Sep 17 00:00:00 2001 From: MistPhizzle Date: Wed, 25 Jun 2014 11:44:02 -0400 Subject: [PATCH] Catapult --- .../ProjectKorra/BendingManager.java | 5 + .../ProjectKorra/ConfigManager.java | 11 + src/com/projectkorra/ProjectKorra/Flight.java | 1 + .../projectkorra/ProjectKorra/Methods.java | 193 +++++++++++++- .../projectkorra/ProjectKorra/PKListener.java | 10 + .../ProjectKorra/earthbending/Catapult.java | 245 ++++++++++++++++++ src/config.yml | 6 + 7 files changed, 469 insertions(+), 2 deletions(-) create mode 100644 src/com/projectkorra/ProjectKorra/earthbending/Catapult.java diff --git a/src/com/projectkorra/ProjectKorra/BendingManager.java b/src/com/projectkorra/ProjectKorra/BendingManager.java index 5b39995f..149ad273 100644 --- a/src/com/projectkorra/ProjectKorra/BendingManager.java +++ b/src/com/projectkorra/ProjectKorra/BendingManager.java @@ -19,6 +19,7 @@ import com.projectkorra.ProjectKorra.airbending.AirScooter; import com.projectkorra.ProjectKorra.airbending.AirSpout; import com.projectkorra.ProjectKorra.airbending.Tornado; import com.projectkorra.ProjectKorra.chiblocking.ChiPassive; +import com.projectkorra.ProjectKorra.earthbending.Catapult; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; import com.projectkorra.ProjectKorra.firebending.FireJet; import com.projectkorra.ProjectKorra.firebending.FirePassive; @@ -85,6 +86,10 @@ public class BendingManager implements Runnable { } } + for (int ID: Catapult.instances.keySet()) { + Catapult.progress(ID); + } + FireStream.dissipateAll(); } catch (Exception e) { Methods.stopBending(); diff --git a/src/com/projectkorra/ProjectKorra/ConfigManager.java b/src/com/projectkorra/ProjectKorra/ConfigManager.java index 19d4cb90..5a3dc60b 100644 --- a/src/com/projectkorra/ProjectKorra/ConfigManager.java +++ b/src/com/projectkorra/ProjectKorra/ConfigManager.java @@ -137,6 +137,17 @@ public class ConfigManager { config.addDefault("Abilities.Water.WaterSpout.Height", 20); plugin.getConfig().addDefault("Abilities.Earth.Passive.Duration", 2500); + + config.addDefault("Abilities.Earth.Catapult.Enabled", true); + config.addDefault("Abilities.Earth.Catapult.Description", "To use, left-click while looking in the direction you want to be launched. " + + "A pillar of earth will jut up from under you and launch you in that direction - " + + "if and only if there is enough earth behind where you're looking to launch you. " + + "Skillful use of this ability takes much time and work, and it does result in the " + + "death of certain gung-ho earthbenders. If you plan to use this ability, be sure " + + "you've read about your passive ability you innately have as an earthbender."); + config.addDefault("Abilities.Earth.Catapult.Length", 7); + config.addDefault("Abilities.Earth.Catapult.Speed", 12); + config.addDefault("Abilities.Earth.Catapult.Push", 5); config.addDefault("Abilities.Fire.FireJet.Enabled", true); config.addDefault("Abilities.Fire.FireJet.Description", "This ability is used for a limited burst of flight for firebenders. Clicking with this " diff --git a/src/com/projectkorra/ProjectKorra/Flight.java b/src/com/projectkorra/ProjectKorra/Flight.java index db7c987d..8390d513 100644 --- a/src/com/projectkorra/ProjectKorra/Flight.java +++ b/src/com/projectkorra/ProjectKorra/Flight.java @@ -10,6 +10,7 @@ import com.projectkorra.ProjectKorra.Ability.AvatarState; import com.projectkorra.ProjectKorra.airbending.AirScooter; import com.projectkorra.ProjectKorra.airbending.AirSpout; import com.projectkorra.ProjectKorra.airbending.Tornado; +import com.projectkorra.ProjectKorra.earthbending.Catapult; import com.projectkorra.ProjectKorra.firebending.FireJet; import com.projectkorra.ProjectKorra.waterbending.Bloodbending; import com.projectkorra.ProjectKorra.waterbending.WaterSpout; diff --git a/src/com/projectkorra/ProjectKorra/Methods.java b/src/com/projectkorra/ProjectKorra/Methods.java index c7d8bc8b..4b3658a4 100644 --- a/src/com/projectkorra/ProjectKorra/Methods.java +++ b/src/com/projectkorra/ProjectKorra/Methods.java @@ -22,6 +22,7 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityDamageByEntityEvent; @@ -35,8 +36,6 @@ import com.projectkorra.ProjectKorra.Ability.AvatarState; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; import com.projectkorra.ProjectKorra.waterbending.FreezeMelt; import com.projectkorra.ProjectKorra.waterbending.WaterCore; -import com.projectkorra.abilities.RaiseEarth.EarthColumn; -import com.projectkorra.abilities.Surge.Surge; public class Methods { @@ -491,6 +490,22 @@ public class Methods { return null; } + public static int getEarthbendableBlocksLength(Player player, Block block, + Vector direction, int maxlength) { + Location location = block.getLocation(); + direction = direction.normalize(); + double j; + for (int i = 0; i <= maxlength; i++) { + j = (double) i; + if (!isEarthbendable(player, + location.clone().add(direction.clone().multiply(j)) + .getBlock())) { + return i; + } + } + return maxlength; + } + public static boolean isMeltable(Block block) { if (block.getType() == Material.ICE || block.getType() == Material.SNOW || block.getType() == Material.PACKED_ICE) { return true; @@ -627,6 +642,180 @@ public class Methods { return true; } + public static void moveEarth(Player player, Location location, + Vector direction, int chainlength) { + moveEarth(player, location, direction, chainlength, true); + } + + public static void moveEarth(Player player, Location location, + Vector direction, int chainlength, boolean throwplayer) { + Block block = location.getBlock(); + moveEarth(player, block, direction, chainlength, throwplayer); + } + + public static void moveEarth(Player player, Block block, Vector direction, + int chainlength) { + moveEarth(player, block, direction, chainlength, true); + } + + public static boolean moveEarth(Player player, Block block, + Vector direction, int chainlength, boolean throwplayer) { + if (isEarthbendable(player, block)) { +// && !isRegionProtectedFromBuild(player, Abilities.RaiseEarth, +// block.getLocation())) { + + boolean up = false; + boolean down = false; + Vector norm = direction.clone().normalize(); + if (norm.dot(new Vector(0, 1, 0)) == 1) { + up = true; + } else if (norm.dot(new Vector(0, -1, 0)) == 1) { + down = true; + } + Vector negnorm = norm.clone().multiply(-1); + + Location location = block.getLocation(); + + ArrayList blocks = new ArrayList(); + for (double j = -2; j <= chainlength; j++) { + Block checkblock = location.clone() + .add(negnorm.clone().multiply(j)).getBlock(); + if (!tempnophysics.contains(checkblock)) { + blocks.add(checkblock); + tempnophysics.add(checkblock); + } + } + + Block affectedblock = location.clone().add(norm).getBlock(); + if (EarthPassive.isPassiveSand(block)) { + EarthPassive.revertSand(block); + } + // if (block.getType() == Material.SAND) { + // block.setType(Material.SANDSTONE); + // } + + if (affectedblock == null) + return false; + if (isTransparentToEarthbending(player, affectedblock)) { + if (throwplayer) { + for (Entity entity : getEntitiesAroundPoint( + affectedblock.getLocation(), 1.75)) { + if (entity instanceof LivingEntity) { + LivingEntity lentity = (LivingEntity) entity; + if (lentity.getEyeLocation().getBlockX() == affectedblock + .getX() + && lentity.getEyeLocation().getBlockZ() == affectedblock + .getZ()) + if (!(entity instanceof FallingBlock)) + entity.setVelocity(norm.clone().multiply( + .75)); + } else { + if (entity.getLocation().getBlockX() == affectedblock + .getX() + && entity.getLocation().getBlockZ() == affectedblock + .getZ()) + if (!(entity instanceof FallingBlock)) + entity.setVelocity(norm.clone().multiply( + .75)); + } + } + + } + + if (up) { + Block topblock = affectedblock.getRelative(BlockFace.UP); + if (topblock.getType() != Material.AIR) { + breakBlock(affectedblock); + } else if (!affectedblock.isLiquid() + && affectedblock.getType() != Material.AIR) { + // affectedblock.setType(Material.GLASS); + moveEarthBlock(affectedblock, topblock); + } + } else { + breakBlock(affectedblock); + } + + // affectedblock.setType(block.getType()); + // affectedblock.setData(block.getData()); + // + // addTempEarthBlock(block, affectedblock); + moveEarthBlock(block, affectedblock); + block.getWorld().playEffect(block.getLocation(), + Effect.GHAST_SHOOT, 0, 4); + + for (double i = 1; i < chainlength; i++) { + affectedblock = location + .clone() + .add(negnorm.getX() * i, negnorm.getY() * i, + negnorm.getZ() * i).getBlock(); + if (!isEarthbendable(player, affectedblock)) { + // verbose(affectedblock.getType()); + if (down) { + if (isTransparentToEarthbending(player, + affectedblock) + && !affectedblock.isLiquid() + && affectedblock.getType() != Material.AIR) { + moveEarthBlock(affectedblock, block); + } + } + // if (!Tools.adjacentToThreeOrMoreSources(block) + // && Tools.isWater(block)) { + // block.setType(Material.AIR); + // } else { + // byte full = 0x0; + // block.setType(Material.WATER); + // block.setData(full); + // } + break; + } + if (EarthPassive.isPassiveSand(affectedblock)) { + EarthPassive.revertSand(affectedblock); + } + // if (affectedblock.getType() == Material.SAND) { + // affectedblock.setType(Material.SANDSTONE); + // } + if (block == null) { + for (Block checkblock : blocks) { + tempnophysics.remove(checkblock); + } + return false; + } + // block.setType(affectedblock.getType()); + // block.setData(affectedblock.getData()); + // addTempEarthBlock(affectedblock, block); + moveEarthBlock(affectedblock, block); + block = affectedblock; + } + + int i = chainlength; + affectedblock = location + .clone() + .add(negnorm.getX() * i, negnorm.getY() * i, + negnorm.getZ() * i).getBlock(); + if (!isEarthbendable(player, affectedblock)) { + if (down) { + if (isTransparentToEarthbending(player, affectedblock) + && !affectedblock.isLiquid()) { + moveEarthBlock(affectedblock, block); + } + } + } + + } else { + for (Block checkblock : blocks) { + tempnophysics.remove(checkblock); + } + return false; + } + for (Block checkblock : blocks) { + tempnophysics.remove(checkblock); + } + return true; + } + return false; + } + + public static void moveEarthBlock(Block source, Block target) { byte full = 0x0; Information info; diff --git a/src/com/projectkorra/ProjectKorra/PKListener.java b/src/com/projectkorra/ProjectKorra/PKListener.java index 2be67d2d..e0b54fce 100644 --- a/src/com/projectkorra/ProjectKorra/PKListener.java +++ b/src/com/projectkorra/ProjectKorra/PKListener.java @@ -49,6 +49,7 @@ import com.projectkorra.ProjectKorra.airbending.AirSpout; import com.projectkorra.ProjectKorra.airbending.Tornado; import com.projectkorra.ProjectKorra.chiblocking.ChiPassive; import com.projectkorra.ProjectKorra.chiblocking.Paralyze; +import com.projectkorra.ProjectKorra.earthbending.Catapult; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; import com.projectkorra.ProjectKorra.firebending.Enflamed; import com.projectkorra.ProjectKorra.firebending.FireJet; @@ -313,6 +314,15 @@ public class PKListener implements Listener { Bloodbending.launch(player); } } + + if (Methods.isEarthAbility(abil)) { + if (Methods.isWeapon(player.getItemInHand().getType()) && !plugin.getConfig().getBoolean("Properties.Earth.CanBendWithWeapons")) { + return; + } + if (abil.equalsIgnoreCase("Catapult")) { + new Catapult(player); + } + } if (Methods.isFireAbility(abil)) { if (Methods.isWeapon(player.getItemInHand().getType()) && !plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { return; diff --git a/src/com/projectkorra/ProjectKorra/earthbending/Catapult.java b/src/com/projectkorra/ProjectKorra/earthbending/Catapult.java new file mode 100644 index 00000000..008c9e7d --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/earthbending/Catapult.java @@ -0,0 +1,245 @@ +package com.projectkorra.ProjectKorra.earthbending; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Location; +import org.bukkit.block.Block; +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 Catapult { + + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + public static ConcurrentHashMap cooldowns = new ConcurrentHashMap(); + // private static ConcurrentHashMap timers = new + // ConcurrentHashMap(); + // static final long soonesttime = Methods.timeinterval; + + private static int length = ProjectKorra.plugin.getConfig().getInt("Abilities.Earth.Catapult.Length"); + private static double speed = ProjectKorra.plugin.getConfig().getDouble("Abilities.Earth.Catapult.Speed"); + private static double push = ProjectKorra.plugin.getConfig().getDouble("Abilities.Earth.Catapult.Push"); + + private static long interval = (long) (1000. / speed); + // private static long interval = 1500; + + private Player player; + private Location origin; + private Location location; + private Vector direction; + private int distance; + private boolean catapult = false; + private boolean moving = false; + private boolean flying = false; + private long time; + private long starttime; + private int ticks = 0; + + public Catapult(Player player) { + // if (timers.containsKey(player)) { + // if (System.currentTimeMillis() < timers.get(player) + soonesttime) { + // return; + // } + // } + + if (cooldowns.containsKey(player.getName())) { + if (cooldowns.get(player.getName()) + ProjectKorra.plugin.getConfig().getLong("Properties.GlobalCooldown") >= System.currentTimeMillis()) { + return; + } else { + cooldowns.remove(player.getName()); + } + } + + this.player = player; + origin = player.getEyeLocation().clone(); + direction = origin.getDirection().clone().normalize(); + Vector neg = direction.clone().multiply(-1); + + Block block; + distance = 0; + for (int i = 0; i <= length; i++) { + location = origin.clone().add(neg.clone().multiply((double) i)); + block = location.getBlock(); + if (Methods.isEarthbendable(player, block)) { + // block.setType(Material.SANDSTONE); + distance = Methods.getEarthbendableBlocksLength(player, block, + neg, length - i); + break; + } else if (!Methods.isTransparentToEarthbending(player, block)) { + break; + } + } + + // Methods.verbose(distance); + + if (distance != 0) { + if ((double) distance >= location.distance(origin)) { + catapult = true; + } + time = System.currentTimeMillis() - interval; + starttime = System.currentTimeMillis(); + moving = true; + instances.put(player.getEntityId(), this); + cooldowns.put(player.getName(), System.currentTimeMillis()); + // timers.put(player, System.currentTimeMillis()); + } + + } + + public Catapult(Player player, Catapult source) { + flying = true; + this.player = player; + moving = false; + location = source.location.clone(); + starttime = source.starttime; + direction = source.direction.clone(); + distance = source.distance; + time = source.time; + instances.put(player.getEntityId(), this); + fly(); + } + + public boolean progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return false; + } + + if (System.currentTimeMillis() - time >= interval) { + time = System.currentTimeMillis(); + if (moving) + if (!moveEarth()) { + moving = false; + } + } + + if (flying) + fly(); + + if (!flying && !moving && System.currentTimeMillis() > starttime + 1000) + remove(); + return true; + } + + private void fly() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + // Methods.verbose(player.getLocation().distance(location)); + if (player.getWorld() != location.getWorld()) { + remove(); + return; + } + + if (player.getLocation().distance(location) < 3) { + if (!moving && System.currentTimeMillis() > starttime + 1000) + flying = false; + return; + } + + for (Block block : Methods + .getBlocksAroundPoint(player.getLocation(), 1.5)) { + if ((Methods.isSolid(block) || block.isLiquid())) { + // Methods.verbose("Catapulting stopped"); + flying = false; + return; + } + } + Vector vector = direction.clone().multiply(push * distance / length); + vector.setY(player.getVelocity().getY()); + player.setVelocity(vector); + // Methods.verbose("Fly!"); + } + + private void remove() { + instances.remove(player.getEntityId()); + } + + private boolean moveEarth() { + // Methods.verbose(distance); + // Methods.verbose(direction); + // Location loc = location.clone().add(direction); + if (ticks > distance) { + return false; + } else { + ticks++; + } + + // Methods.moveEarth(player, location, direction, distance, false); + location = location.clone().add(direction); + + if (catapult) { + if (location.distance(origin) < .5) { + boolean remove = false; + for (Entity entity : Methods.getEntitiesAroundPoint(origin, 2)) { + if (entity instanceof Player) { + Player target = (Player) entity; + boolean equal = target.getEntityId() == player + .getEntityId(); + if (equal) { + remove(); + remove = true; + } + if (equal || target.isSneaking()) { + new Flight(target); + target.setAllowFlight(true); + new Catapult(target, this); + } + } + entity.setVelocity(direction.clone().multiply( + push * distance / length)); + + } + return remove; + } + } else { + if (location.distance(origin) <= length - distance) { + for (Entity entity : Methods.getEntitiesAroundPoint(location, 2)) { + entity.setVelocity(direction.clone().multiply( + push * distance / length)); + } + return false; + } + } + Methods.moveEarth(player, location.clone().subtract(direction), + direction, distance, false); + return true; + } + + public static boolean progress(int ID) { + return instances.get(ID).progress(); + } + + public static List getPlayers() { + List players = new ArrayList(); + for (int id : instances.keySet()) { + Player player = instances.get(id).player; + if (!players.contains(player)) + players.add(player); + } + return players; + } + + public static void removeAll() { + for (int id : instances.keySet()) { + instances.remove(id); + } + } + + public static String getDescription() { + return "To use, left-click while looking in the direction you want to be launched. " + + "A pillar of earth will jut up from under you and launch you in that direction - " + + "if and only if there is enough earth behind where you're looking to launch you. " + + "Skillful use of this ability takes much time and work, and it does result in the " + + "death of certain gung-ho earthbenders. If you plan to use this ability, be sure " + + "you've read about your passive ability you innately have as an earthbender."; + } +} diff --git a/src/config.yml b/src/config.yml index b2361d05..cbbd4e27 100644 --- a/src/config.yml +++ b/src/config.yml @@ -87,6 +87,12 @@ Abilities: Earth: Passive: Duration: 2500 + Catapult: + Enabled: true + Description: "To use, left-click while looking in the direction you want to be launched. A pillar of earth will jut up from under you and launch you in that direction - if and only if there is enough earth behind where you're looking to launch you. Skillful use of this ability takes much time and work, and it does result in the death of certain gung-ho earthbenders. if you plan to use this ability, be sure you've read about your passive ability you innately have as an earthbender." + Length: 7 + Speed: 12 + Push: 5 Fire: FireJet: Enabled: true