From 3adf108ba1cd80d8c6df8b28d5820f1012a97d17 Mon Sep 17 00:00:00 2001 From: MistPhizzle Date: Sat, 23 Aug 2014 14:51:24 -0400 Subject: [PATCH] Lava Surge --- .../ProjectKorra/Ability/StockAbilities.java | 4 +- .../ProjectKorra/ConfigManager.java | 6 + .../projectkorra/ProjectKorra/Methods.java | 42 +++ .../projectkorra/ProjectKorra/PKListener.java | 31 ++ .../projectkorra/ProjectKorra/TempBlock.java | 8 +- .../ProjectKorra/airbending/AirBlast.java | 3 + .../earthbending/EarthPassive.java | 45 +++ .../earthbending/EarthbendingManager.java | 14 +- .../ProjectKorra/earthbending/LavaWall.java | 329 ++++++++++++++++++ .../ProjectKorra/earthbending/LavaWave.java | 297 ++++++++++++++++ src/config.yml | 6 + src/plugin.yml | 1 + 12 files changed, 780 insertions(+), 6 deletions(-) create mode 100644 src/com/projectkorra/ProjectKorra/earthbending/LavaWall.java create mode 100644 src/com/projectkorra/ProjectKorra/earthbending/LavaWave.java diff --git a/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java b/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java index 0316d8a6..3bb6293b 100644 --- a/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java +++ b/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java @@ -18,7 +18,7 @@ public enum StockAbilities { AvatarState, // Project Korra - Extraction, Smokescreen, Combustion; + Extraction, Smokescreen, Combustion, LavaSurge; private enum AirbendingAbilities { AirBlast, AirBubble, AirShield, AirSuction, AirSwipe, Tornado, AirScooter, AirSpout, AirBurst; @@ -29,7 +29,7 @@ public enum StockAbilities { } private enum EarthbendingAbilities { - Catapult, RaiseEarth, EarthGrab, EarthTunnel, EarthBlast, Collapse, Tremorsense, EarthArmor, Shockwave, Extraction; + Catapult, RaiseEarth, EarthGrab, EarthTunnel, EarthBlast, Collapse, Tremorsense, EarthArmor, Shockwave, Extraction, LavaSurge; } private enum FirebendingAbilities { diff --git a/src/com/projectkorra/ProjectKorra/ConfigManager.java b/src/com/projectkorra/ProjectKorra/ConfigManager.java index 836582d2..319dc24f 100644 --- a/src/com/projectkorra/ProjectKorra/ConfigManager.java +++ b/src/com/projectkorra/ProjectKorra/ConfigManager.java @@ -361,6 +361,12 @@ public class ConfigManager { config.addDefault("Abilities.Earth.Extraction.TripleLootChance", 15); config.addDefault("Abilities.Earth.Extraction.DoubleLootChance", 40); + config.addDefault("Abilities.Earth.LavaSurge.Enabled", true); + config.addDefault("Abilities.Earth.LavaSurge.Description", "This ability allows an Earthbender to bend an existing Lava Source to create a large wave that deals damage and knocks back anything in its path. To use, simply tap sneak (Default: Shift) while targetting a source of lava. Once a source has been selected, left click to launch the wave off into the direction you are looking. This ability has a small knockback and does a fair amount of damage."); + config.addDefault("Abilities.Earth.LavaSurge.Radius", 3); + config.addDefault("Abilities.Earth.LavaSurge.HorizontalPush", 0.5); + config.addDefault("Abilities.Earth.LavaSurge.VerticalPush", 0.1); + config.addDefault("Abilities.Earth.RaiseEarth.Enabled", true); config.addDefault("Abilities.Earth.RaiseEarth.Description", "To use, simply left-click on an earthbendable block. " + "A column of earth will shoot upwards from that location. " diff --git a/src/com/projectkorra/ProjectKorra/Methods.java b/src/com/projectkorra/ProjectKorra/Methods.java index ef6ac1a0..81f2cfe4 100644 --- a/src/com/projectkorra/ProjectKorra/Methods.java +++ b/src/com/projectkorra/ProjectKorra/Methods.java @@ -94,6 +94,7 @@ import com.projectkorra.ProjectKorra.firebending.Cook; import com.projectkorra.ProjectKorra.firebending.FireBlast; import com.projectkorra.ProjectKorra.firebending.FireBurst; import com.projectkorra.ProjectKorra.firebending.FireJet; +import com.projectkorra.ProjectKorra.firebending.FirePassive; import com.projectkorra.ProjectKorra.firebending.FireShield; import com.projectkorra.ProjectKorra.firebending.FireStream; import com.projectkorra.ProjectKorra.firebending.Fireball; @@ -892,6 +893,31 @@ public class Methods { } return null; } + + public static Block getLavaSourceBlock(Player player, double range) { + Location location = player.getEyeLocation(); + Vector vector = location.getDirection().clone().normalize(); + for (double i = 0; i <= range; i++) { + Block block = location.clone().add(vector.clone().multiply(i)) + .getBlock(); + if (isRegionProtectedFromBuild(player, "LavaSurge", + location)) + continue; + if (isLavabendable(block, player)) { + if (TempBlock.isTempBlock(block)) { + TempBlock tb = TempBlock.get(block); + byte full = 0x0; + if (tb.state.getRawData() != full + && (tb.state.getType() != Material.LAVA || tb.state + .getType() != Material.STATIONARY_LAVA)) { + continue; + } + } + return block; + } + } + return null; + } public static boolean hasPermission(Player player, String ability) { if (player.hasPermission("bending.ability." + ability)) return true; @@ -926,6 +952,10 @@ public class Methods { BlockFace.SOUTH }; for (BlockFace face : faces) { Block blocki = block.getRelative(face); + if ((blocki.getType() == Material.LAVA || blocki.getType() == Material.STATIONARY_LAVA) + && blocki.getData() == full + && EarthPassive.canPhysicsChange(blocki)) + sources++; if ((blocki.getType() == Material.WATER || blocki.getType() == Material.STATIONARY_WATER) && blocki.getData() == full && WaterManipulation.canPhysicsChange(blocki)) @@ -1288,6 +1318,11 @@ public class Methods { if (block.getType() == Material.WATER || block.getType() == Material.STATIONARY_WATER) return true; return false; } + + public static boolean isLava(Block block) { + if (block.getType() == Material.LAVA || block.getType() == Material.STATIONARY_LAVA) return true; + return false; + } public static boolean isWaterAbility(String ability) { return AbilityModuleManager.waterbendingabilities.contains(ability); @@ -1302,6 +1337,13 @@ public class Methods { if (canPlantbend(player) && isPlant(block)) return true; return false; } + + public static boolean isLavabendable(Block block, Player player) { + byte full = 0x0; + if (TempBlock.isTempBlock(block)) return false; + if ((block.getType() == Material.LAVA || block.getType() == Material.STATIONARY_LAVA) && block.getData() == full) return true; + return false; + } public static boolean isWeapon(Material mat) { diff --git a/src/com/projectkorra/ProjectKorra/PKListener.java b/src/com/projectkorra/ProjectKorra/PKListener.java index fee2041f..7fc84b75 100644 --- a/src/com/projectkorra/ProjectKorra/PKListener.java +++ b/src/com/projectkorra/ProjectKorra/PKListener.java @@ -85,6 +85,8 @@ import com.projectkorra.ProjectKorra.earthbending.EarthPassive; import com.projectkorra.ProjectKorra.earthbending.EarthTunnel; import com.projectkorra.ProjectKorra.earthbending.EarthWall; import com.projectkorra.ProjectKorra.earthbending.Extraction; +import com.projectkorra.ProjectKorra.earthbending.LavaWall; +import com.projectkorra.ProjectKorra.earthbending.LavaWave; import com.projectkorra.ProjectKorra.earthbending.Shockwave; import com.projectkorra.ProjectKorra.earthbending.Tremorsense; import com.projectkorra.ProjectKorra.firebending.ArcOfFire; @@ -132,6 +134,14 @@ public class PKListener implements Listener { event.setCancelled(true); } } + + if (event.getDamager() != null) { + if (LavaWave.isBlockInWave(event.getDamager())) { + Bukkit.getServer().broadcastMessage("Hit by LavaSurge Lava"); + event.setCancelled(true); + } + } + } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @@ -250,6 +260,9 @@ public class PKListener implements Listener { if (event.isCancelled()) return; Block toblock = event.getToBlock(); Block fromblock = event.getBlock(); + if (Methods.isLava(fromblock)) { + event.setCancelled(!EarthPassive.canFlowFromTo(fromblock, toblock)); + } if (Methods.isWater(fromblock)) { event.setCancelled(!AirBubble.canFlowTo(toblock)); if (!event.isCancelled()) { @@ -407,6 +420,10 @@ public class PKListener implements Listener { new Extraction(player); } + if (abil.equalsIgnoreCase("LavaSurge")) { + LavaWall.form(player); + } + } if (Methods.isFireAbility(abil)) { @@ -718,6 +735,10 @@ public class PKListener implements Listener { if (abil.equalsIgnoreCase("Tremorsense")) { new Tremorsense(player); } + + if (abil.equalsIgnoreCase("LavaSurge")) { + new LavaWall(player); + } } if (Methods.isFireAbility(abil)) { if (Methods.isWeapon(player.getItemInHand().getType()) && !plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { @@ -834,6 +855,10 @@ public class PKListener implements Listener { } } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onEntityDamageBlock(EntityDamageByBlockEvent event) { + + } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onEntityDamageEvent(EntityDamageEvent event) { if (event.isCancelled()) return; @@ -872,6 +897,9 @@ public class PKListener implements Listener { if (!event.isCancelled()) { event.setCancelled(!WaterManipulation.canPhysicsChange(block)); } + if (!event.isCancelled()) { + event.setCancelled(!EarthPassive.canPhysicsChange(block)); + } if (!event.isCancelled()) { event.setCancelled(FreezeMelt.frozenblocks.containsKey(block)); } @@ -1129,6 +1157,7 @@ public class PKListener implements Listener { Block block = event.getBlock(); event.setCancelled(!WaterManipulation.canPhysicsChange(block)); + event.setCancelled(!EarthPassive.canPhysicsChange(block)); if (!event.isCancelled()) event.setCancelled(Illumination.blocks.containsKey(block)); if (!event.isCancelled()) @@ -1142,6 +1171,8 @@ public class PKListener implements Listener { event.setCancelled(true); if (!WaterManipulation.canPhysicsChange(event.getBlock())) event.setCancelled(true); + if (!EarthPassive.canPhysicsChange(event.getBlock())) + event.setCancelled(true); } diff --git a/src/com/projectkorra/ProjectKorra/TempBlock.java b/src/com/projectkorra/ProjectKorra/TempBlock.java index 5bb12bcf..1b255ead 100644 --- a/src/com/projectkorra/ProjectKorra/TempBlock.java +++ b/src/com/projectkorra/ProjectKorra/TempBlock.java @@ -52,7 +52,13 @@ public class TempBlock { if (instances.containsKey(block)) { instances.get(block).revertBlock(); } else { - if ((defaulttype == Material.WATER + if ((defaulttype == Material.LAVA + || defaulttype == Material.STATIONARY_LAVA || defaulttype == Material.AIR) + && Methods.isAdjacentToThreeOrMoreSources(block)) { + block.setType(Material.LAVA); + block.setData((byte) 0x0); + } + else if ((defaulttype == Material.WATER || defaulttype == Material.STATIONARY_WATER || defaulttype == Material.AIR) && Methods.isAdjacentToThreeOrMoreSources(block)) { block.setType(Material.WATER); diff --git a/src/com/projectkorra/ProjectKorra/airbending/AirBlast.java b/src/com/projectkorra/ProjectKorra/airbending/AirBlast.java index 500efee7..d94537ff 100644 --- a/src/com/projectkorra/ProjectKorra/airbending/AirBlast.java +++ b/src/com/projectkorra/ProjectKorra/airbending/AirBlast.java @@ -7,9 +7,12 @@ import org.bukkit.Effect; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.BlockState; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.material.Attachable; +import org.bukkit.material.Lever; import org.bukkit.util.Vector; import com.projectkorra.ProjectKorra.Flight; diff --git a/src/com/projectkorra/ProjectKorra/earthbending/EarthPassive.java b/src/com/projectkorra/ProjectKorra/earthbending/EarthPassive.java index bf470a22..b0033b30 100644 --- a/src/com/projectkorra/ProjectKorra/earthbending/EarthPassive.java +++ b/src/com/projectkorra/ProjectKorra/earthbending/EarthPassive.java @@ -12,6 +12,7 @@ import org.bukkit.entity.Player; import com.projectkorra.ProjectKorra.Element; import com.projectkorra.ProjectKorra.Methods; import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.TempBlock; public class EarthPassive { @@ -121,4 +122,48 @@ public class EarthPassive { public static void removeAll() { revertAllSand(); } + + public static boolean canPhysicsChange(Block block) { + if (LavaWall.affectedblocks.containsKey(block)) + return false; + if (LavaWall.wallblocks.containsKey(block)) + return false; + if (LavaWave.isBlockWave(block)) + return false; + if (TempBlock.isTempBlock(block)) + return false; + if (TempBlock.isTouchingTempBlock(block)) + return false; + return true; + } + + public static boolean canFlowFromTo(Block from, Block to) { + // if (to.getType() == Material.TORCH) + // return true; + if (LavaWall.affectedblocks.containsKey(to) + || LavaWall.affectedblocks.containsKey(from)) { + // Methods.verbose("waterwallaffectedblocks"); + return false; + } + if (LavaWall.wallblocks.containsKey(to) + || LavaWall.wallblocks.containsKey(from)) { + // Methods.verbose("waterwallwall"); + return false; + } + if (LavaWave.isBlockWave(to) || LavaWave.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; + } } diff --git a/src/com/projectkorra/ProjectKorra/earthbending/EarthbendingManager.java b/src/com/projectkorra/ProjectKorra/earthbending/EarthbendingManager.java index b28dbf49..fe1feae7 100644 --- a/src/com/projectkorra/ProjectKorra/earthbending/EarthbendingManager.java +++ b/src/com/projectkorra/ProjectKorra/earthbending/EarthbendingManager.java @@ -11,11 +11,11 @@ import com.projectkorra.ProjectKorra.RevertChecker; public class EarthbendingManager implements Runnable { public ProjectKorra plugin; - + public EarthbendingManager(ProjectKorra plugin) { this.plugin = plugin; } - + public void run() { EarthPassive.revertSands(); EarthPassive.handleMetalPassives(); @@ -41,10 +41,18 @@ public class EarthbendingManager implements Runnable { for (int ID : CompactColumn.instances.keySet()) { CompactColumn.progress(ID); } - + Shockwave.progressAll(); for (int ID : EarthBlast.instances.keySet()) { EarthBlast.progress(ID); } + + for (int ID : LavaWall.instances.keySet()) { + LavaWall.progress(ID); + } + for (int ID : LavaWave.instances.keySet()) { + LavaWave.progress(ID); + } + } } diff --git a/src/com/projectkorra/ProjectKorra/earthbending/LavaWall.java b/src/com/projectkorra/ProjectKorra/earthbending/LavaWall.java new file mode 100644 index 00000000..2d27e93b --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/earthbending/LavaWall.java @@ -0,0 +1,329 @@ +package com.projectkorra.ProjectKorra.earthbending; + +import java.util.ArrayList; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Bukkit; +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +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; +import com.projectkorra.ProjectKorra.firebending.FireBlast; + +public class LavaWall { + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + public static ConcurrentHashMap affectedblocks = new ConcurrentHashMap(); + public static ConcurrentHashMap wallblocks = new ConcurrentHashMap(); + private static double range = ProjectKorra.plugin.getConfig().getDouble("Abilities.Water.Surge.Wall.Range"); + private static final double defaultradius = ProjectKorra.plugin.getConfig().getDouble("Abilities.Water.Surge.Wall.Radius"); + private static final long interval = 30; + private static final byte full = 0x0; + Player player; + private Location location = null; + private Block sourceblock = null; + private Location firstdestination = null; + private Location targetdestination = null; + private Vector firstdirection = null; + private Vector targetdirection = null; + private boolean progressing = false; + private boolean settingup = false; + private boolean forming = false; + private long time; + private double radius = defaultradius; + + public LavaWall(Player player) { + this.player = player; + + if (LavaWave.instances.containsKey(player.getEntityId())) { + LavaWave wave = LavaWave.instances.get(player.getEntityId()); + if (!wave.progressing) { + LavaWave.launch(player); + return; + } + } + + if (AvatarState.isAvatarState(player)) { + radius = AvatarState.getValue(radius); + } + +// if (instances.containsKey(player.getEntityId())) { +// if (prepare()) { +// if (instances.containsKey(player.getEntityId())) { +// instances.get(player.getEntityId()).cancel(); +// } +// instances.put(player.getEntityId(), this); +// time = System.currentTimeMillis(); +// } +// } else if (prepare()) { +// if (instances.containsKey(player.getEntityId())) { +// instances.get(player.getEntityId()).cancel(); +// } +// instances.put(player.getEntityId(), this); +// time = System.currentTimeMillis(); +// } + if (LavaWave.cooldowns.containsKey(player.getName())) { + if (LavaWave.cooldowns.get(player.getName()) + ProjectKorra.plugin.getConfig().getLong("Properties.GlobalCooldown") >= System.currentTimeMillis()) { + return; + } else { + LavaWave.cooldowns.remove(player.getName()); + } + } + } + + public boolean prepare() { + cancelPrevious(); + Block block = Methods.getLavaSourceBlock(player, range); + if (block != null) { + sourceblock = block; + focusBlock(); + return true; + } + return false; + } + private void cancelPrevious() { + if (instances.containsKey(player.getEntityId())) { + LavaWall old = instances.get(player.getEntityId()); + if (old.progressing) { + old.removeLava(old.sourceblock); + } else { + old.cancel(); + } + } + } + public void cancel() { + unfocusBlock(); + } + private void focusBlock() { + location = sourceblock.getLocation(); + } + private void unfocusBlock() { + instances.remove(player.getEntityId()); + } + public void moveLava() { + if (sourceblock != null) { + targetdestination = player.getTargetBlock(Methods.getTransparentEarthbending(), (int) range).getLocation(); + if (targetdestination.distance(location) <= 1) { + progressing = false; + targetdestination = null; + } else { + progressing = true; + settingup = true; + firstdestination = getToEyeLevel(); + firstdirection = getDirection(sourceblock.getLocation(), firstdestination); + targetdirection = getDirection(firstdestination, targetdestination); + + if (!Methods.isAdjacentToThreeOrMoreSources(sourceblock)) { + sourceblock.setType(Material.AIR); + } + addLava(sourceblock); + } + } + } + private Location getToEyeLevel() { + Location loc = sourceblock.getLocation().clone(); + loc.setY(targetdestination.getY()); + return loc; + } + private Vector getDirection(Location location, Location destination) { + double x1, y1, z1; + double x0, y0, z0; + x1 = destination.getX(); + y1 = destination.getY(); + z1 = destination.getZ(); + x0 = location.getX(); + y0 = location.getY(); + z0 = location.getZ(); + return new Vector(x1 - x0, y1 - y0, z1 - z0); + } + public boolean progress() { + if (player.isDead() || !player.isOnline()) { + breakBlock(); + // instances.remove(player.getEntityId()); + return false; + } + if (!Methods.canBend(player.getName(), "LavaSurge")) { + if (!forming) + breakBlock(); + unfocusBlock(); + return false; + } + if (System.currentTimeMillis() - time >= interval) { + time = System.currentTimeMillis(); + if (!forming) { + } + if (Methods.getBoundAbility(player) == null) { + unfocusBlock(); + return false; + } + if (!progressing + && !Methods.getBoundAbility(player).equalsIgnoreCase("LavaSurge")) { + unfocusBlock(); + return false; + } + if (progressing + && (!player.isSneaking() || !Methods.getBoundAbility(player).equalsIgnoreCase("LavaSurge"))) { + breakBlock(); + return false; + } + if (!progressing) { + sourceblock.getWorld().playEffect(location, Effect.SMOKE, 4, (int) range); + return false; + } + if (forming) { + ArrayList blocks = new ArrayList(); + Location loc = Methods.getTargetedLocation(player, (int) range, 8, 9, 79); + location = loc.clone(); + Vector dir = player.getEyeLocation().getDirection(); + Vector vec; + Block block; + for (double i = 0; i <= radius; i += 0.5) { + for (double angle = 0; angle < 360; angle += 10) { + vec = Methods.getOrthogonalVector(dir.clone(), angle, i); + block = loc.clone().add(vec).getBlock(); + if (Methods.isRegionProtectedFromBuild(player, "LavaSurge", block.getLocation())) + continue; + if (wallblocks.containsKey(block)) { + blocks.add(block); + } else if (!blocks.contains(block) + && (block.getType() == Material.AIR + || block.getType() == Material.FIRE + || Methods.isLavabendable(block, player))) { + wallblocks.put(block, player); + addWallBlock(block); + blocks.add(block); + FireBlast.removeFireBlastsAroundPoint(block.getLocation(), 2); + } + } + } + for (Block blocki : wallblocks.keySet()) { + if (wallblocks.get(blocki) == player && !blocks.contains(blocki)) { + finalRemoveLava(blocki); + } + } + return true; + } + if (sourceblock.getLocation().distance(firstdestination) < .5 && settingup) { + settingup = false; + } + Vector direction; + if (settingup) { + direction = firstdirection; + } else { + direction = targetdirection; + } + location = location.clone().add(direction); + Block block = location.getBlock(); + if (block.getLocation().equals(sourceblock.getLocation())) { + location = location.clone().add(direction); + block = location.getBlock(); + } + if (block.getType() != Material.AIR) { + breakBlock(); + return false; + } + if (!progressing) { + breakBlock(); + return false; + } + addLava(block); + removeLava(sourceblock); + sourceblock = block; + if (location.distance(targetdestination) < 1) { + removeLava(sourceblock); + forming = true; + } + return true; + } + return false; + } + private void addWallBlock(Block block) { + new TempBlock(block, Material.STATIONARY_LAVA, (byte) 8); + } + private void breakBlock() { + finalRemoveLava(sourceblock); + for (Block block : wallblocks.keySet()) { + if (wallblocks.get(block) == player) { + finalRemoveLava(block); + } + } + instances.remove(player.getEntityId()); + } + private void removeLava(Block block) { + if (block != null) { + if (affectedblocks.containsKey(block)) { + if (!Methods.isAdjacentToThreeOrMoreSources(block)) { + TempBlock.revertBlock(block, Material.AIR); + } + affectedblocks.remove(block); + } + } + } + private static void finalRemoveLava(Block block) { + if (affectedblocks.containsKey(block)) { + TempBlock.revertBlock(block, Material.AIR); + affectedblocks.remove(block); + } + if (wallblocks.containsKey(block)) { + TempBlock.revertBlock(block, Material.AIR); + wallblocks.remove(block); + } + } + private void addLava(Block block) { + if (Methods.isRegionProtectedFromBuild(player, "LavaSurge", block.getLocation())) + return; + if (!TempBlock.isTempBlock(block)) { + new TempBlock(block, Material.STATIONARY_LAVA, (byte) 8); + affectedblocks.put(block, block); + } + } + public static void moveLava(Player player) { + if (instances.containsKey(player.getEntityId())) { + instances.get(player.getEntityId()).moveLava(); + } + } + public static boolean progress(int ID) { + return instances.get(ID).progress(); + } + public static void form(Player player) { + if (!instances.containsKey(player.getEntityId())) { + new LavaWave(player); + return; + } else { + if (Methods.isLavabendable(player.getTargetBlock(null, (int) LavaWave.defaultrange), player)) { + new LavaWave(player); + return; + } + } + moveLava(player); + } + public static void removeAll() { + for (Block block : affectedblocks.keySet()) { + TempBlock.revertBlock(block, Material.AIR); + affectedblocks.remove(block); + wallblocks.remove(block); + } + for (Block block : wallblocks.keySet()) { + TempBlock.revertBlock(block, Material.AIR); + affectedblocks.remove(block); + wallblocks.remove(block); + } + } + public static boolean wasBrokenFor(Player player, Block block) { + if (instances.containsKey(player.getEntityId())) { + LavaWall wall = instances.get(player.getEntityId()); + if (wall.sourceblock == null) + return false; + if (wall.sourceblock.equals(block)) + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/earthbending/LavaWave.java b/src/com/projectkorra/ProjectKorra/earthbending/LavaWave.java new file mode 100644 index 00000000..e230592f --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/earthbending/LavaWave.java @@ -0,0 +1,297 @@ +package com.projectkorra.ProjectKorra.earthbending; + +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.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; +import com.projectkorra.ProjectKorra.firebending.FireBlast; + +public class LavaWave { + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + public static ConcurrentHashMap cooldowns = new ConcurrentHashMap(); + private static final double defaultmaxradius = ProjectKorra.plugin.getConfig().getDouble("Abilities.Earth.LavaSurge.Radius"); + private static final double defaultfactor = ProjectKorra.plugin.getConfig().getDouble("Abilities.Earth.LavaSurge.HorizontalPush"); + private static final double upfactor = ProjectKorra.plugin.getConfig().getDouble("Abilities.Earth.LavaSurge.VerticalPush"); + private static final long interval = 30; + // public static ConcurrentHashMap affectedblocks = new ConcurrentHashMap(); + private static final byte full = 0x0; + // private static final byte half = 0x4; + static double defaultrange = 20; + // private static int damage = 5; + // private static double speed = 1.5; + Player player; + private Location location = null; + private Block sourceblock = null; + private Location targetdestination = null; + private Vector targetdirection = null; + private ConcurrentHashMap wave = new ConcurrentHashMap(); + private ConcurrentHashMap frozenblocks = new ConcurrentHashMap(); + private long time; + private double radius = 1; + private double maxradius = defaultmaxradius; + private double factor = defaultfactor; + double range = defaultrange; + boolean progressing = false; + boolean canhitself = true; + public LavaWave(Player player) { + this.player = player; + + if (AvatarState.isAvatarState(player)) { + maxradius = AvatarState.getValue(maxradius); + } + if (prepare()) { + if (instances.containsKey(player.getEntityId())) { + instances.get(player.getEntityId()).cancel(); + } + instances.put(player.getEntityId(), this); + time = System.currentTimeMillis(); + } + } + public boolean prepare() { + cancelPrevious(); + // Block block = player.getTargetBlock(null, (int) range); + Block block = Methods.getLavaSourceBlock(player, range); + if (block != null) { + sourceblock = block; + focusBlock(); + return true; + } + return false; + } + private void cancelPrevious() { + if (instances.containsKey(player.getEntityId())) { + LavaWave old = instances.get(player.getEntityId()); + if (old.progressing) { + old.breakBlock(); + } else { + old.cancel(); + } + } + } + public void cancel() { + unfocusBlock(); + } + private void focusBlock() { + location = sourceblock.getLocation(); + } + private void unfocusBlock() { + instances.remove(player.getEntityId()); + } + public void moveLava() { + if (cooldowns.containsKey(player.getName())) { + if (cooldowns.get(player.getName()) + ProjectKorra.plugin.getConfig().getLong("Properties.GlobalCooldown") >= System.currentTimeMillis()) { + return; + } else { + cooldowns.remove(player.getName()); + } + } + cooldowns.put(player.getName(), System.currentTimeMillis()); + if (sourceblock != null) { + if (sourceblock.getWorld() != player.getWorld()) { + return; + } + if (AvatarState.isAvatarState(player)) + factor = AvatarState.getValue(factor); + Entity target = Methods.getTargetedEntity(player, range, new ArrayList()); + if (target == null) { + targetdestination = player.getTargetBlock(Methods.getTransparentEarthbending(), (int) range).getLocation(); + } else { + targetdestination = ((LivingEntity) target).getEyeLocation(); + } + if (targetdestination.distance(location) <= 1) { + progressing = false; + targetdestination = null; + } else { + progressing = true; + targetdirection = getDirection(sourceblock.getLocation(), targetdestination).normalize(); + targetdestination = location.clone().add(targetdirection.clone().multiply(range)); + if (!Methods.isAdjacentToThreeOrMoreSources(sourceblock)) { + sourceblock.setType(Material.AIR); + } + addLava(sourceblock); + } + } + } + private Vector getDirection(Location location, Location destination) { + double x1, y1, z1; + double x0, y0, z0; + x1 = destination.getX(); + y1 = destination.getY(); + z1 = destination.getZ(); + x0 = location.getX(); + y0 = location.getY(); + z0 = location.getZ(); + return new Vector(x1 - x0, y1 - y0, z1 - z0); + } + public boolean progress() { + if (player.isDead() || !player.isOnline() || !Methods.canBend(player.getName(), "LavaSurge")) { + breakBlock(); + return false; + } + if (System.currentTimeMillis() - time >= interval) { + time = System.currentTimeMillis(); + if (Methods.getBoundAbility(player) == null) { + unfocusBlock(); + return false; + } + if (!progressing + && !Methods.getBoundAbility(player).equalsIgnoreCase("LavaSurge")) { + unfocusBlock(); + return false; + } + if (!progressing) { + sourceblock.getWorld().playEffect(location, Effect.SMOKE, 4, (int) range); + return false; + } + if (location.getWorld() != player.getWorld()) { + breakBlock(); + return false; + } + Vector direction = targetdirection; + location = location.clone().add(direction); + Block blockl = location.getBlock(); + ArrayList blocks = new ArrayList(); + if (!Methods.isRegionProtectedFromBuild(player, "LavaSurge", location) && (((blockl.getType() == Material.AIR + || blockl.getType() == Material.FIRE + || Methods.isPlant(blockl) + || Methods.isLava(blockl) + || Methods.isLavabendable(blockl, player))) && blockl.getType() != Material.LEAVES)) { + for (double i = 0; i <= radius; i += .5) { + for (double angle = 0; angle < 360; angle += 10) { + Vector vec = Methods.getOrthogonalVector(targetdirection, angle, i); + Block block = location.clone().add(vec).getBlock(); + if (!blocks.contains(block) && (block.getType() == Material.AIR + || block.getType() == Material.FIRE) + || Methods.isLavabendable(block, player)) { + blocks.add(block); + FireBlast.removeFireBlastsAroundPoint(block.getLocation(), 2); + } + } + + } + } + for (Block block : wave.keySet()) { + if (!blocks.contains(block)) + finalRemoveLava(block); + } + for (Block block : blocks) { + if (!wave.containsKey(block)) + addLava(block); + } + if (wave.isEmpty()) { + breakBlock(); + progressing = false; + return false; + } + for (Entity entity : Methods.getEntitiesAroundPoint(location, 2 * radius)) { + boolean knockback = false; + for (Block block : wave.keySet()) { + if (entity.getLocation().distance(block.getLocation()) <= 2) { + if (entity.getEntityId() != player.getEntityId() || canhitself) + knockback = true; + } + } + if (knockback) { + Vector dir = direction.clone(); + dir.setY(dir.getY() * upfactor); + entity.setVelocity(entity.getVelocity().clone() + .add(dir.clone().multiply(factor))); + entity.setFallDistance(0); + if (entity.getFireTicks() > 0) + entity.getWorld().playEffect(entity.getLocation(), Effect.EXTINGUISH, 0); + entity.setFireTicks(0); + } + } + if (!progressing) { + breakBlock(); + return false; + } + if (location.distance(targetdestination) < 1) { + progressing = false; + breakBlock(); + return false; + } + if (radius < maxradius) + radius += .5; + return true; + } + + return false; + } + private void breakBlock() { + for (Block block : wave.keySet()) { + finalRemoveLava(block); + } + instances.remove(player.getEntityId()); + } + private void finalRemoveLava(Block block) { + if (wave.containsKey(block)) { + TempBlock.revertBlock(block, Material.AIR); + wave.remove(block); + } + } + private void addLava(Block block) { + if (Methods.isRegionProtectedFromBuild(player, "LavaSurge", block.getLocation())) + return; + if (!TempBlock.isTempBlock(block)) { + new TempBlock(block, Material.STATIONARY_LAVA, (byte) 8); + wave.put(block, block); + } + } + private void clearWave() { + for (Block block : wave.keySet()) { + TempBlock.revertBlock(block, Material.AIR); + } + wave.clear(); + } + public static void moveLava(Player player) { + if (instances.containsKey(player.getEntityId())) { + instances.get(player.getEntityId()).moveLava(); + } + } + public static boolean progress(int ID) { + return instances.get(ID).progress(); + } + + public static boolean isBlockInWave(Block block) { + for (int ID: instances.keySet()) { + if (block.getLocation().distance(instances.get(ID).location) <= 2 * instances.get(ID).radius) { + return true; + } + return false; + } + return false; + } + public static boolean isBlockWave(Block block) { + for (int ID : instances.keySet()) { + if (instances.get(ID).wave.containsKey(block)) + return true; + } + return false; + } + public static void launch(Player player) { + moveLava(player); + } + public static void removeAll() { + for (int id : instances.keySet()) { + for (Block block : instances.get(id).wave.keySet()) { + block.setType(Material.AIR); + instances.get(id).wave.remove(block); + } + for (Block block : instances.get(id).frozenblocks.keySet()) { + block.setType(Material.AIR); + instances.get(id).frozenblocks.remove(block); + } + } + } +} diff --git a/src/config.yml b/src/config.yml index ba2f9d53..0260f606 100644 --- a/src/config.yml +++ b/src/config.yml @@ -263,6 +263,12 @@ Abilities: Cooldown: 10000 TripleLootChance: 15 DoubleLootChance: 40 + LavaSurge: + Enabled: true + Description: "This ability allows an Earthbender to bend an existing Lava Source to create a large wave that deals damage and knocks back anything in its path. To use, simply tap sneak (Default: Shift) while targetting a source of lava. Once a source has been selected, left click to launch the wave off into the direction you are looking. This ability has a small knockback and does a fair amount of damage." + Radius: 3 + HorizontalPush: 0.5 + VerticalPush: 0.1 RaiseEarth: Enabled: true Description: "To use, simply left-click on an earthbendable block. A column of earth will shoot upwards from that location. Anything in the way of the column will be brought up with it, leaving talented benders the ability to trap brainless entities up there. Additionally, simply sneak (default shift) looking at an earthbendable block. A wall of earth will shoot upwards from that location. Anything in the way of the wall will be brought up with it." diff --git a/src/plugin.yml b/src/plugin.yml index f9ed64ac..09f8a18c 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -87,6 +87,7 @@ permissions: bending.earth.passive: true bending.earth.metalbending: true bending.earth.grapplinghook: true + bending.ability.LavaSurge bending.fire: default: true description: Grants access to all firebending abilities.