From bd1f83f2cfc23445f63256787a8c2e99e4624a42 Mon Sep 17 00:00:00 2001 From: MistPhizzle Date: Wed, 25 Jun 2014 13:08:36 -0400 Subject: [PATCH] WaterManipulation --- .../ProjectKorra/BendingManager.java | 5 + .../projectkorra/ProjectKorra/Methods.java | 1 + .../projectkorra/ProjectKorra/PKListener.java | 31 +- .../ProjectKorra/waterbending/FreezeMelt.java | 6 +- .../ProjectKorra/waterbending/WaterCore.java | 84 --- .../waterbending/WaterManipulation.java | 707 ++++++++++++++++++ .../waterbending/WaterReturn.java | 221 ++++++ src/config.yml | 7 + 8 files changed, 967 insertions(+), 95 deletions(-) delete mode 100644 src/com/projectkorra/ProjectKorra/waterbending/WaterCore.java create mode 100644 src/com/projectkorra/ProjectKorra/waterbending/WaterManipulation.java create mode 100644 src/com/projectkorra/ProjectKorra/waterbending/WaterReturn.java diff --git a/src/com/projectkorra/ProjectKorra/BendingManager.java b/src/com/projectkorra/ProjectKorra/BendingManager.java index 1f5b8604..a79071af 100644 --- a/src/com/projectkorra/ProjectKorra/BendingManager.java +++ b/src/com/projectkorra/ProjectKorra/BendingManager.java @@ -30,6 +30,7 @@ import com.projectkorra.ProjectKorra.firebending.FireStream; import com.projectkorra.ProjectKorra.waterbending.Bloodbending; import com.projectkorra.ProjectKorra.waterbending.FreezeMelt; import com.projectkorra.ProjectKorra.waterbending.Plantbending; +import com.projectkorra.ProjectKorra.waterbending.WaterManipulation; import com.projectkorra.ProjectKorra.waterbending.WaterPassive; import com.projectkorra.ProjectKorra.waterbending.WaterSpout; @@ -104,6 +105,10 @@ public class BendingManager implements Runnable { CompactColumn.progress(ID); } + for (int ID: WaterManipulation.instances.keySet()) { + WaterManipulation.progress(ID); + } + FireStream.dissipateAll(); } catch (Exception e) { Methods.stopBending(); diff --git a/src/com/projectkorra/ProjectKorra/Methods.java b/src/com/projectkorra/ProjectKorra/Methods.java index 621aeed7..cf251911 100644 --- a/src/com/projectkorra/ProjectKorra/Methods.java +++ b/src/com/projectkorra/ProjectKorra/Methods.java @@ -37,6 +37,7 @@ import com.projectkorra.ProjectKorra.earthbending.EarthColumn; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; import com.projectkorra.ProjectKorra.waterbending.FreezeMelt; import com.projectkorra.ProjectKorra.waterbending.WaterCore; +import com.projectkorra.ProjectKorra.waterbending.WaterManipulation; public class Methods { diff --git a/src/com/projectkorra/ProjectKorra/PKListener.java b/src/com/projectkorra/ProjectKorra/PKListener.java index 70ad8165..89eb5d57 100644 --- a/src/com/projectkorra/ProjectKorra/PKListener.java +++ b/src/com/projectkorra/ProjectKorra/PKListener.java @@ -65,6 +65,7 @@ import com.projectkorra.ProjectKorra.waterbending.Bloodbending; import com.projectkorra.ProjectKorra.waterbending.FreezeMelt; import com.projectkorra.ProjectKorra.waterbending.Melt; import com.projectkorra.ProjectKorra.waterbending.WaterCore; +import com.projectkorra.ProjectKorra.waterbending.WaterManipulation; import com.projectkorra.ProjectKorra.waterbending.WaterPassive; import com.projectkorra.ProjectKorra.waterbending.WaterSpout; @@ -98,10 +99,14 @@ public class PKListener implements Listener { Block toblock = event.getToBlock(); Block fromblock = event.getBlock(); if (Methods.isWater(fromblock)) { + event.setCancelled(!AirBubble.canFlowTo(toblock)); if (!event.isCancelled()) { - if (Methods.isAdjacentToFrozenBlock(toblock) || Methods.isAdjacentToFrozenBlock(fromblock)) { - event.setCancelled(true); - } + event.setCancelled(!WaterManipulation.canFlowFromTo(fromblock, + toblock)); + } + if (!event.isCancelled()) { + if (Illumination.blocks.containsKey(toblock)) + toblock.setType(Material.AIR); } } } @@ -175,6 +180,9 @@ public class PKListener implements Listener { if (abil.equalsIgnoreCase("PhaseChange")) { new Melt(player); } + if (abil.equalsIgnoreCase("WaterManipulation")) { + new WaterManipulation(player); + } } if (Methods.isEarthAbility(abil)) { @@ -350,6 +358,9 @@ public class PKListener implements Listener { if (abil.equalsIgnoreCase("WaterSpout")) { new WaterSpout(player); } + if (abil.equalsIgnoreCase("WaterManipulation")) { + WaterManipulation.moveWater(player); + } } if (Methods.isEarthAbility(abil)) { @@ -586,17 +597,21 @@ public class PKListener implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onBlockPhysics(BlockPhysicsEvent event) { Block block = event.getBlock(); - if (TempBlock.isTempBlock(block) || TempBlock.isTouchingTempBlock(block)) { - event.setCancelled(true); - } + event.setCancelled(!WaterManipulation.canPhysicsChange(block)); + if (!event.isCancelled()) + event.setCancelled(Illumination.blocks.containsKey(block)); + if (!event.isCancelled()) + event.setCancelled(Methods.tempnophysics.contains(block)); } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onBlockForm(BlockFormEvent event) { - if (!WaterCore.canPhysicsChange(event.getBlock())) + if (TempBlock.isTempBlock(event.getBlock())) + event.setCancelled(true); + if (!WaterManipulation.canPhysicsChange(event.getBlock())) event.setCancelled(true); } + public void onNameTag(AsyncPlayerReceiveNameTagEvent e) { List elements = Methods.getBendingPlayer(e.getNamedPlayer().getName()).getElements(); if (elements.size() > 1) diff --git a/src/com/projectkorra/ProjectKorra/waterbending/FreezeMelt.java b/src/com/projectkorra/ProjectKorra/waterbending/FreezeMelt.java index 897bec87..ac7a4636 100644 --- a/src/com/projectkorra/ProjectKorra/waterbending/FreezeMelt.java +++ b/src/com/projectkorra/ProjectKorra/waterbending/FreezeMelt.java @@ -50,9 +50,9 @@ public class FreezeMelt { } private static boolean isFreezable(Player player, Block block) { - if (Methods.isRegionProtectedFromBuild(player, Abilities.PhaseChange, - block.getLocation())) - return false; +// if (Methods.isRegionProtectedFromBuild(player, Abilities.PhaseChange, +// block.getLocation())) +// return false; if (block.getType() == Material.WATER || block.getType() == Material.STATIONARY_WATER) if (WaterManipulation.canPhysicsChange(block) diff --git a/src/com/projectkorra/ProjectKorra/waterbending/WaterCore.java b/src/com/projectkorra/ProjectKorra/waterbending/WaterCore.java deleted file mode 100644 index d9637224..00000000 --- a/src/com/projectkorra/ProjectKorra/waterbending/WaterCore.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.projectkorra.ProjectKorra.waterbending; - -import java.util.concurrent.ConcurrentHashMap; - -import org.bukkit.Material; -import org.bukkit.block.Block; -import com.projectkorra.ProjectKorra.Methods; -import com.projectkorra.ProjectKorra.TempBlock; - -public class WaterCore { - - public static ConcurrentHashMap frozenblocks = new ConcurrentHashMap(); - public static ConcurrentHashMap waterSpoutAffectedBlocks = new ConcurrentHashMap(); - public static ConcurrentHashMap waterManipulationAffectedBlocks = new ConcurrentHashMap(); - -// public static void removeSpouts(Location loc0, double radius, -// Player sourceplayer) { -// if (!Methods.isAbilityInstalled("WaterSpout", "orion304")) return; -// for (Player player : WaterSpoutAbility.instances.keySet()) { -// if (!player.equals(sourceplayer)) { -// Location loc1 = player.getLocation().getBlock().getLocation(); -// loc0 = loc0.getBlock().getLocation(); -// double dx = loc1.getX() - loc0.getX(); -// double dy = loc1.getY() - loc0.getY(); -// double dz = loc1.getZ() - loc0.getZ(); -// -// double distance = Math.sqrt(dx * dx + dz * dz); -// -// if (distance <= radius && dy > 0 && dy < WaterSpoutAbility.defaultheight) -// WaterSpoutAbility.instances.get(player).remove(); -// } -// } -// } - - public static void thaw(Block block) { - if (frozenblocks.containsKey(block)) { - byte data = frozenblocks.get(block); - frozenblocks.remove(block); - block.setType(Material.WATER); - block.setData(data); - } - } - - public static boolean canFlowFromTo(Block from, Block to) { - if (WaterCore.waterManipulationAffectedBlocks.containsKey(to) || WaterCore.waterManipulationAffectedBlocks.containsKey(from)) { - return false; - } - if (WaterCore.waterSpoutAffectedBlocks.containsKey(to) || WaterCore.waterSpoutAffectedBlocks.containsKey(from)) { - return false; - } - - if (TempBlock.isTempBlock(to) || TempBlock.isTempBlock(from)) { - return false; - } - if (Methods.isAdjacentToFrozenBlock(to) - || Methods.isAdjacentToFrozenBlock(from)) { - return false; - } - - return true; - } - - public static boolean canPhysicsChange(Block block) { - if (waterManipulationAffectedBlocks.containsKey(block)) - return false; - if (Methods.isAbilityInstalled("WaterSpout", "orion304")) { - if (waterSpoutAffectedBlocks.containsKey(block)) - return false; - } -// if (Methods.isAbilityInstalled("Surge", "orion304")) { -// if (waterWallAffectedBlocks.containsKey(block)) -// return false; -// if (waterwallblocks.containsKey(block)) -// return false; -//// if (WaveAbility.isBlockWave(block)) -//// return false; -// } - if (TempBlock.isTempBlock(block)) - return false; - if (TempBlock.isTouchingTempBlock(block)) - return false; - return true; - } -} diff --git a/src/com/projectkorra/ProjectKorra/waterbending/WaterManipulation.java b/src/com/projectkorra/ProjectKorra/waterbending/WaterManipulation.java new file mode 100644 index 00000000..d2d5819d --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/waterbending/WaterManipulation.java @@ -0,0 +1,707 @@ +package com.projectkorra.ProjectKorra.waterbending; + +import java.util.HashSet; +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.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.TempBlock; +import com.projectkorra.ProjectKorra.Ability.AvatarState; + +public class WaterManipulation { + + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + public static ConcurrentHashMap affectedblocks = new ConcurrentHashMap(); + public static ConcurrentHashMap prepared = new ConcurrentHashMap(); + + private static int ID = Integer.MIN_VALUE; + + private static final byte full = 0x0; + // private static final byte half = 0x4; + + static double range = ProjectKorra.plugin.getConfig().getDouble("Abilities.Water.WaterManipulation.Range"); + private static double pushfactor = ProjectKorra.plugin.getConfig().getDouble("Abilities.Water.WaterManipulation.Push"); + private static double defaultdamage = ProjectKorra.plugin.getConfig().getDouble("Abilities.Water.WaterManipulation.Damage"); + private static double speed = ProjectKorra.plugin.getConfig().getDouble("Abilities.Water.WaterManipulation.Speed"); + private static final double deflectrange = 3; + // private static double speed = 1.5; + + private static HashSet water = new HashSet(); + + private static long interval = (long) (1000. / speed); + + Player player; + private int id; + private Location location = null; + private Block sourceblock = null; + private TempBlock trail, trail2; + private boolean progressing = false; + private Location firstdestination = null; + private Location targetdestination = null; + private Vector firstdirection = null; + private Vector targetdirection = null; + private boolean falling = false; + private boolean settingup = false; + // private boolean targetting = false; + private final boolean displacing = false; + private long time; + private double damage = defaultdamage; + private int displrange; + + public WaterManipulation(Player player) { + if (water.isEmpty()) { + water.add((byte) 0); + water.add((byte) 8); + water.add((byte) 9); + } + this.player = player; + if (prepare()) { + id = ID; + instances.put(id, this); + prepared.put(player, id); + if (ID == Integer.MAX_VALUE) + ID = Integer.MIN_VALUE; + ID++; + time = System.currentTimeMillis(); + } + } + + public boolean prepare() { + // Block block = player.getTargetBlock(null, (int) range); + Block block = Methods.getWaterSourceBlock(player, range, + Methods.canPlantbend(player)); + // if (prepared.containsKey(player) + // && !Methods.isWaterbendable(block, player)) { + // instances.get(prepared.get(player)).displacing = true; + // instances.get(prepared.get(player)).moveWater(); + // } + cancelPrevious(); + block(player); + if (block != null) { + sourceblock = block; + focusBlock(); + return true; + } + return false; + } + + private void cancelPrevious() { + if (prepared.containsKey(player)) { + if (instances.containsKey(prepared.get(player))) { + WaterManipulation old = instances.get(prepared.get(player)); + if (!old.progressing) { + old.cancel(); + } + } + } + } + + public void cancel() { + unfocusBlock(); + } + + private void focusBlock() { + location = sourceblock.getLocation(); + } + + private void unfocusBlock() { + remove(id); + } + + public void moveWater() { + if (sourceblock != null) { + if (sourceblock.getWorld() == player.getWorld()) { + targetdestination = getTargetLocation(player); + + if (targetdestination.distance(location) <= 1) { + progressing = false; + targetdestination = null; + remove(id); + } else { + progressing = true; + settingup = true; + firstdestination = getToEyeLevel(); + firstdirection = Methods.getDirection( + sourceblock.getLocation(), firstdestination) + .normalize(); + targetdestination = Methods.getPointOnLine(firstdestination, + targetdestination, range); + targetdirection = Methods.getDirection(firstdestination, + targetdestination).normalize(); + + if (Methods.isPlant(sourceblock)) + new Plantbending(sourceblock); + addWater(sourceblock); + } + + } + + BendingPlayer.getBendingPlayer(player).cooldown( + Abilities.WaterManipulation); + + } + } + + private static Location getTargetLocation(Player player) { + Entity target = Methods.getTargetedEntity(player, range, new ArrayList()); + Location location; + if (target == null) { + location = Methods.getTargetedLocation(player, range, + Methods.transparentToEarthbending); + } else { + // targetting = true; + location = ((LivingEntity) target).getEyeLocation(); + // location.setY(location.getY() - 1); + } + return location; + } + + private Location getToEyeLevel() { + Location loc = sourceblock.getLocation().clone(); + double dy = targetdestination.getY() - sourceblock.getY(); + if (dy <= 2) { + loc.setY(sourceblock.getY() + 2); + } else { + loc.setY(targetdestination.getY() - 1); + } + return loc; + } + + private static void remove(int id) { + Player player = instances.get(id).player; + if (prepared.containsKey(player)) { + if (prepared.get(player) == id) + prepared.remove(player); + } + instances.remove(id); + } + + private void redirect(Player player, Location targetlocation) { + if (progressing && !settingup) { + if (location.distance(player.getLocation()) <= range) + targetdirection = Methods.getDirection(location, targetlocation) + .normalize(); + targetdestination = targetlocation; + this.player = player; + } + } + + public boolean progress() { + if (player.isDead() || !player.isOnline() + || !Methods.canBend(player.getName(), "WaterManipulation")) { + breakBlock(); + return false; + } + if (System.currentTimeMillis() - time >= interval) { + // removeWater(oldwater); + // if (Methods.isRegionProtectedFromBuild(player, + // Abilities.WaterManipulation, location)) { + // breakBlock(); + // return false; + // } + + time = System.currentTimeMillis(); + + if (Methods.getBoundAbility(player) == null) { + unfocusBlock(); + return false; + } + if (!progressing + && !falling + && !Methods.getBoundAbility(player).equalsIgnoreCase("WaterManipulation")) { + unfocusBlock(); + return false; + } + + if (falling) { + // location = location.clone().add(0, -1, 0); + // + // if (location.getBlock().getType() != Material.AIR) { + // falling = false; + // unfocusBlock(); + // return false; + // } + // + // for (Entity entity : Methods.getEntitiesAroundPoint(location, + // 1)) { + // if (entity instanceof LivingEntity) { + // Methods.damageEntity(player, entity, damage); + // falling = false; + // } + // } + // + // if (!falling) { + // breakBlock(); + // return false; + // } + // + // location.getBlock().setType(sourceblock.getType()); + // sourceblock.setType(Material.AIR); + // + // sourceblock = location.getBlock(); + // if (!Methods.isSolid(sourceblock.getRelative(BlockFace.DOWN)) + // || targetting) { + // finalRemoveWater(sourceblock); + // } else { + // sourceblock.setData(full); + // affectedblocks.remove(sourceblock); + // } + // + // instances.remove(player.getEntityId()); + breakBlock(); + new WaterReturn(player, sourceblock); + return false; + + } else { + if (!progressing) { + sourceblock.getWorld().playEffect(location, Effect.SMOKE, + 4, (int) range); + return false; + } + + // Methods.verbose(firstdestination); + + if (sourceblock.getLocation().distance(firstdestination) < .5) { + settingup = false; + } + + // if (!player.isSneaking() && displacing) { + // displacing = false; + // breakBlock(); + // return false; + // } + + Vector direction; + if (settingup) { + direction = firstdirection; + } else { + direction = targetdirection; + } + + Block block = location.getBlock(); + if (displacing) { + Block targetblock = player.getTargetBlock(null, displrange); + direction = Methods.getDirection(location, + targetblock.getLocation()).normalize(); + if (!location.getBlock().equals(targetblock.getLocation())) { + location = location.clone().add(direction); + + block = location.getBlock(); + if (block.getLocation().equals( + sourceblock.getLocation())) { + location = location.clone().add(direction); + block = location.getBlock(); + } + } + + } else { + Methods.removeSpouts(location, player); + + double radius = FireBlast.affectingradius; + Player source = player; + if (EarthBlast.annihilateBlasts(location, radius, source) + || WaterManipulation.annihilateBlasts(location, + radius, source) + || FireBlast.annihilateBlasts(location, radius, + source)) { + breakBlock(); + new WaterReturn(player, sourceblock); + return false; + } + + location = location.clone().add(direction); + + block = location.getBlock(); + if (block.getLocation().equals(sourceblock.getLocation())) { + location = location.clone().add(direction); + block = location.getBlock(); + } + } + + if (trail2 != null) { + if (trail2.getBlock().equals(block)) { + trail2.revertBlock(); + trail2 = null; + } + } + + if (trail != null) { + if (trail.getBlock().equals(block)) { + trail.revertBlock(); + trail = null; + if (trail2 != null) { + trail2.revertBlock(); + trail2 = null; + } + } + } + + if (Methods.isTransparentToEarthbending(player, block) + && !block.isLiquid()) { + Methods.breakBlock(block); + } else if (block.getType() != Material.AIR + && !Methods.isWater(block)) { + breakBlock(); + new WaterReturn(player, sourceblock); + return false; + } + + if (!displacing) { + for (Entity entity : Methods.getEntitiesAroundPoint(location, + FireBlast.affectingradius)) { + if (entity instanceof LivingEntity + && entity.getEntityId() != player.getEntityId()) { + + // Block testblock = location.getBlock(); + // Block block1 = entity.getLocation().getBlock(); + // Block block2 = ((LivingEntity) entity) + // .getEyeLocation().getBlock(); + // + // if (testblock.equals(block1) + // || testblock.equals(block2)) { + + Location location = player.getEyeLocation(); + Vector vector = location.getDirection(); + entity.setVelocity(vector.normalize().multiply(pushfactor)); + // entity.setVelocity(entity.getVelocity().clone() + // .add(direction)); + if (AvatarState.isAvatarState(player)) + damage = AvatarState.getValue(damage); + Methods.damageEntity(player, entity, (int) Methods + .waterbendingNightAugment(damage, + player.getWorld())); + progressing = false; + // } + } + } + } + + if (!progressing) { + breakBlock(); + new WaterReturn(player, sourceblock); + return false; + } + + addWater(block); + reduceWater(sourceblock); + // if (block.getType() != Material.AIR) { + // block.setType(Material.GLOWSTONE); + // } else { + // block.setType(Material.GLASS); + // } + + if (trail2 != null) { + trail2.revertBlock(); + trail2 = null; + } + if (trail != null) { + trail2 = trail; + trail2.setType(Material.WATER, (byte) 2); + } + trail = new TempBlock(sourceblock, Material.WATER, (byte) 1); + sourceblock = block; + + if (location.distance(targetdestination) <= 1 + || location.distance(firstdestination) > range) { + + falling = true; + progressing = false; + } + + return true; + } + } + + return false; + + } + + private void breakBlock() { + + // removeWater(oldwater); + finalRemoveWater(sourceblock); + remove(id); + } + + private void reduceWater(Block block) { + if (displacing) { + removeWater(block); + return; + } + if (affectedblocks.containsKey(block)) { + if (!Methods.isAdjacentToThreeOrMoreSources(block)) { + // && !Methods.adjacentToAnyWater(block)) { + block.setType(Material.AIR); + // block.setType(Material.WATER); + // block.setData(half); + } + // oldwater = block; + affectedblocks.remove(block); + } + } + + private void removeWater(Block block) { + if (block != null) { + if (affectedblocks.containsKey(block)) { + if (!Methods.isAdjacentToThreeOrMoreSources(block)) { + block.setType(Material.AIR); + } + affectedblocks.remove(block); + } + } + } + + private void finalRemoveWater(Block block) { + if (trail != null) { + trail.revertBlock(); + trail = null; + } + if (trail2 != null) { + trail2.revertBlock(); + trail = null; + } + if (displacing) { + removeWater(block); + return; + } + if (affectedblocks.containsKey(block)) { + if (!Methods.isAdjacentToThreeOrMoreSources(block)) { + // && !Methods.adjacentToAnyWater(block)) { + block.setType(Material.AIR); + // block.setType(Material.WATER); + // block.setData(half); + } + affectedblocks.remove(block); + } + } + + private static void addWater(Block block) { + if (!affectedblocks.containsKey(block)) { + affectedblocks.put(block, block); + } + if (FreezeMelt.frozenblocks.containsKey(block)) + FreezeMelt.frozenblocks.remove(block); + block.setType(Material.WATER); + block.setData(full); + } + + public static void moveWater(Player player) { + // BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + + // if (!bPlayer.isOnCooldown(Abilities.WaterManipulation)) { + + if (prepared.containsKey(player)) { + if (instances.containsKey(prepared.get(player))) { + instances.get(prepared.get(player)).moveWater(); + } + prepared.remove(player); + } else if (WaterReturn.hasWaterBottle(player)) { + Location eyeloc = player.getEyeLocation(); + Block block = eyeloc.add(eyeloc.getDirection().normalize()) + .getBlock(); + if (Methods.isTransparentToEarthbending(player, block) + && Methods.isTransparentToEarthbending(player, + eyeloc.getBlock())) { + + if (getTargetLocation(player).distance(block.getLocation()) > 1) { + block.setType(Material.WATER); + block.setData(full); + WaterManipulation watermanip = new WaterManipulation( + player); + watermanip.moveWater(); + if (!watermanip.progressing) { + block.setType(Material.AIR); + } else { + WaterReturn.emptyWaterBottle(player); + } + } + } + } + // } + + redirectTargettedBlasts(player); + } + + private static void redirectTargettedBlasts(Player player) { + for (int id : instances.keySet()) { + WaterManipulation manip = instances.get(id); + + if (!manip.progressing) + continue; + + if (!manip.location.getWorld().equals(player.getWorld())) + continue; + +// if (Methods.isRegionProtectedFromBuild(player, +// Abilities.WaterManipulation, manip.location)) +// continue; + + if (manip.player.equals(player)) + manip.redirect(player, getTargetLocation(player)); + + Location location = player.getEyeLocation(); + Vector vector = location.getDirection(); + Location mloc = manip.location; + if (mloc.distance(location) <= range + && Methods.getDistanceFromLine(vector, location, + manip.location) < deflectrange + && mloc.distance(location.clone().add(vector)) < mloc + .distance(location.clone().add( + vector.clone().multiply(-1)))) { + manip.redirect(player, getTargetLocation(player)); + } + + } + } + + private static void block(Player player) { + for (int id : instances.keySet()) { + WaterManipulation manip = instances.get(id); + + if (manip.player.equals(player)) + continue; + + if (!manip.location.getWorld().equals(player.getWorld())) + continue; + + if (!manip.progressing) + continue; +// +// if (Methods.isRegionProtectedFromBuild(player, +// Abilities.WaterManipulation, manip.location)) +// continue; + + Location location = player.getEyeLocation(); + Vector vector = location.getDirection(); + Location mloc = manip.location; + if (mloc.distance(location) <= range + && Methods.getDistanceFromLine(vector, location, + manip.location) < deflectrange + && mloc.distance(location.clone().add(vector)) < mloc + .distance(location.clone().add( + vector.clone().multiply(-1)))) { + manip.breakBlock(); + } + + } + } + + public static boolean progress(int ID) { + if (instances.containsKey(ID)) + return instances.get(ID).progress(); + return false; + } + + public static boolean canFlowFromTo(Block from, Block to) { + // if (to.getType() == Material.TORCH) + // return true; + if (affectedblocks.containsKey(to) || affectedblocks.containsKey(from)) { + // Methods.verbose("affectedblocks"); + return false; + } + if (WaterSpout.affectedblocks.containsKey(to) + || WaterSpout.affectedblocks.containsKey(from)) { + // Methods.verbose("waterspout"); + return false; + } + if (WaterWall.affectedblocks.containsKey(to) + || WaterWall.affectedblocks.containsKey(from)) { + // Methods.verbose("waterwallaffectedblocks"); + return false; + } + if (WaterWall.wallblocks.containsKey(to) + || WaterWall.wallblocks.containsKey(from)) { + // Methods.verbose("waterwallwall"); + return false; + } + if (Wave.isBlockWave(to) || Wave.isBlockWave(from)) { + // Methods.verbose("wave"); + return false; + } + if (TempBlock.isTempBlock(to) || TempBlock.isTempBlock(from)) { + // Methods.verbose("tempblock"); + return false; + } + if (Methods.isAdjacentToFrozenBlock(to) + || Methods.isAdjacentToFrozenBlock(from)) { + // Methods.verbose("frozen"); + return false; + } + + return true; + } + + public static boolean canPhysicsChange(Block block) { + if (affectedblocks.containsKey(block)) + return false; + if (WaterSpout.affectedblocks.containsKey(block)) + return false; + if (WaterWall.affectedblocks.containsKey(block)) + return false; + if (WaterWall.wallblocks.containsKey(block)) + return false; + if (Wave.isBlockWave(block)) + return false; + if (TempBlock.isTempBlock(block)) + return false; + if (TempBlock.isTouchingTempBlock(block)) + return false; + return true; + } + + public static void removeAll() { + for (int id : instances.keySet()) + instances.get(id).breakBlock(); + prepared.clear(); + } + + public static boolean canBubbleWater(Block block) { + return canPhysicsChange(block); + } + + public static String getDescription() { + // TODO Auto-generated method stub + return "To use, place your cursor over a waterbendable object and tap sneak (default: shift). " + + "Smoke will appear where you've selected, indicating the origin of your ability. " + + "After you have selected an origin, simply left-click in any direction and you will " + + "see your water spout off in that direction, slicing any creature in its path. " + + "If you look towards a creature when you use this ability, it will target that creature. " + + "A collision from Water Manipulation both knocks the target back and deals some damage. " + + "Alternatively, if you have source selected and tap shift again, " + + "you will be able to control the water more directly."; + } + + public static void removeAroundPoint(Location location, double radius) { + for (int id : instances.keySet()) { + WaterManipulation manip = instances.get(id); + if (manip.location.getWorld().equals(location.getWorld())) + if (manip.location.distance(location) <= radius) + manip.breakBlock(); + } + } + + public static boolean annihilateBlasts(Location location, double radius, + Player source) { + boolean broke = false; + for (int id : instances.keySet()) { + WaterManipulation manip = instances.get(id); + if (manip.location.getWorld().equals(location.getWorld()) + && !source.equals(manip.player)) + if (manip.location.distance(location) <= radius) { + manip.breakBlock(); + broke = true; + } + } + return broke; + } + +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/waterbending/WaterReturn.java b/src/com/projectkorra/ProjectKorra/waterbending/WaterReturn.java new file mode 100644 index 00000000..d092e8cf --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/waterbending/WaterReturn.java @@ -0,0 +1,221 @@ +package com.projectkorra.ProjectKorra.waterbending; + +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.TempBlock; + +public class WaterReturn { + + private static ConcurrentHashMap instances = new ConcurrentHashMap(); + // private static int ID = Integer.MIN_VALUE; + private static long interval = 50; + + private static final byte full = 0x0; + private static double range = 30; + + private Player player; + // private int id; + private Location location; + private TempBlock block; + private long time; + + public WaterReturn(Player player, Block block) { + if (instances.containsKey(player)) + return; + this.player = player; + location = block.getLocation(); + if (Methods.canBend(player.getName(), "WaterManipulation")) { +// if (!Methods.isRegionProtectedFromBuild(player, +// Abilities.WaterManipulation, location) +// && Methods.canBend(player, Abilities.WaterManipulation)) { + if (Methods.isTransparentToEarthbending(player, block) + && !block.isLiquid()) + this.block = new TempBlock(block, Material.WATER, full); + } + // if (ID >= Integer.MAX_VALUE) { + // ID = Integer.MIN_VALUE; + // } + // id = ID++; + instances.put(player, this); + } + + private void progress() { + if (!hasEmptyWaterBottle()) { + remove(); + return; + } + + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if (player.getWorld() != location.getWorld()) { + remove(); + return; + } + + if (System.currentTimeMillis() < time + interval) + return; + + time = System.currentTimeMillis(); + + Vector direction = Methods + .getDirection(location, player.getEyeLocation()).normalize(); + location = location.clone().add(direction); + + if (location == null || block == null) { + remove(); + return; + } + + if (location.getBlock().equals(block.getLocation().getBlock())) + return; + +// if (Methods.isRegionProtectedFromBuild(player, +// Abilities.WaterManipulation, location)) { +// remove(); +// return; +// } + + if (location.distance(player.getEyeLocation()) > Methods + .waterbendingNightAugment(range, player.getWorld())) { + remove(); + return; + } + + if (location.distance(player.getEyeLocation()) <= 1.5) { + fillBottle(); + return; + } + + Block newblock = location.getBlock(); + if (Methods.isTransparentToEarthbending(player, newblock) + && !newblock.isLiquid()) { + block.revertBlock(); + block = new TempBlock(newblock, Material.WATER, full); + } else { + remove(); + return; + } + + } + + private void remove() { + if (block != null) { + block.revertBlock(); + block = null; + } + instances.remove(player); + } + + private boolean hasEmptyWaterBottle() { + PlayerInventory inventory = player.getInventory(); + if (inventory.contains(Material.GLASS_BOTTLE)) { + return true; + } + return false; + } + + private void fillBottle() { + PlayerInventory inventory = player.getInventory(); + if (inventory.contains(Material.GLASS_BOTTLE)) { + int index = inventory.first(Material.GLASS_BOTTLE); + ItemStack item = inventory.getItem(index); + if (item.getAmount() == 1) { + inventory.setItem(index, new ItemStack(Material.POTION)); + } else { + item.setAmount(item.getAmount() - 1); + inventory.setItem(index, item); + HashMap leftover = inventory + .addItem(new ItemStack(Material.POTION)); + for (int left : leftover.keySet()) { + player.getWorld().dropItemNaturally(player.getLocation(), + leftover.get(left)); + } + } + } + + remove(); + } + + private static boolean isBending(Player player) { + for (int id : WaterManipulation.instances.keySet()) { + if (WaterManipulation.instances.get(id).player.equals(player)) + return true; + } + + if (OctopusForm.instances.containsKey(player)) + return true; + + for (int id : Wave.instances.keySet()) { + if (Wave.instances.get(id).player.equals(player)) + return true; + } + + for (int id : WaterWall.instances.keySet()) { + if (WaterWall.instances.get(id).player.equals(player)) + return true; + } + + if (IceSpike2.isBending(player)) + return true; + + return false; + } + + public static boolean hasWaterBottle(Player player) { + if (instances.containsKey(player)) + return false; + if (isBending(player)) + return false; + PlayerInventory inventory = player.getInventory(); + return (inventory.contains(new ItemStack(Material.POTION), 1)); + } + + public static void emptyWaterBottle(Player player) { + PlayerInventory inventory = player.getInventory(); + int index = inventory.first(new ItemStack(Material.POTION)); + if (index != -1) { + ItemStack item = inventory.getItem(index); + if (item.getAmount() == 1) { + inventory.setItem(index, new ItemStack(Material.GLASS_BOTTLE)); + } else { + item.setAmount(item.getAmount() - 1); + inventory.setItem(index, item); + HashMap leftover = inventory + .addItem(new ItemStack(Material.GLASS_BOTTLE)); + for (int left : leftover.keySet()) { + player.getWorld().dropItemNaturally(player.getLocation(), + leftover.get(left)); + } + } + } + } + + public static void progressAll() { + for (Player player : instances.keySet()) { + instances.get(player).progress(); + } + } + + public static void removeAll() { + for (Player player : instances.keySet()) { + WaterReturn wr = instances.get(player); + if (wr.block != null) + wr.block.revertBlock(); + } + instances.clear(); + } + +} \ No newline at end of file diff --git a/src/config.yml b/src/config.yml index 2b2c9362..299492e7 100644 --- a/src/config.yml +++ b/src/config.yml @@ -85,6 +85,13 @@ Abilities: Radius: 5 Plantbending: RegrowTime: 180000 + WaterManipulation: + Enabled: true + Description: "To use, place your cursor over a waterbendable object and tap sneak (default: shift). Smoke will appear where you've selected, indicating the origin of your ability. After you have selected an origin, simply left-click in any direction and you will see your water spout off in that direction, slicing any creature in its path. If you look towards a creature when you use this ability, it will target that creature. A collision from Water Manipulation both knocks the target back and deals some damage. Alternatively, if you have the source selected and tap shift again, you will be able to control the water more directly." + Damage: 3.0 + Range: 20 + Speed: 35 + Push: .3 WaterSpout: Enabled: true Description: "To use this ability, click while over or in water. You will spout water up from beneath you to experience controlled levitation. This ability is a toggle, so you can activate it then use other abilities and it will remain on. If you try to spout over an area with no water, snow, or ice, the spout will dissipate and you will fall. Click again with this ability selected to deactivate it."