diff --git a/src/com/projectkorra/ProjectKorra/BendingManager.java b/src/com/projectkorra/ProjectKorra/BendingManager.java index 149ad273..86474103 100644 --- a/src/com/projectkorra/ProjectKorra/BendingManager.java +++ b/src/com/projectkorra/ProjectKorra/BendingManager.java @@ -20,6 +20,7 @@ import com.projectkorra.ProjectKorra.airbending.AirSpout; import com.projectkorra.ProjectKorra.airbending.Tornado; import com.projectkorra.ProjectKorra.chiblocking.ChiPassive; import com.projectkorra.ProjectKorra.earthbending.Catapult; +import com.projectkorra.ProjectKorra.earthbending.EarthColumn; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; import com.projectkorra.ProjectKorra.firebending.FireJet; import com.projectkorra.ProjectKorra.firebending.FirePassive; @@ -90,6 +91,10 @@ public class BendingManager implements Runnable { Catapult.progress(ID); } + for (int ID: EarthColumn.instances.keySet()) { + EarthColumn.progress(ID); + } + FireStream.dissipateAll(); } catch (Exception e) { Methods.stopBending(); diff --git a/src/com/projectkorra/ProjectKorra/ConfigManager.java b/src/com/projectkorra/ProjectKorra/ConfigManager.java index 5a3dc60b..152326c8 100644 --- a/src/com/projectkorra/ProjectKorra/ConfigManager.java +++ b/src/com/projectkorra/ProjectKorra/ConfigManager.java @@ -149,6 +149,19 @@ public class ConfigManager { config.addDefault("Abilities.Earth.Catapult.Speed", 12); config.addDefault("Abilities.Earth.Catapult.Push", 5); + 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. " + + "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. "); + config.addDefault("Abilities.Earth.RaiseEarth.Column.Height", 6); + config.addDefault("Abilities.Earth.RaiseEarth.Wall.Range", 15); + config.addDefault("Abilities.Earth.RaiseEarth.Wall.Height", 6); + config.addDefault("Abilities.Earth.RaiseEarth.Wall.Width", 6); + config.addDefault("Abilities.Fire.FireJet.Enabled", true); config.addDefault("Abilities.Fire.FireJet.Description", "This ability is used for a limited burst of flight for firebenders. Clicking with this " + "ability selected will launch you in the direction you're looking, granting you " diff --git a/src/com/projectkorra/ProjectKorra/Methods.java b/src/com/projectkorra/ProjectKorra/Methods.java index 4b3658a4..a87876c8 100644 --- a/src/com/projectkorra/ProjectKorra/Methods.java +++ b/src/com/projectkorra/ProjectKorra/Methods.java @@ -33,6 +33,7 @@ import org.bukkit.util.Vector; import com.projectkorra.ProjectKorra.Ability.AbilityModule; 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; diff --git a/src/com/projectkorra/ProjectKorra/PKListener.java b/src/com/projectkorra/ProjectKorra/PKListener.java index e0b54fce..64cf7256 100644 --- a/src/com/projectkorra/ProjectKorra/PKListener.java +++ b/src/com/projectkorra/ProjectKorra/PKListener.java @@ -50,6 +50,7 @@ import com.projectkorra.ProjectKorra.airbending.Tornado; import com.projectkorra.ProjectKorra.chiblocking.ChiPassive; import com.projectkorra.ProjectKorra.chiblocking.Paralyze; import com.projectkorra.ProjectKorra.earthbending.Catapult; +import com.projectkorra.ProjectKorra.earthbending.EarthColumn; import com.projectkorra.ProjectKorra.earthbending.EarthPassive; import com.projectkorra.ProjectKorra.firebending.Enflamed; import com.projectkorra.ProjectKorra.firebending.FireJet; @@ -166,6 +167,15 @@ public class PKListener implements Listener { new WaterSpout(player); } } + + if (Methods.isEarthAbility(abil)) { + if (Methods.isWeapon(player.getItemInHand().getType()) && !plugin.getConfig().getBoolean("Properties.Earth.CanBendWithWeapons")) { + return; + } + if (abil.equalsIgnoreCase("RaiseEarth")) { + new EarthWall(player); + } + } } } @@ -322,6 +332,10 @@ public class PKListener implements Listener { if (abil.equalsIgnoreCase("Catapult")) { new Catapult(player); } + + if (abil.equalsIgnoreCase("RaiseEarth")) { + new EarthColumn(player); + } } if (Methods.isFireAbility(abil)) { if (Methods.isWeapon(player.getItemInHand().getType()) && !plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) { diff --git a/src/com/projectkorra/ProjectKorra/earthbending/EarthColumn.java b/src/com/projectkorra/ProjectKorra/earthbending/EarthColumn.java new file mode 100644 index 00000000..10be1c3a --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/earthbending/EarthColumn.java @@ -0,0 +1,246 @@ +package com.projectkorra.ProjectKorra.earthbending; + +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Location; +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; + +public class EarthColumn { + + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + public static final int standardheight = ProjectKorra.plugin.getConfig().getInt("Abilities.Earth.RaiseEarth.Column.Height"); + + private static ConcurrentHashMap alreadydoneblocks = new ConcurrentHashMap(); + private static ConcurrentHashMap baseblocks = new ConcurrentHashMap(); + public static ConcurrentHashMap cooldowns = new ConcurrentHashMap(); + + private static int ID = Integer.MIN_VALUE; + + private static double range = 20; + private static double speed = 8; + private static final Vector direction = new Vector(0, 1, 0); + + private static long interval = (long) (1000. / speed); + + private Location origin; + private Location location; + private Block block; + private int distance; + private Player player; + private int id; + private long time; + private int height = standardheight; + private ConcurrentHashMap affectedblocks = new ConcurrentHashMap(); + + public EarthColumn(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()); + } + } + + try { + block = Methods.getEarthSourceBlock(player, range); + if (block == null) + return; + origin = block.getLocation(); + location = origin.clone(); + distance = Methods.getEarthbendableBlocksLength(player, block, + direction.clone().multiply(-1), height); + } catch (IllegalStateException e) { + return; + } + + this.player = player; + + loadAffectedBlocks(); + + if (distance != 0) { + if (canInstantiate()) { + id = ID; + instances.put(id, this); + cooldowns.put(player.getName(), System.currentTimeMillis()); + if (ID >= Integer.MAX_VALUE) { + ID = Integer.MIN_VALUE; + } + ID++; + time = System.currentTimeMillis() - interval; + } + } + } + + public EarthColumn(Player player, Location origin) { + this.origin = origin; + location = origin.clone(); + block = location.getBlock(); + this.player = player; + distance = Methods.getEarthbendableBlocksLength(player, block, direction + .clone().multiply(-1), height); + + loadAffectedBlocks(); + + if (distance != 0) { + if (canInstantiate()) { + id = ID; + instances.put(id, this); + if (ID >= Integer.MAX_VALUE) { + ID = Integer.MIN_VALUE; + } + ID++; + time = System.currentTimeMillis() - interval; + } + } + } + + public EarthColumn(Player player, Location origin, int height) { + this.height = height; + this.origin = origin; + location = origin.clone(); + block = location.getBlock(); + this.player = player; + distance = Methods.getEarthbendableBlocksLength(player, block, direction + .clone().multiply(-1), height); + + loadAffectedBlocks(); + + if (distance != 0) { + if (canInstantiate()) { + id = ID; + instances.put(id, this); + if (ID >= Integer.MAX_VALUE) { + ID = Integer.MIN_VALUE; + } + ID++; + time = System.currentTimeMillis() - interval; + } + } + } + + private void loadAffectedBlocks() { + affectedblocks.clear(); + Block thisblock; + for (int i = 0; i <= distance; i++) { + thisblock = block.getWorld().getBlockAt( + location.clone().add(direction.clone().multiply(-i))); + affectedblocks.put(thisblock, thisblock); + if (CompactColumn.blockInAllAffectedBlocks(thisblock)) + CompactColumn.revertBlock(thisblock); + } + } + + private boolean blockInAffectedBlocks(Block block) { + if (affectedblocks.containsKey(block)) { + return true; + } + return false; + } + + public static boolean blockInAllAffectedBlocks(Block block) { + for (int ID : instances.keySet()) { + if (instances.get(ID).blockInAffectedBlocks(block)) + return true; + } + return false; + } + + public static void revertBlock(Block block) { + for (int ID : instances.keySet()) { + if (instances.get(ID).blockInAffectedBlocks(block)) { + instances.get(ID).affectedblocks.remove(block); + } + } + } + + private boolean canInstantiate() { + for (Block block : affectedblocks.keySet()) { + if (blockInAllAffectedBlocks(block) + || alreadydoneblocks.containsKey(block)) { + return false; + } + } + return true; + } + + public boolean progress() { + if (System.currentTimeMillis() - time >= interval) { + time = System.currentTimeMillis(); + if (!moveEarth()) { + instances.remove(id); + for (Block block : affectedblocks.keySet()) { + alreadydoneblocks.put(block, block); + } + baseblocks.put( + location.clone() + .add(direction.clone().multiply( + -1 * (distance - 1))).getBlock(), + (distance - 1)); + + return false; + } + } + return true; + } + + private boolean moveEarth() { + Block block = location.getBlock(); + location = location.add(direction); + Methods.moveEarth(player, block, direction, distance); + loadAffectedBlocks(); + + if (location.distance(origin) >= distance) { + return false; + } + + return true; + } + + public static boolean progress(int ID) { + return instances.get(ID).progress(); + } + + public static boolean blockIsBase(Block block) { + if (baseblocks.containsKey(block)) { + return true; + } + return false; + } + + public static void removeBlockBase(Block block) { + if (baseblocks.containsKey(block)) { + baseblocks.remove(block); + } + + } + + public static void removeAll() { + for (int id : instances.keySet()) { + instances.remove(id); + } + } + + public static void resetBlock(Block block) { + + if (alreadydoneblocks.containsKey(block)) { + alreadydoneblocks.remove(block); + } + + } + + public static String getDescription() { + return "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. "; + } + +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/earthbending/EarthWall.java b/src/com/projectkorra/ProjectKorra/earthbending/EarthWall.java new file mode 100644 index 00000000..a7dcfecf --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/earthbending/EarthWall.java @@ -0,0 +1,101 @@ +package com.projectkorra.ProjectKorra.earthbending; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.Ability.AvatarState; + +public class EarthWall { + + private static final int range = ProjectKorra.plugin.getConfig().getInt("Abilities.Earth.RaiseEarth.Wall.Range"); + private static final int defaultheight = ProjectKorra.plugin.getConfig().getInt("Abilities.Earth.RaiseEarth.Wall.Height"); + private static final int defaulthalfwidth = ProjectKorra.plugin.getConfig().getInt("Abilities.Earth.RaiseEarth.Wall.Width") / 2; + + private int height = defaultheight; + private int halfwidth = defaulthalfwidth; + + public EarthWall(Player player) { + if (EarthColumn.cooldowns.containsKey(player.getName())) { + if (EarthColumn.cooldowns.get(player.getName()) + ProjectKorra.plugin.getConfig().getLong("Properties.GlobalCooldown") >= System.currentTimeMillis()) { + return; + } else { + EarthColumn.cooldowns.remove(player.getName()); + } + } + + if (AvatarState.isAvatarState(player)) { + height = (int) (2. / 5. * (double) AvatarState.getValue(height)); + halfwidth = AvatarState.getValue(halfwidth); + } + + Vector direction = player.getEyeLocation().getDirection().normalize(); + + double ox, oy, oz; + ox = -direction.getZ(); + oy = 0; + oz = direction.getX(); + + Vector orth = new Vector(ox, oy, oz); + orth = orth.normalize(); + + Block sblock = Methods.getEarthSourceBlock(player, range); + Location origin; + if (sblock == null) { + origin = player.getTargetBlock(Methods.getTransparentEarthbending(), + range).getLocation(); + } else { + origin = sblock.getLocation(); + } + World world = origin.getWorld(); + + boolean cooldown = false; + + for (int i = -halfwidth; i <= halfwidth; i++) { + Block block = world.getBlockAt(origin.clone().add( + orth.clone().multiply((double) i))); + // if (block.getType() == Material.AIR || block.isLiquid()) { + if (Methods.isTransparentToEarthbending(player, block)) { + for (int j = 1; j < height; j++) { + block = block.getRelative(BlockFace.DOWN); + if (Methods.isEarthbendable(player, block)) { + cooldown = true; + new EarthColumn(player, block.getLocation(), height); + // } else if (block.getType() != Material.AIR + // && !block.isLiquid()) { + } else if (!Methods + .isTransparentToEarthbending(player, block)) { + break; + } + } + } else if (Methods.isEarthbendable(player, + block.getRelative(BlockFace.UP))) { + for (int j = 1; j < height; j++) { + block = block.getRelative(BlockFace.UP); + // if (block.getType() == Material.AIR || block.isLiquid()) + // { + if (Methods.isTransparentToEarthbending(player, block)) { + cooldown = true; + new EarthColumn(player, block.getRelative( + BlockFace.DOWN).getLocation(), height); + } else if (!Methods.isEarthbendable(player, block)) { + break; + } + } + } else if (Methods.isEarthbendable(player, block)) { + cooldown = true; + new EarthColumn(player, block.getLocation(), height); + } + } + + if (cooldown) + EarthColumn.cooldowns.put(player.getName(), System.currentTimeMillis()); + + } + +} \ No newline at end of file diff --git a/src/config.yml b/src/config.yml index cbbd4e27..f56a2503 100644 --- a/src/config.yml +++ b/src/config.yml @@ -93,6 +93,15 @@ Abilities: Length: 7 Speed: 12 Push: 5 + 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." + Column: + Height: 6 + Wall: + Range: 15 + Height: 6 + Width: 6 Fire: FireJet: Enabled: true