diff --git a/src/com/projectkorra/ProjectKorra/BendingManager.java b/src/com/projectkorra/ProjectKorra/BendingManager.java index 06c3636e..b55e4422 100644 --- a/src/com/projectkorra/ProjectKorra/BendingManager.java +++ b/src/com/projectkorra/ProjectKorra/BendingManager.java @@ -23,6 +23,7 @@ import com.projectkorra.ProjectKorra.earthbending.Catapult; import com.projectkorra.ProjectKorra.earthbending.CompactColumn; import com.projectkorra.ProjectKorra.earthbending.EarthColumn; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; +import com.projectkorra.ProjectKorra.firebending.Cook; import com.projectkorra.ProjectKorra.firebending.FireJet; import com.projectkorra.ProjectKorra.firebending.FirePassive; import com.projectkorra.ProjectKorra.firebending.FireStream; @@ -74,6 +75,7 @@ public class BendingManager implements Runnable { AirScooter.progressAll(); AirSpout.spoutAll(); WaterSpout.handleSpouts(Bukkit.getServer()); + Cook.progressAll(); for (int ID: Tornado.instances.keySet()) { Tornado.progress(ID); } diff --git a/src/com/projectkorra/ProjectKorra/ConfigManager.java b/src/com/projectkorra/ProjectKorra/ConfigManager.java index fe934033..f983cf5a 100644 --- a/src/com/projectkorra/ProjectKorra/ConfigManager.java +++ b/src/com/projectkorra/ProjectKorra/ConfigManager.java @@ -186,6 +186,18 @@ public class ConfigManager { config.addDefault("Abilities.Fire.FireJet.Duration", 1500); config.addDefault("Abilities.Fire.FireJet.Cooldown", 6000); + config.addDefault("Abilities.Fire.HeatControl.Enabled", true); + config.addDefault("Abilities.Fire.HeatControl.Description", "While this ability is selected, the firebender becomes impervious " + + "to fire damage and cannot be ignited. " + + "If the user left-clicks with this ability, the targeted area will be " + + "extinguished, although it will leave any creature burning engulfed in flames. " + + "This ability can also cool lava. If this ability is used while targetting ice or snow, it" + + " will instead melt blocks in that area. Finally, sneaking with this ability will cook any food in your hand."); + config.addDefault("Abilities.Fire.HeatControl.Extinguish.Range", 20); + config.addDefault("Abilities.Fire.HeatControl.Extinguish.Radius", 7); + config.addDefault("Abilities.Fire.HeatControl.Melt.Range", 15); + config.addDefault("Abilities.Fire.HeatControl.Melt.Radius", 5); + plugin.getConfig().addDefault("Abilities.Chi.Passive.FallReductionFactor", 0.5); plugin.getConfig().addDefault("Abilities.Chi.Passive.Speed", 1); plugin.getConfig().addDefault("Abilities.Chi.Passive.Jump", 2); diff --git a/src/com/projectkorra/ProjectKorra/Methods.java b/src/com/projectkorra/ProjectKorra/Methods.java index a87876c8..cefaeee4 100644 --- a/src/com/projectkorra/ProjectKorra/Methods.java +++ b/src/com/projectkorra/ProjectKorra/Methods.java @@ -35,7 +35,6 @@ import com.projectkorra.ProjectKorra.Ability.AbilityModuleManager; import com.projectkorra.ProjectKorra.Ability.AvatarState; import com.projectkorra.ProjectKorra.earthbending.EarthColumn; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; -import com.projectkorra.ProjectKorra.waterbending.FreezeMelt; import com.projectkorra.ProjectKorra.waterbending.WaterCore; public class Methods { @@ -338,26 +337,27 @@ public class Methods { } public static boolean isAdjacentToThreeOrMoreSources(Block block) { - if (TempBlock.isTempBlock(block)) return false; + if (TempBlock.isTempBlock(block)) + return false; int sources = 0; byte full = 0x0; - BlockFace[] faces = {BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, BlockFace.SOUTH }; - for (BlockFace face: faces) { + BlockFace[] faces = { BlockFace.EAST, BlockFace.WEST, BlockFace.NORTH, + BlockFace.SOUTH }; + for (BlockFace face : faces) { Block blocki = block.getRelative(face); - /* - * TODO : Checks for WaterManip and other abilities. - */ - - if (isWater(block) && blocki.getData() == full) { + if ((blocki.getType() == Material.WATER || blocki.getType() == Material.STATIONARY_WATER) + && blocki.getData() == full + && WaterManipulation.canPhysicsChange(blocki)) sources++; - } if (FreezeMelt.frozenblocks.containsKey(blocki)) { - if (FreezeMelt.frozenblocks.get(blocki) == full) sources++; - } else if (blocki.getType() == Material.ICE){ + if (FreezeMelt.frozenblocks.get(blocki) == full) + sources++; + } else if (blocki.getType() == Material.ICE) { sources++; } } - if (sources >= 2) return true; + if (sources >= 2) + return true; return false; } @@ -662,8 +662,8 @@ public class Methods { public static boolean moveEarth(Player player, Block block, Vector direction, int chainlength, boolean throwplayer) { if (isEarthbendable(player, block)) { -// && !isRegionProtectedFromBuild(player, Abilities.RaiseEarth, -// block.getLocation())) { + // && !isRegionProtectedFromBuild(player, Abilities.RaiseEarth, + // block.getLocation())) { boolean up = false; boolean down = false; diff --git a/src/com/projectkorra/ProjectKorra/PKListener.java b/src/com/projectkorra/ProjectKorra/PKListener.java index 88bda5a8..f99f3c67 100644 --- a/src/com/projectkorra/ProjectKorra/PKListener.java +++ b/src/com/projectkorra/ProjectKorra/PKListener.java @@ -55,7 +55,9 @@ import com.projectkorra.ProjectKorra.earthbending.CompactColumn; import com.projectkorra.ProjectKorra.earthbending.EarthColumn; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; import com.projectkorra.ProjectKorra.earthbending.EarthWall; +import com.projectkorra.ProjectKorra.firebending.Cook; import com.projectkorra.ProjectKorra.firebending.Enflamed; +import com.projectkorra.ProjectKorra.firebending.Extinguish; import com.projectkorra.ProjectKorra.firebending.FireJet; import com.projectkorra.ProjectKorra.firebending.FireStream; import com.projectkorra.ProjectKorra.waterbending.Bloodbending; @@ -182,6 +184,15 @@ public class PKListener implements Listener { new Collapse(player); } } + + if (Methods.isFireAbility(abil)) { + if (Methods.isWeapon(player.getItemInHand().getType()) && !plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { + return; + } + if (abil.equalsIgnoreCase("HeatControl")) { + new Cook(player); + } + } } } @@ -355,6 +366,9 @@ public class PKListener implements Listener { if (abil.equalsIgnoreCase("FireJet")) { new FireJet(player); } + if (abil.equalsIgnoreCase("HeatControl")) { + new Extinguish(player); + } } } } diff --git a/src/com/projectkorra/ProjectKorra/firebending/Cook.java b/src/com/projectkorra/ProjectKorra/firebending/Cook.java new file mode 100644 index 00000000..14222c8a --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/firebending/Cook.java @@ -0,0 +1,130 @@ +package com.projectkorra.ProjectKorra.firebending; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Effect; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import com.projectkorra.ProjectKorra.Methods; + +public class Cook { + + private static ConcurrentHashMap instances = new ConcurrentHashMap(); + + private static final long cooktime = 2000; + private static final Material[] cookables = { Material.RAW_BEEF, + Material.RAW_CHICKEN, Material.RAW_FISH, Material.PORK, + Material.POTATO_ITEM }; + + private Player player; + private ItemStack items; + private long time; + + public Cook(Player player) { + this.player = player; + items = player.getItemInHand(); + time = System.currentTimeMillis(); + if (isCookable(items.getType())) { + instances.put(player, this); + } + } + + private void progress() { + if (player.isDead() || !player.isOnline()) { + cancel(); + return; + } + + if (Methods.getBoundAbility(player) == null) { + cancel(); + return; + } + if (!player.isSneaking() + || !Methods.getBoundAbility(player).equalsIgnoreCase("HeatControl")) { + cancel(); + return; + } + + if (!items.equals(player.getItemInHand())) { + time = System.currentTimeMillis(); + items = player.getItemInHand(); + } + + if (!isCookable(items.getType())) { + cancel(); + return; + } + + if (System.currentTimeMillis() > time + cooktime) { + cook(); + time = System.currentTimeMillis(); + } + + player.getWorld().playEffect(player.getEyeLocation(), + Effect.MOBSPAWNER_FLAMES, 0, 10); + } + + private void cancel() { + instances.remove(player); + } + + private static boolean isCookable(Material material) { + return Arrays.asList(cookables).contains(material); + } + + private void cook() { + Material cooked = getCooked(items.getType()); + ItemStack newitem = new ItemStack(cooked); + HashMap cantfit = player.getInventory().addItem( + newitem); + for (int id : cantfit.keySet()) { + player.getWorld() + .dropItem(player.getEyeLocation(), cantfit.get(id)); + } + int amount = items.getAmount(); + if (amount == 1) { + player.getInventory() + .clear(player.getInventory().getHeldItemSlot()); + // items.setType(Material.AIR); + } else { + items.setAmount(amount - 1); + } + } + + private Material getCooked(Material material) { + Material cooked = Material.AIR; + switch (material) { + case RAW_BEEF: + cooked = Material.COOKED_BEEF; + break; + case RAW_FISH: + cooked = Material.COOKED_FISH; + break; + case RAW_CHICKEN: + cooked = Material.COOKED_CHICKEN; + break; + case PORK: + cooked = Material.GRILLED_PORK; + break; + case POTATO_ITEM: + cooked = Material.BAKED_POTATO; + break; + } + return cooked; + } + + public static void progressAll() { + for (Player player : instances.keySet()) { + instances.get(player).progress(); + } + } + + public static void removeAll() { + instances.clear(); + } + +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/firebending/Extinguish.java b/src/com/projectkorra/ProjectKorra/firebending/Extinguish.java new file mode 100644 index 00000000..91ec0bb3 --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/firebending/Extinguish.java @@ -0,0 +1,94 @@ +package com.projectkorra.ProjectKorra.firebending; + +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Effect; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +import com.projectkorra.ProjectKorra.Element; +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.airbending.AirBlast; + +public class Extinguish { + + private static double defaultrange = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.HeatControl.Extinguish.Range"); + private static double defaultradius = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.HeatControl.Extinguish.Radius"); + public static ConcurrentHashMap cooldowns = new ConcurrentHashMap(); + + private static byte full = AirBlast.full; + + public Extinguish(Player player) { + + if (cooldowns.containsKey(player.getName())) { + if (cooldowns.get(player.getName()) + ProjectKorra.plugin.getConfig().getLong("Properties.GlobalCooldown") >= System.currentTimeMillis()) { + return; + } else { + cooldowns.remove(player.getName()); + } + } + + double range = Methods.firebendingDayAugment(defaultrange, + player.getWorld()); + if (Methods.isMeltable(player.getTargetBlock(null, (int) range))) { + new HeatMelt(player); + return; + } + double radius = Methods.firebendingDayAugment(defaultradius, + player.getWorld()); + for (Block block : Methods.getBlocksAroundPoint( + player.getTargetBlock(null, (int) range).getLocation(), radius)) { +// if (Methods.isRegionProtectedFromBuild(player, Abilities.Blaze, +// block.getLocation())) +// continue; + if (block.getType() == Material.FIRE) { + block.setType(Material.AIR); + block.getWorld().playEffect(block.getLocation(), + Effect.EXTINGUISH, 0); + } else if (block.getType() == Material.STATIONARY_LAVA) { + block.setType(Material.OBSIDIAN); + block.getWorld().playEffect(block.getLocation(), + Effect.EXTINGUISH, 0); + } else if (block.getType() == Material.LAVA) { + if (block.getData() == full) { + block.setType(Material.OBSIDIAN); + } else { + block.setType(Material.COBBLESTONE); + } + block.getWorld().playEffect(block.getLocation(), + Effect.EXTINGUISH, 0); + } + } + + cooldowns.put(player.getName(), System.currentTimeMillis()); + } + + public static boolean canBurn(Player player) { + if (Methods.getBoundAbility(player) != null) { + if (Methods.getBoundAbility(player).equalsIgnoreCase("HeatControl") || FireJet.checkTemporaryImmunity(player)) { + player.setFireTicks(0); + return false; + } + } + + if (player.getFireTicks() > 80 + && Methods.canBendPassive(player.getName(), Element.Fire)) { + player.setFireTicks(80); + } + + // Methods.verbose(player.getFireTicks()); + + return true; + } + + public static String getDescription() { + return "While this ability is selected, the firebender becomes impervious " + + "to fire damage and cannot be ignited. " + + "If the user left-clicks with this ability, the targeted area will be " + + "extinguished, although it will leave any creature burning engulfed in flames. " + + "This ability can also cool lava. If this ability is used while targetting ice or snow, it" + + " will instead melt blocks in that area. Finally, sneaking with this ability will cook any food in your hand."; + } +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/firebending/HeatMelt.java b/src/com/projectkorra/ProjectKorra/firebending/HeatMelt.java new file mode 100644 index 00000000..9c173179 --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/firebending/HeatMelt.java @@ -0,0 +1,40 @@ +package com.projectkorra.ProjectKorra.firebending; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.waterbending.Melt; + +public class HeatMelt { + + private static final int range = ProjectKorra.plugin.getConfig().getInt("Abilities.Fire.HeatControl.Melt.Range"); + private static final int radius = ProjectKorra.plugin.getConfig().getInt("Abilities.Fire.HeatControl.Melt.Radius"); + + public HeatMelt(Player player) { + Location location = Methods.getTargetedLocation(player, + (int) Methods.firebendingDayAugment(range, player.getWorld())); + for (Block block : Methods.getBlocksAroundPoint(location, + (int) Methods.firebendingDayAugment(radius, player.getWorld()))) { + if (Methods.isMeltable(block)) { + Melt.melt(player, block); + } else if (isHeatable(block)) { + heat(block); + } + } + } + + private static void heat(Block block) { + if (block.getType() == Material.OBSIDIAN) { + block.setType(Material.LAVA); + block.setData((byte) 0x0); + } + } + + private static boolean isHeatable(Block block) { + return false; + } +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/waterbending/FreezeMelt.java b/src/com/projectkorra/ProjectKorra/waterbending/FreezeMelt.java deleted file mode 100644 index 244ea7af..00000000 --- a/src/com/projectkorra/ProjectKorra/waterbending/FreezeMelt.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.projectkorra.ProjectKorra.waterbending; - -import java.util.concurrent.ConcurrentHashMap; - -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.entity.Player; - -import com.projectkorra.ProjectKorra.TempBlock; - - -public class FreezeMelt { - - public static ConcurrentHashMap frozenblocks = new ConcurrentHashMap(); - - public static void freeze(Player player, Block block) { - if (TempBlock.isTempBlock(block)) - return; - byte data = block.getData(); - block.setType(Material.ICE); - frozenblocks.put(block, data); - } - - 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 void handleFrozenBlocks() { -// for (Block block : frozenblocks.keySet()) { -// if (canThaw(block)) -// thaw(block); -// } -// } - -// public static boolean canThaw(Block block) { -// if (frozenblocks.containsKey(block)) { -// for (Player player : block.getWorld().getPlayers()) { -// // if (Tools.getBendingAbility(player) == Abilities.OctopusForm) { -// // if (block.getLocation().distance(player.getLocation()) <= OctopusForm.radius + 2) -// // return false; -// // } -// if (Tools.hasAbility(player, Abilities.PhaseChange) && Tools.canBend(player, Abilities.PhaseChange)) { -// double range = Tools.waterbendingNightAugment(defaultrange, -// player.getWorld()); -// if (AvatarState.isAvatarState(player)) { -// range = AvatarState.getValue(range); -// } -// if (block.getLocation().distance(player.getLocation()) <= range) -// return false; -// } -// } -// } -// if (!WaterManipulation.canPhysicsChange(block)) -// return false; -// return true; -// } - - private static void thawAll() { - for (Block block : frozenblocks.keySet()) { - if (block.getType() == Material.ICE) { - byte data = frozenblocks.get(block); - block.setType(Material.WATER); - block.setData(data); - frozenblocks.remove(block); - } - } - } - - public static void removeAll() { - thawAll(); - } -} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/waterbending/Melt.java b/src/com/projectkorra/ProjectKorra/waterbending/Melt.java new file mode 100644 index 00000000..bbf82b1d --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/waterbending/Melt.java @@ -0,0 +1,95 @@ +package com.projectkorra.ProjectKorra.waterbending; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.TempBlock; +import com.projectkorra.ProjectKorra.Ability.AvatarState; + +public class Melt { + + private static final int defaultrange = FreezeMelt.defaultrange; + private static final int defaultradius = FreezeMelt.defaultradius; + private static final int defaultevaporateradius = 3; + private static final int seaLevel = ConfigManager.seaLevel; + + private static final byte full = 0x0; + + public Melt(Player player) { + BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); + + if (bPlayer.isOnCooldown(Abilities.PhaseChange)) + return; + + int range = (int) Methods.waterbendingNightAugment(defaultrange, + player.getWorld()); + int radius = (int) Methods.waterbendingNightAugment(defaultradius, + player.getWorld()); + + if (AvatarState.isAvatarState(player)) { + range = AvatarState.getValue(range); + radius = AvatarState.getValue(radius); + } + boolean evaporate = false; + Location location = Methods.getTargetedLocation(player, range); + if (Methods.isWater(player.getTargetBlock(null, range)) + && !(player.getEyeLocation().getBlockY() <= 62)) { + evaporate = true; + radius = (int) Methods.waterbendingNightAugment( + defaultevaporateradius, player.getWorld()); + } + for (Block block : Methods.getBlocksAroundPoint(location, radius)) { + if (evaporate) { + if (block.getY() > seaLevel) + evaporate(player, block); + } else { + melt(player, block); + } + } + + bPlayer.cooldown(Abilities.PhaseChange); + } + + public static void melt(Player player, Block block) { + if (Methods.isRegionProtectedFromBuild(player, Abilities.PhaseChange, + block.getLocation())) + return; + if (!Wave.canThaw(block)) { + Wave.thaw(block); + return; + } + if (!Torrent.canThaw(block)) { + Torrent.thaw(block); + return; + } + if (Methods.isMeltable(block) && !TempBlock.isTempBlock(block) + && WaterManipulation.canPhysicsChange(block)) { + if (block.getType() == Material.SNOW) { + block.setType(Material.AIR); + return; + } + if (FreezeMelt.frozenblocks.containsKey(block)) { + FreezeMelt.thaw(block); + } else { + block.setType(Material.WATER); + block.setData(full); + } + } + } + + public static void evaporate(Player player, Block block) { + if (Methods.isRegionProtectedFromBuild(player, Abilities.PhaseChange, + block.getLocation())) + return; + if (Methods.isWater(block) && !TempBlock.isTempBlock(block) + && WaterManipulation.canPhysicsChange(block)) { + block.setType(Material.AIR); + block.getWorld().playEffect(block.getLocation(), Effect.SMOKE, 1); + } + } + +} \ No newline at end of file diff --git a/src/config.yml b/src/config.yml index 73484b82..7dcab93c 100644 --- a/src/config.yml +++ b/src/config.yml @@ -115,6 +115,15 @@ Abilities: Speed: 0.7 Duration: 1500 Cooldown: 6000 + HeatControl: + Enabled: true + Description: "While this ability is selected, the firebender becomes impervious to fire damage and cannot be ignited. If the user left-clicks with this ability, the targeted area will be extinguished, although it will leave any creature burning engulfed in flames. This ability can also cool lava. If this ability is used while targeting ice or snow, it will instead melt blocks in that area. Finally, sneaking with this ability will cook any food in your hand." + Extinguish: + Range: 20 + Radius: 7 + Melt: + Range: 15 + Radius: 5 Chi: Passive: FallReductionFactor: 0.5