diff --git a/Dev Builds/Korra.jar b/Dev Builds/Korra.jar index c708a711..b5ba364f 100644 Binary files a/Dev Builds/Korra.jar and b/Dev Builds/Korra.jar differ diff --git a/src/com/projectkorra/ProjectKorra/Ability/AbilityModuleManager.java b/src/com/projectkorra/ProjectKorra/Ability/AbilityModuleManager.java index 364c03a7..8259290f 100644 --- a/src/com/projectkorra/ProjectKorra/Ability/AbilityModuleManager.java +++ b/src/com/projectkorra/ProjectKorra/Ability/AbilityModuleManager.java @@ -90,6 +90,7 @@ public class AbilityModuleManager { if (a == StockAbilities.Torrent) shiftabilities.add(a.name()); if (a == StockAbilities.WaterManipulation) shiftabilities.add(a.name()); if (a == StockAbilities.IceSpike) shiftabilities.add(a.name()); + if (a == StockAbilities.IceBlast) shiftabilities.add(a.name()); if (a == StockAbilities.WaterWave) shiftabilities.add(a.name()); } } diff --git a/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java b/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java index 51240f78..97ab7ada 100644 --- a/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java +++ b/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java @@ -18,14 +18,15 @@ public enum StockAbilities { AvatarState, // Project Korra - Extraction, Smokescreen, Combustion, LavaSurge, LavaFlow, Suffocate, WaterWave; + Extraction, Smokescreen, Combustion, LavaSurge, LavaFlow, Suffocate, IceBlast, WaterWave; private enum AirbendingAbilities { AirBlast, AirBubble, AirShield, AirSuction, AirSwipe, Tornado, AirScooter, AirSpout, AirBurst, Suffocate; } private enum WaterbendingAbilities { - WaterBubble, PhaseChange, HealingWaters, WaterManipulation, Surge, Bloodbending, WaterSpout, IceSpike, OctopusForm, Torrent, WaterWave; + WaterBubble, PhaseChange, HealingWaters, WaterManipulation, Surge, Bloodbending, WaterSpout, IceSpike, IceBlast, OctopusForm, Torrent, WaterWave; + } private enum EarthbendingAbilities { diff --git a/src/com/projectkorra/ProjectKorra/BendingPlayer.java b/src/com/projectkorra/ProjectKorra/BendingPlayer.java index af343412..0ea6c3e3 100644 --- a/src/com/projectkorra/ProjectKorra/BendingPlayer.java +++ b/src/com/projectkorra/ProjectKorra/BendingPlayer.java @@ -14,7 +14,7 @@ public class BendingPlayer { UUID uuid; String player; ArrayList elements; - HashMap abilities; + private HashMap abilities; ConcurrentHashMap cooldowns; boolean permaRemoved; boolean isToggled; @@ -26,7 +26,7 @@ public class BendingPlayer { this.uuid = uuid; this.player = player; this.elements = elements; - this.abilities = abilities; + this.setAbilities(abilities); cooldowns = new ConcurrentHashMap(); this.permaRemoved = permaRemoved; isToggled = true; @@ -34,15 +34,15 @@ public class BendingPlayer { players.put(player, this); } - + public boolean isOnCooldown(String ability) { return this.cooldowns.containsKey(ability); } - + public void addCooldown(String ability, long cooldown) { this.cooldowns.put(ability, cooldown + System.currentTimeMillis()); } - + public void removeCooldown(String ability) { this.cooldowns.remove(ability); } @@ -107,4 +107,11 @@ public class BendingPlayer { public boolean isChiBlocked() { return blockedChi; } + + public void setAbilities(HashMap abilities) { + this.abilities = abilities; + for (int i = 1; i <= 9; i++) { + DBConnection.sql.modifyQuery("UPDATE pk_players SET slot" + i + " = '" + (abilities.get(i) == null ? null: abilities.get(i)) + "' WHERE uuid = '" + uuid + "'"); + } + } } diff --git a/src/com/projectkorra/ProjectKorra/Commands.java b/src/com/projectkorra/ProjectKorra/Commands.java index f336e4eb..e9069a9a 100644 --- a/src/com/projectkorra/ProjectKorra/Commands.java +++ b/src/com/projectkorra/ProjectKorra/Commands.java @@ -26,6 +26,7 @@ import org.bukkit.scheduler.BukkitTask; import com.projectkorra.ProjectKorra.Ability.AbilityModuleManager; import com.projectkorra.ProjectKorra.Ability.StockAbilities; +import com.projectkorra.ProjectKorra.Objects.Preset; import com.projectkorra.ProjectKorra.Utilities.GrapplingHookAPI; public class Commands { @@ -36,7 +37,7 @@ public class Commands { this.plugin = plugin; init(); } - + /* * Element Aliases */ @@ -64,15 +65,16 @@ public class Commands { String[] importaliases = {"import", "i"}; String[] givealiases = {"give", "g", "spawn"}; String[] invinciblealiases = {"invincible", "inv"}; + String[] presetaliases = {"preset", "presets", "pre", "set"}; /* * Item Aliases */ - + public static Set invincible = new HashSet(); - + String[] grapplinghookaliases = {"grapplinghook", "grapplehook", "hook", "ghook"}; - + public static boolean debug = ProjectKorra.plugin.getConfig().getBoolean("debug"); public static boolean isToggledForAll = false; @@ -91,22 +93,122 @@ public class Commands { s.sendMessage(ChatColor.RED + "/bending bind [Ability] # " + ChatColor.YELLOW + "Bind an ability."); return true; } - if (Arrays.asList(invinciblealiases).contains(args[0].toLowerCase())) { - if (!s.hasPermission("bending.command.invincible")) { - s.sendMessage(ChatColor.RED + "You don't have permission to do that."); - return true; - } - + if (Arrays.asList(presetaliases).contains(args[0].toLowerCase())) { if (!(s instanceof Player)) { s.sendMessage(ChatColor.RED + "This command is only usable by players."); return true; } + Player player = (Player) s; + + String[] deletealiases = {"delete", "d", "del"}; + String[] createaliases = {"create", "c", "save"}; + String[] listaliases = {"list", "l"}; + if (args.length == 2 && Arrays.asList(listaliases).contains(args[1].toLowerCase())) { + if (!s.hasPermission("bending.command.preset.list")) { + s.sendMessage(ChatColor.RED + "You don't have permission to do that."); + return true; + } + + List listnames = Preset.presets.get(player.getUniqueId()); + List ln2 = new ArrayList(); + + if (listnames == null || listnames.isEmpty()) { + s.sendMessage(ChatColor.RED + "You don't have any presets."); + return true; + } + + for (Preset preset: listnames) { + ln2.add(preset.getName()); + } + + s.sendMessage(ChatColor.GREEN + "Your Presets: " + ChatColor.DARK_AQUA + ln2.toString()); + return true; + + }else if (args.length != 3) { // bending preset bind|create|delete {name} + s.sendMessage(ChatColor.GOLD + "Proper Usage: /bending preset create|bind|list|delete [name]"); + return true; + } + + String name = args[2]; + + if (Arrays.asList(deletealiases).contains(args[1].toLowerCase())) { + if (!s.hasPermission("bending.command.preset.delete")) { + s.sendMessage(ChatColor.RED + "You don't have permission to do that."); + return true; + } + if (!Preset.presetExists(player, name)) { + s.sendMessage(ChatColor.RED + "You don't have a preset with that name."); + return true; + } + + Preset preset = Preset.getPreset(player, name); + preset.delete(); + s.sendMessage(ChatColor.GREEN + "You have deleted your preset named: " + name); + } + + if (Arrays.asList(bindaliases).contains(args[1].toLowerCase())) { + if (!s.hasPermission("bending.command.preset.bind")) { + s.sendMessage(ChatColor.RED + "You don't have permission to do that."); + return true; + } + + if (!Preset.presetExists(player, name)) { + s.sendMessage(ChatColor.RED + "You don't have a preset with that name."); + return true; + } + + Preset.bindPreset(player, name); + s.sendMessage(ChatColor.GREEN + "Your bound slots have been set to match the " + name + " preset."); + return true; + } + + if (Arrays.asList(createaliases).contains(args[1].toLowerCase())) { + if (!s.hasPermission("bending.command.preset.create")) { + s.sendMessage(ChatColor.RED + "You don't have permission to do that."); + return true; + } + + int limit = Methods.getMaxPresets(player); + + if (Preset.presets.get(player) != null && Preset.presets.get(player).size() >= limit) { + s.sendMessage(ChatColor.RED + "You have reached your max number of Presets."); + return true; + } + + if (Preset.presetExists(player, name)) { + s.sendMessage(ChatColor.RED + "A preset with that name already exists."); + return true; + } + + BendingPlayer bPlayer = Methods.getBendingPlayer(player.getName()); + + if (bPlayer == null) return true; + + HashMap abilities = bPlayer.getAbilities(); + Preset preset = new Preset(player.getUniqueId(), name, abilities); + preset.save(); + s.sendMessage(ChatColor.GREEN + "Created preset with the name: " + name); + return true; + } + + } + if (Arrays.asList(invinciblealiases).contains(args[0].toLowerCase())) { + if (!s.hasPermission("bending.command.invincible")) { + s.sendMessage(ChatColor.RED + "You don't have permission to do that."); + return true; + } + + if (!(s instanceof Player)) { + s.sendMessage(ChatColor.RED + "This command is only usable by players."); + return true; + } + if (args.length != 1) { s.sendMessage(ChatColor.GOLD + "Proper Usage: /bending invincible"); return true; } - + if (!invincible.contains(s.getName())) { /* * Player is not invincible. @@ -124,24 +226,29 @@ public class Commands { s.sendMessage(ChatColor.RED + "You don't have permission to do that."); return true; } - + if (args.length < 3) { s.sendMessage(ChatColor.GOLD + "Proper Usage: /bending give [Player] [Item] "); return true; } - + Player player = Bukkit.getPlayer(args[1]); - + if (player == null) { s.sendMessage(ChatColor.RED + "That player is not online."); return true; } - - if (Arrays.asList(grapplinghookaliases).contains(args[2])) { + + if (Arrays.asList(grapplinghookaliases).contains(args[2].toLowerCase())) { /* * They are spawning in a grappling hook. * bending give [Player] grapplinghook [# of Uses] */ + + if (args.length != 3) { + s.sendMessage(ChatColor.GOLD + "Proper Usage: /bending give GrapplingHook <#OfUses>"); + return true; + } int uses; try { uses = Integer.parseInt(args[3]); @@ -150,7 +257,7 @@ public class Commands { s.sendMessage(ChatColor.GOLD + "Example: /bending give " + s.getName() + " grapplinghook 25"); return true; } - + ItemStack hook = GrapplingHookAPI.createHook(uses); player.getInventory().addItem(hook); s.sendMessage(ChatColor.GREEN + "A grappling hook with " + uses + " uses has been added to your inventory."); @@ -192,7 +299,7 @@ public class Commands { } BendingPlayer bPlayer = Methods.getBendingPlayer(s.getName()); if (args.length == 1) { - bPlayer.abilities.clear(); + bPlayer.getAbilities().clear(); for (int i = 1; i <= 9; i++) { Methods.saveAbility(bPlayer, i, null); } @@ -207,8 +314,8 @@ public class Commands { s.sendMessage(ChatColor.RED + "The slot must be an integer between 0 and 9."); return true; } - if (bPlayer.abilities.get(slot) != null) { - bPlayer.abilities.remove(slot); + if (bPlayer.getAbilities().get(slot) != null) { + bPlayer.getAbilities().remove(slot); Methods.saveAbility(bPlayer, slot, null); } s.sendMessage("You have cleared slot #" + slot); @@ -404,7 +511,7 @@ public class Commands { if (bPlayer.hasElement(Element.Fire)) elements.append("f"); if (bPlayer.hasElement(Element.Chi)) elements.append("c"); - HashMap abilities = bPlayer.abilities; + HashMap abilities = bPlayer.getAbilities(); ResultSet rs2 = DBConnection.sql.readQuery("SELECT * FROM pk_players WHERE uuid = '" + bPlayer.uuid.toString() + "'"); @@ -533,7 +640,7 @@ public class Commands { return true; } BendingPlayer bPlayer = Methods.getBendingPlayer(s.getName()); - HashMap abilities = bPlayer.abilities; + HashMap abilities = bPlayer.getAbilities(); if (abilities.isEmpty()) { s.sendMessage("You don't have any bound abilities."); @@ -611,7 +718,7 @@ public class Commands { } if (args.length == 2) { - + Player p = Bukkit.getPlayer(args[1]); if (p == null) { s.sendMessage(ChatColor.GREEN + "You are running a lookup of an offline player, this may take a second."); @@ -802,14 +909,14 @@ public class Commands { } BendingPlayer bPlayer = Methods.getBendingPlayer(player.getName()); - + if (bPlayer.isPermaRemoved()) { bPlayer.permaRemoved = false; Methods.savePermaRemoved(bPlayer); s.sendMessage(ChatColor.RED + "You have restored the bending of: " + ChatColor.DARK_AQUA + player.getName()); return true; } - + bPlayer.elements.clear(); Methods.removeUnusableAbilities(player.getName()); Methods.saveElements(bPlayer); diff --git a/src/com/projectkorra/ProjectKorra/ConfigManager.java b/src/com/projectkorra/ProjectKorra/ConfigManager.java index 45da5876..de4e4a59 100644 --- a/src/com/projectkorra/ProjectKorra/ConfigManager.java +++ b/src/com/projectkorra/ProjectKorra/ConfigManager.java @@ -85,6 +85,11 @@ public class ConfigManager { config.addDefault("Properties.Chi.CanBendWithWeapons", true); + ArrayList disabledWorlds = new ArrayList(); + disabledWorlds.add("TestWorld"); + disabledWorlds.add("TestWorld2"); + config.addDefault("Properties.DisabledWorlds", disabledWorlds); + config.addDefault("Abilities.AvatarState.Enabled", true); config.addDefault("Abilities.AvatarState.Description", "The signature ability of the Avatar, this is a toggle. Click to activate to become " + "nearly unstoppable. While in the Avatar State, the user takes severely reduced damage from " @@ -224,6 +229,11 @@ public class ConfigManager { + "be at least partially submerged in water."); config.addDefault("Abilities.Water.HealingWaters.Radius", 5); config.addDefault("Abilities.Water.HealingWaters.Interval", 750); + + config.addDefault("Abilities.Water.IceBlast.Enabled", true); + config.addDefault("Abilities.Water.IceBlast.Damage", 3); + config.addDefault("Abilities.Water.IceBlast.Range", 20); + config.addDefault("Abilities.Water.IceBlast.Description", "This ability offers a powerful ice utility for Waterbenders. It can be used to fire an explosive burst of ice at an opponent, spraying ice and snow around it. To use, simply tap sneak (Default: Shift) while targeting a block of ice to select it as a source. From there, you can just left click to send the blast off at your opponent."); config.addDefault("Abilities.Water.IceSpike.Enabled", true); config.addDefault("Abilities.Water.IceSpike.Description", "This ability has many functions. Clicking while targetting ice, or an entity over some ice, " @@ -296,6 +306,13 @@ public class ConfigManager { + "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."); config.addDefault("Abilities.Water.WaterSpout.Height", 20); + + config.addDefault("Abilities.Water.WaterWave.Enabled", true); + config.addDefault("Abilities.Water.WaterWave.Description", "This ability provides a Waterbender with boosted mobility and transportation. To use, first click a source block to select it; then hold sneak (Default: Shift) to begin streaming the water around you. While the water is streaming around you let go of sneak and the water will form underneath your feet, blasting you off into the direction that you are facing. Additionally, taping sneak while riding the wave still stop it."); + config.addDefault("Abilities.Water.WaterWave.Range", 6); + config.addDefault("Abilities.Water.WaterWave.ChargeTime", 1000); + config.addDefault("Abilities.Water.WaterWave.FlightTime", 2000); + config.addDefault("Abilities.Water.WaterWave.Speed", 1.2); config.addDefault("Abilities.Earth.Passive.Duration", 2500); diff --git a/src/com/projectkorra/ProjectKorra/DBConnection.java b/src/com/projectkorra/ProjectKorra/DBConnection.java index ff77a023..65464e80 100644 --- a/src/com/projectkorra/ProjectKorra/DBConnection.java +++ b/src/com/projectkorra/ProjectKorra/DBConnection.java @@ -40,6 +40,25 @@ public class DBConnection { + " PRIMARY KEY (id));"; sql.modifyQuery(query); } + + if (!sql.tableExists("pk_presets")) { + ProjectKorra.log.info("Creating pk_presets table"); + String query = "CREATE TABLE `pk_presets` (" + + "`id` int(32) NOT NULL AUTO_INCREMENT," + + "`uuid` varchar(255)," + + "`name` varchar(255)," + + "`slot1` varchar(255)," + + "`slot2` varchar(255)," + + "`slot3` varchar(255)," + + "`slot4` varchar(255)," + + "`slot5` varchar(255)," + + "`slot6` varchar(255)," + + "`slot7` varchar(255)," + + "`slot8` varchar(255)," + + "`slot9` varchar(255)," + + " PRIMARY KEY (id));"; + sql.modifyQuery(query); + } } else { sql = new SQLite(ProjectKorra.log, "[ProjectKorra] Establishing SQLite Connection.", "projectkorra.db", ProjectKorra.plugin.getDataFolder().getAbsolutePath()); ((SQLite) sql).open(); @@ -63,6 +82,24 @@ public class DBConnection { + "`slot9` TEXT(255));"; sql.modifyQuery(query); } + + if (!sql.tableExists("pk_presets")) { + ProjectKorra.log.info("Creating pk_presets table"); + String query = "CREATE TABLE `pk_presets` (" + + "`id` INTEGER PRIMARY KEY," + + "`uuid` TEXT(255)," + + "`name` TEXT(255)," + + "`slot1` TEXT(255)," + + "`slot2` TEXT(255)," + + "`slot3` TEXT(255)," + + "`slot4` TEXT(255)," + + "`slot5` TEXT(255)," + + "`slot6` TEXT(255)," + + "`slot7` TEXT(255)," + + "`slot8` TEXT(255)," + + "`slot9` TEXT(255));"; + sql.modifyQuery(query); + } } } } \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/Methods.java b/src/com/projectkorra/ProjectKorra/Methods.java index b27c13ae..1b866fec 100644 --- a/src/com/projectkorra/ProjectKorra/Methods.java +++ b/src/com/projectkorra/ProjectKorra/Methods.java @@ -36,6 +36,7 @@ import org.bukkit.World.Environment; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Entity; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.LivingEntity; @@ -173,7 +174,7 @@ public class Methods { public static void bindAbility(Player player, String ability) { int slot = player.getInventory().getHeldItemSlot() + 1; BendingPlayer bPlayer = getBendingPlayer(player.getName()); - bPlayer.abilities.put(slot, ability); + bPlayer.getAbilities().put(slot, ability); if (isAirAbility(ability)) { player.sendMessage(getAirColor() + "Succesfully bound " + ability + " to slot " + slot); } @@ -204,7 +205,7 @@ public class Methods { */ public static void bindAbility(Player player, String ability, int slot) { BendingPlayer bPlayer = getBendingPlayer(player.getName()); - bPlayer.abilities.put(slot, ability); + bPlayer.getAbilities().put(slot, ability); if (isAirAbility(ability)) { player.sendMessage(getAirColor() + "Succesfully bound " + ability + " to slot " + slot); } @@ -262,6 +263,7 @@ public class Methods { BendingPlayer bPlayer = getBendingPlayer(player); Player p = Bukkit.getPlayer(player); if (bPlayer == null) return false; + if (plugin.getConfig().getStringList("Properties.DisabledWorlds") != null && plugin.getConfig().getStringList("Properties.DisabledWorlds").contains(p.getWorld().getName())) return false; if (Commands.isToggledForAll) return false; if (!bPlayer.isToggled) return false; if (p == null) return false; @@ -293,6 +295,7 @@ public class Methods { if (!bPlayer.isToggled) return false; if (!bPlayer.hasElement(element)) return false; if (isRegionProtectedFromBuild(p, null, p.getLocation())) return false; + if (bPlayer.blockedChi) return false; return true; } @@ -545,7 +548,7 @@ public class Methods { if (bPlayer == null) return null; int slot = player.getInventory().getHeldItemSlot() + 1; - return bPlayer.abilities.get(slot); + return bPlayer.getAbilities().get(slot); } public static long getGlobalCooldown() { @@ -939,6 +942,20 @@ public class Methods { } return null; } + + public static Block getIceSourceBlock(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, "IceBlast", location)) + continue; + if (isIcebendable(block)) { + return block; + } + } + return null; + } public static boolean hasPermission(Player player, String ability) { if (player.hasPermission("bending.ability." + ability)) return true; @@ -1369,6 +1386,12 @@ public class Methods { return true; return false; } + + public static boolean isIcebendable(Block block) { + if (block.getType() == Material.ICE) return true; + if (block.getType() == Material.PACKED_ICE && plugin.getConfig().getBoolean("Properties.Water.CanBendPackedIce")) return true; + return false; + } public static boolean isWeapon(Material mat) { @@ -1673,7 +1696,7 @@ public class Methods { finalabilities.put(i, slots.get(i)); } } - bPlayer.abilities = finalabilities; + bPlayer.setAbilities(finalabilities); } catch (Exception ex) { } @@ -1796,7 +1819,7 @@ public class Methods { if (bPlayer == null) return; String uuid = bPlayer.uuid.toString(); - HashMap abilities = bPlayer.abilities; + HashMap abilities = bPlayer.getAbilities(); DBConnection.sql.modifyQuery("UPDATE pk_players SET slot" + slot + " = '" + (abilities.get(slot) == null ? null : abilities.get(slot)) + "' WHERE uuid = '" + uuid + "'"); } @@ -1971,5 +1994,14 @@ public class Methods { } return null; } + + public static int getMaxPresets(Player player) { + if (player.isOp()) return 500; + int cap = 0; + for (int i = 0; i <= 500; i++) { + if (player.hasPermission("bending.command.presets.create." + i)) cap = i; + } + return cap; + } } diff --git a/src/com/projectkorra/ProjectKorra/Objects/Preset.java b/src/com/projectkorra/ProjectKorra/Objects/Preset.java new file mode 100644 index 00000000..0608d02b --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/Objects/Preset.java @@ -0,0 +1,129 @@ +package com.projectkorra.ProjectKorra.Objects; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import com.projectkorra.ProjectKorra.BendingPlayer; +import com.projectkorra.ProjectKorra.DBConnection; +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.ProjectKorra; + +public class Preset { + + public static ConcurrentHashMap> presets = new ConcurrentHashMap>(); + + UUID uuid; + HashMap abilities; + String name; + + public Preset(UUID uuid, String name, HashMap abilities) { + this.uuid = uuid; + this.name = name; + this.abilities = abilities; + if (!presets.containsKey(uuid)) { + presets.put(uuid, new ArrayList()); + } + presets.get(uuid).add(this); + } + + public static void loadPresets(Player player) { + UUID uuid = player.getUniqueId(); + if (uuid == null) return; + ResultSet rs2 = DBConnection.sql.readQuery("SELECT * FROM pk_presets WHERE uuid = '" + uuid.toString() + "'"); + try { + if (rs2.next()) { // Presets exist. + int i = 0; + do { + HashMap moves = new HashMap(); + for (int total = 1; total <= 9; total++) { + String slot = rs2.getString("slot" + total); + if (slot != null) moves.put(total, slot); + } + new Preset(uuid, rs2.getString("name"), moves); + i++; + } while (rs2.next()); + ProjectKorra.log.info("Loaded " + i + " presets for " + player.getName()); + } + } catch (SQLException ex) { + ex.printStackTrace(); + } + } + + public static void bindPreset(Player player, String name) { + BendingPlayer bPlayer = Methods.getBendingPlayer(player.getName()); + if (bPlayer == null) return; + if (!presets.containsKey(player.getUniqueId())) return; + for (Preset preset: presets.get(player.getUniqueId())) { + if (preset.name.equalsIgnoreCase(name)) { // We found it + bPlayer.setAbilities(preset.abilities); + } + } + } + + public static boolean presetExists(Player player, String name) { + if (!presets.containsKey(player.getUniqueId())) return false; + boolean exists = false; + for (Preset preset: presets.get(player.getUniqueId())) { + if (preset.name.equalsIgnoreCase(name)) exists = true; + } + return exists; + } + + public static Preset getPreset(Player player, String name) { + if (!presets.containsKey(player.getUniqueId())) return null; + for (Preset preset: presets.get(player.getUniqueId())) { + if (preset.name.equalsIgnoreCase(name)) return preset; + } + return null; + } + + public void delete() { + ResultSet rs2 = DBConnection.sql.readQuery("SELECT * FROM pk_presets WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + try { + if (rs2.next()) { + DBConnection.sql.modifyQuery("DELETE FROM pk_presets WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + } + } catch (SQLException ex) { + ex.printStackTrace(); + } + presets.get(uuid).remove(this); + } + + public String getName() { + return this.name; + } + + public void save() { + ResultSet rs2 = DBConnection.sql.readQuery("SELECT * FROM pk_presets WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + try { + if (!rs2.next()) { // Preset doesn't already exists. + DBConnection.sql.modifyQuery("INSERT INTO pk_presets (uuid, name) VALUES ('" + uuid.toString() + "', '" + name + "')"); + } + } catch (SQLException ex) { + ex.printStackTrace(); + } + + /* + * Now we know the preset exists in the SQL table, so we can manipulate it normally. + */ + + DBConnection.sql.modifyQuery("UPDATE pk_presets SET slot1 = '" + abilities.get(1) + "' WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + DBConnection.sql.modifyQuery("UPDATE pk_presets SET slot2 = '" + abilities.get(2) + "' WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + DBConnection.sql.modifyQuery("UPDATE pk_presets SET slot3 = '" + abilities.get(3) + "' WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + DBConnection.sql.modifyQuery("UPDATE pk_presets SET slot4 = '" + abilities.get(4) + "' WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + DBConnection.sql.modifyQuery("UPDATE pk_presets SET slot5 = '" + abilities.get(5) + "' WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + DBConnection.sql.modifyQuery("UPDATE pk_presets SET slot6 = '" + abilities.get(6) + "' WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + DBConnection.sql.modifyQuery("UPDATE pk_presets SET slot7 = '" + abilities.get(7) + "' WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + DBConnection.sql.modifyQuery("UPDATE pk_presets SET slot8 = '" + abilities.get(8) + "' WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + DBConnection.sql.modifyQuery("UPDATE pk_presets SET slot9 = '" + abilities.get(9) + "' WHERE uuid = '" + uuid.toString() + "' AND name = '" + name + "'"); + } + +} diff --git a/src/com/projectkorra/ProjectKorra/PKListener.java b/src/com/projectkorra/ProjectKorra/PKListener.java index f3b627f8..5b94b349 100644 --- a/src/com/projectkorra/ProjectKorra/PKListener.java +++ b/src/com/projectkorra/ProjectKorra/PKListener.java @@ -61,6 +61,7 @@ import org.bukkit.util.Vector; import com.projectkorra.ProjectKorra.Ability.AvatarState; import com.projectkorra.ProjectKorra.CustomEvents.PlayerGrappleEvent; +import com.projectkorra.ProjectKorra.Objects.Preset; import com.projectkorra.ProjectKorra.Utilities.GrapplingHookAPI; import com.projectkorra.ProjectKorra.airbending.AirBlast; import com.projectkorra.ProjectKorra.airbending.AirBubble; @@ -111,6 +112,7 @@ import com.projectkorra.ProjectKorra.firebending.RingOfFire; import com.projectkorra.ProjectKorra.firebending.WallOfFire; import com.projectkorra.ProjectKorra.waterbending.Bloodbending; import com.projectkorra.ProjectKorra.waterbending.FreezeMelt; +import com.projectkorra.ProjectKorra.waterbending.IceBlast; import com.projectkorra.ProjectKorra.waterbending.IceSpike2; import com.projectkorra.ProjectKorra.waterbending.Melt; import com.projectkorra.ProjectKorra.waterbending.OctopusForm; @@ -283,8 +285,9 @@ public class PKListener implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent e) { - Methods.createBendingPlayer(e.getPlayer().getUniqueId(), e.getPlayer().getName()); Player player = e.getPlayer(); + Methods.createBendingPlayer(e.getPlayer().getUniqueId(), player.getName()); + Preset.loadPresets(player); String append = ""; boolean chatEnabled = ProjectKorra.plugin.getConfig().getBoolean("Properties.Chat.Enable"); if ((player.hasPermission("bending.avatar") || Methods.getBendingPlayer(player.getName()).elements.size() > 1) && chatEnabled) { @@ -384,6 +387,9 @@ public class PKListener implements Listener { if (abil.equalsIgnoreCase("Bloodbending")) { new Bloodbending(player); } + if (abil.equalsIgnoreCase("IceBlast")) { + new IceBlast(player); + } if (abil.equalsIgnoreCase("IceSpike")) { new IceSpike2(player); } @@ -713,6 +719,9 @@ public class PKListener implements Listener { if (abil.equalsIgnoreCase("Bloodbending")) { Bloodbending.launch(player); } + if (abil.equalsIgnoreCase("IceBlast")) { + IceBlast.activate(player); + } if (abil.equalsIgnoreCase("IceSpike")) { IceSpike2.activate(player); } diff --git a/src/com/projectkorra/ProjectKorra/ProjectKorra.java b/src/com/projectkorra/ProjectKorra/ProjectKorra.java index 29b14677..50d74584 100644 --- a/src/com/projectkorra/ProjectKorra/ProjectKorra.java +++ b/src/com/projectkorra/ProjectKorra/ProjectKorra.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import com.projectkorra.ProjectKorra.Ability.AbilityModuleManager; +import com.projectkorra.ProjectKorra.Objects.Preset; import com.projectkorra.ProjectKorra.Utilities.CraftingRecipes; import com.projectkorra.ProjectKorra.airbending.AirbendingManager; import com.projectkorra.ProjectKorra.chiblocking.ChiblockingManager; @@ -49,6 +50,7 @@ public class ProjectKorra extends JavaPlugin { DBConnection.init(); for (Player player: Bukkit.getOnlinePlayers()) { Methods.createBendingPlayer(player.getUniqueId(), player.getName()); + Preset.loadPresets(player); } getServer().getPluginManager().registerEvents(new PKListener(this), this); getServer().getPluginManager().registerEvents(new TagAPIListener(this), this); diff --git a/src/com/projectkorra/ProjectKorra/firebending/Combustion.java b/src/com/projectkorra/ProjectKorra/firebending/Combustion.java index b5f6b99e..6e279937 100644 --- a/src/com/projectkorra/ProjectKorra/firebending/Combustion.java +++ b/src/com/projectkorra/ProjectKorra/firebending/Combustion.java @@ -152,6 +152,7 @@ public class Combustion { if (instances.containsKey(player)) { Combustion combustion = instances.get(player); combustion.createExplosion(combustion.location, combustion.power, breakblocks); + ParticleEffect.EXPLODE.display(combustion.location, (float) Math.random(), (float) Math.random(), (float) Math.random(), 0, 3); } } diff --git a/src/com/projectkorra/ProjectKorra/waterbending/IceBlast.java b/src/com/projectkorra/ProjectKorra/waterbending/IceBlast.java new file mode 100644 index 00000000..01931bc8 --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/waterbending/IceBlast.java @@ -0,0 +1,313 @@ +package com.projectkorra.ProjectKorra.waterbending; + +import java.util.ArrayList; +import java.util.concurrent.ConcurrentHashMap; + +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.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.BendingPlayer; +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.TempBlock; +import com.projectkorra.ProjectKorra.TempPotionEffect; +import com.projectkorra.ProjectKorra.Utilities.ParticleEffect; + +public class IceBlast { + + private static ConcurrentHashMap instances = new ConcurrentHashMap(); + private static double defaultrange = ProjectKorra.plugin.getConfig().getInt("Abilities.Water.IceBlast.Range"); + private static int defaultdamage = ProjectKorra.plugin.getConfig().getInt("Abilities.Water.IceBlast.Damage"); + private static int ID = Integer.MIN_VALUE; + + private static final long interval = 20; + private static final byte data = 0; + private static final double affectingradius = 2; + private static final double deflectrange = 3; + + private int id; + private double range; + private boolean prepared = false; + private boolean settingup = false; + private boolean progressing = false; + private long time; + private Location location; + private Location firstdestination; + private Location destination; + private Block sourceblock; + private Player player; + private TempBlock source; + + public IceBlast(Player player) { + block(player); + range = Methods.waterbendingNightAugment(defaultrange, player.getWorld()); + this.player = player; + Block sourceblock = Methods.getIceSourceBlock(player, range); + + if (sourceblock == null) { + return; + } else { + prepare(sourceblock); + } + } + + private void prepare(Block block) { + for (IceBlast ice : getInstances(player)) { + if (ice.prepared) { + ice.cancel(); + } + } + sourceblock = block; + location = sourceblock.getLocation(); + prepared = true; + createInstance(); + } + + private void createInstance() { + id = ID++; + instances.put(id, this); + if (ID >= Integer.MAX_VALUE) { + ID = Integer.MIN_VALUE; + } + } + + private static ArrayList getInstances(Player player) { + ArrayList list = new ArrayList(); + for (int id : instances.keySet()) { + IceBlast ice = instances.get(id); + if (ice.player.equals(player)) { + list.add(ice); + } + } + + return list; + } + + private static void block(Player player) { + for (int id : instances.keySet()) { + IceBlast ice = instances.get(id); + + if (ice.player.equals(player)) + continue; + + if (!ice.location.getWorld().equals(player.getWorld())) + continue; + + if (!ice.progressing) + continue; + + if (Methods.isRegionProtectedFromBuild(player, "IceBlast", ice.location)) + continue; + + Location location = player.getEyeLocation(); + Vector vector = location.getDirection(); + Location mloc = ice.location; + if (mloc.distance(location) <= defaultrange + && Methods.getDistanceFromLine(vector, location, ice.location) < deflectrange + && mloc.distance(location.clone().add(vector)) < + mloc.distance(location.clone().add(vector.clone().multiply(-1)))) { + ice.cancel(); + } + + } + } + + public static void activate(Player player) { + + BendingPlayer bPlayer = Methods.getBendingPlayer(player.getName()); + + if (bPlayer.isOnCooldown("IceBlast")) return; + + for (IceBlast ice : getInstances(player)) { + if (ice.prepared) { + ice.throwIce(); + } + } + } + + private void cancel() { + if (progressing) { + if (source != null) + source.revertBlock(); + progressing = false; + } + + instances.remove(id); + } + + private void returnWater() { + new WaterReturn(player, sourceblock); + } + + public static void removeAll() { + for (int id : instances.keySet()) { + instances.get(id).cancel(); + } + + instances.clear(); + } + + private void affect(LivingEntity entity) { + int damage = (int) Methods.waterbendingNightAugment(defaultdamage, player.getWorld()); + if (entity instanceof Player) { + BendingPlayer bPlayer = Methods.getBendingPlayer(player.getName()); + if (bPlayer.canBeSlowed()) { + PotionEffect effect = new PotionEffect(PotionEffectType.SLOW, 70, 2); + new TempPotionEffect(entity, effect); + bPlayer.slow(10); + entity.damage(damage, player); + } + } else { + PotionEffect effect = new PotionEffect(PotionEffectType.SLOW, 70, 2); + new TempPotionEffect(entity, effect); + entity.damage(damage, player); + } + Methods.breakBreathbendingHold(entity); + + for(Location loc : Methods.getCircle(entity.getLocation(), 6, 7, false, false, 0)) { + ParticleEffect.SNOW_SHOVEL.display(loc, (float) Math.random(), (float) Math.random(), (float) Math.random(), 0, 10); + } + } + + private void throwIce() { + if (!prepared) + return; + LivingEntity target = (LivingEntity) Methods.getTargetedEntity(player, range, new ArrayList()); + if (target == null) { + destination = Methods.getTargetedLocation(player, range, Methods.transparentToEarthbending); + } else { + destination = target.getEyeLocation(); + } + + location = sourceblock.getLocation(); + if (destination.distance(location) < 1) + return; + firstdestination = location.clone(); + if (destination.getY() - location.getY() > 2) { + firstdestination.setY(destination.getY() - 1); + } else { + firstdestination.add(0, 2, 0); + } + destination = Methods.getPointOnLine(firstdestination, destination, range); + progressing = true; + settingup = true; + prepared = false; + + new TempBlock(sourceblock, Material.AIR, (byte) 0); + + source = new TempBlock(sourceblock, Material.PACKED_ICE, data); + } + + private void progress() { + if (player.isDead() || !player.isOnline() || !Methods.canBend(player.getName(), "IceBlast")) { + cancel(); + return; + } + + if (!player.getWorld().equals(location.getWorld())) { + cancel(); + return; + } + + if (player.getEyeLocation().distance(location) >= range) { + if (progressing) { + cancel(); + returnWater(); + } else { + cancel(); + } + return; + } + + if ((Methods.getBoundAbility(player) == null || !Methods.getBoundAbility(player).equalsIgnoreCase("IceBlast")) && prepared) { + cancel(); + return; + } + + if (System.currentTimeMillis() < time + interval) + return; + + time = System.currentTimeMillis(); + + if (progressing) { + + Vector direction; + + if (location.getBlockY() == firstdestination.getBlockY()) + settingup = false; + + if (location.distance(destination) <= 2) { + cancel(); + returnWater(); + return; + } + + if (settingup) { + direction = Methods.getDirection(location, firstdestination).normalize(); + } else { + direction = Methods.getDirection(location, destination).normalize(); + } + + location.add(direction); + + Block block = location.getBlock(); + + if (block.equals(sourceblock)) + return; + + source.revertBlock(); + source = null; + + if (Methods.isTransparentToEarthbending(player, block) && !block.isLiquid()) { + Methods.breakBlock(block); + } else if (!Methods.isWater(block)) { + cancel(); + returnWater(); + return; + } + + if (Methods.isRegionProtectedFromBuild(player, "IceBlast", location)) { + cancel(); + returnWater(); + return; + } + + for (Entity entity : Methods.getEntitiesAroundPoint(location, affectingradius)) { + if (entity.getEntityId() != player.getEntityId() && entity instanceof LivingEntity) { + affect((LivingEntity) entity); + progressing = false; + returnWater(); + } + } + + if (!progressing) { + cancel(); + return; + } + + sourceblock = block; + source = new TempBlock(sourceblock, Material.PACKED_ICE, data); + + ParticleEffect.SNOWBALL_POOF.display(location, (float) Math.random(), (float) Math.random(), (float) Math.random(), 0, 100); + ParticleEffect.SNOW_SHOVEL.display(location, (float) Math.random(), (float) Math.random(), (float) Math.random(), 0, 100); + location = location.add(direction.clone()); + + } else if (prepared) { + Methods.playFocusWaterEffect(sourceblock); + } + } + + public static void progressAll() { + for (int id : instances.keySet()) { + instances.get(id).progress(); + } + } + +} diff --git a/src/com/projectkorra/ProjectKorra/waterbending/WaterbendingManager.java b/src/com/projectkorra/ProjectKorra/waterbending/WaterbendingManager.java index e5b51470..2389fc9a 100644 --- a/src/com/projectkorra/ProjectKorra/waterbending/WaterbendingManager.java +++ b/src/com/projectkorra/ProjectKorra/waterbending/WaterbendingManager.java @@ -29,6 +29,7 @@ public class WaterbendingManager implements Runnable { Wave.progressAll(); IceSpike.progressAll(); IceSpike2.progressAll(); + IceBlast.progressAll(); WaterWave.progressAll(); } diff --git a/src/config.yml b/src/config.yml index 4fa6774a..7e89821c 100644 --- a/src/config.yml +++ b/src/config.yml @@ -65,6 +65,9 @@ Properties: DayFactor: 1.5 Chi: CanBendWithWeapons: false + DisabledWorlds: + - TestWorld + - TestWorld2 Abilities: AvatarState: Enabled: true @@ -167,6 +170,11 @@ Abilities: Description: "To use, the bender must be at least partially submerged in water. If the user is not sneaking, this ability will automatically begin working provided the user has it selected. If the user is sneaking, he/she is channeling the healing to their target in front of them. In order for this channel to be successful, the user and the target must be at least partially submerged in water." Radius: 5 Interval: 750 + IceBlast: + Enabled: true + Damage: 3 + Range: 20 + Description: "This ability offers a powerful ice utility for Waterbenders. It can be used to fire an explosive burst of ice at an opponent, spraying ice and snow around it. To use, simply tap sneak (Default: Shift) while targeting a block of ice to select it as a source. From there, you can just left click to send the blast off at your opponent." IceSpike: Enabled: true Description: "This ability has many functions. Clicking while targetting ice, or an entity over some ice, will raise a spike of ice up, damaging and slowing the target. Tapping sneak (default: shift) while selecting a water source will select that source that can be fired with a click. Firing this will launch a spike of ice at your target, dealing a bit of damage and slowing the target. If you sneak (shift) will not selecting a source, many ice spikes will erupt from around you, damaging and slowing those targets." @@ -222,7 +230,7 @@ Abilities: Height: 20 WaterWave: Enabled: true - Description: "WaterWave provides a waterbender with extreme mobility and transportation. To use, first click a source block to select it; then hold sneak (Default: Shift) to begin streaming the water around you. While the water is streaming around you let go of sneak and the water will form underneath your feet, blasting you off into the direction that you are facing. Press shift while riding the wave to stop it." + Description: "This ability provides a Waterbender with boosted mobility and transportation. To use, first click a source block to select it; then hold sneak (Default: Shift) to begin streaming the water around you. While the water is streaming around you let go of sneak and the water will form underneath your feet, blasting you off into the direction that you are facing. Additionally, taping sneak while riding the wave still stop it." Range: 6 ChargeTime: 1000 FlightTime: 2000 diff --git a/src/plugin.yml b/src/plugin.yml index 5d4cdbd3..d12b6843 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -1,6 +1,6 @@ name: ProjectKorra author: ProjectKorra -version: 1.4.0 BETA 9 +version: 1.4.0 BETA 11 main: com.projectkorra.ProjectKorra.ProjectKorra commands: projectkorra: @@ -36,6 +36,11 @@ permissions: bending.command.help: true bending.command.clear: true bending.command.who: true + bending.command.preset.list: true + bending.command.preset.create.2: true + bending.command.preset.create: true + bending.command.preset.bind: true + bending.command.preset.delete: true bending.air: true bending.water: true bending.earth: true @@ -61,6 +66,7 @@ permissions: description: Grants access to most waterbending abilities. children: bending.ability.HealingWaters: true + bending.ability.IceBlast: true bending.ability.IceSpike: true bending.ability.OctopusForm: true bending.ability.PhaseChange: true