diff --git a/src/com/projectkorra/ProjectKorra/Ability/AbilityModuleManager.java b/src/com/projectkorra/ProjectKorra/Ability/AbilityModuleManager.java index 4678ced6..2640330a 100644 --- a/src/com/projectkorra/ProjectKorra/Ability/AbilityModuleManager.java +++ b/src/com/projectkorra/ProjectKorra/Ability/AbilityModuleManager.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.projectkorra.ProjectKorra.Ability; import java.io.File; @@ -125,6 +126,7 @@ public class AbilityModuleManager { 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.WaterArms) shiftabilities.add(a.name()); // Water Sub Abilities if (a == StockAbilities.HealingWaters) subabilities.add(a.name()); @@ -304,4 +306,4 @@ public class AbilityModuleManager { Collections.sort(chiabilities); } -} +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/Ability/MultiAbility/MultiAbilityModule.java b/src/com/projectkorra/ProjectKorra/Ability/MultiAbility/MultiAbilityModule.java new file mode 100644 index 00000000..5e9c97f8 --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/Ability/MultiAbility/MultiAbilityModule.java @@ -0,0 +1,135 @@ +package com.projectkorra.ProjectKorra.Ability.MultiAbility; + +import java.util.ArrayList; + +import com.projectkorra.ProjectKorra.MultiAbilityManager.MultiAbilitySub; +import com.projectkorra.ProjectKorra.SubElement; +import com.projectkorra.ProjectKorra.Utilities.AbilityLoadable; + +public abstract class MultiAbilityModule extends AbilityLoadable implements Cloneable { + + public MultiAbilityModule(String name) { + super(name); + } + + /** + * Called when the ability is loaded by PK. This is where the developer registers Listeners and Permissions. + */ + public abstract void onThisLoad(); + + /** + * Accessor Method to get the version of the ability. + * + * @return The version of the ability as a String. + */ + public abstract String getVersion(); + + /** + * Accessor Method to get the Element of the ability. + * It is recommended to use the Element ENUM to get the returned String. + * This can be an empty String, in which case the ability will not belong to any element (such as AvatarState). + * + * @return The Element the ability belongs to. + */ + public abstract String getElement(); + + /** + * Accessor Method to get the name of the author. + * + * @return The name of the author. + */ + public abstract String getAuthor(); + + /** + * Accessor Method to get the description of the ability. + * This String is sent to any player who runs /pk display ability. + * + * @return The Description of the ability. + */ + public abstract String getDescription(); + + /** + * Accessor Method to get whether this ability uses sneaking to operate. + * Some features of the ProjectKorra plugin only work when this is false. (Fast Swimming for Waterbenders) + * + * @return Whether or not the ability uses the sneak key. + */ + public boolean isShiftAbility(){ + return true; + } + + /** + * Accessor Method to get whether this ability harms entities. + * AirSpout is an example of a harmless ability. For AirSpout, this returns true. + * IceBlast is an example of a harmful ability. For IceBlast, this returns false. + * Torrent is an example of both a harmless and a harmful ability. For Torrent, this returns false. + * + * @return Whether of not the ability can hurt entities. + */ + public abstract boolean isHarmlessAbility(); + + /** + * Accessor Method to get whether this ability can set fire to blocks. + * + * @return Whether or not this ability can ignite blocks. + */ + public boolean isIgniteAbility(){ + return false; + } + + /** + * Accessor Method to get whether this ability can create explosions. + * + * @return Whether or not this ability creates explosions. + */ + public boolean isExplodeAbility(){ + return false; + } + + /** + * Accessor Method to get which SubElement the ability belongs to. + * If isSubAbility() returns true, the developer absolutely must implement this as well. + * + * List of sub-elements: + * + * Water: + * Icebending. + * Bloodbending. + * Plantbending. + * Healing. + * + * Earth: + * Sandbending. + * Metalbending. + * Lavabending. + * + * Fire: + * Combustion. + * Lightning. + * + * Air: + * Flight. + * SpiritualProjection. + * + * @return The SubElement the ability belongs to. + */ + public SubElement getSubElement(){ + return null; + } + + /** + * Returns the sub abilities of a MultiAbility. + * e.g. new MultiAbilitySub("SubAbility", Element.Fire, SubElement.Lightning); + * @return + */ + public abstract ArrayList getAbilities(); + + /** + * Void Method called whenever ProjectKorra stops and the ability is unloaded. + * + */ + public void stop(){ + + } + +} diff --git a/src/com/projectkorra/ProjectKorra/Ability/MultiAbility/MultiAbilityModuleManager.java b/src/com/projectkorra/ProjectKorra/Ability/MultiAbility/MultiAbilityModuleManager.java new file mode 100644 index 00000000..19998d6e --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/Ability/MultiAbility/MultiAbilityModuleManager.java @@ -0,0 +1,98 @@ +package com.projectkorra.ProjectKorra.Ability.MultiAbility; + +import java.io.File; +import java.util.List; + +import com.projectkorra.ProjectKorra.Element; +import com.projectkorra.ProjectKorra.MultiAbilityManager; +import com.projectkorra.ProjectKorra.MultiAbilityManager.MultiAbility; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.Ability.AbilityModuleManager; +import com.projectkorra.ProjectKorra.Ability.StockAbilities; +import com.projectkorra.ProjectKorra.Utilities.AbilityLoader; + +public class MultiAbilityModuleManager +{ + private final AbilityLoader loader; + public static List multiAbility; + + public MultiAbilityModuleManager() + { + final File path = new File(ProjectKorra.plugin.getDataFolder().toString() + "/MultiAbilities/"); + if (!path.exists()) + { + path.mkdir(); + } + + loader = new AbilityLoader(ProjectKorra.plugin, path, new Object[] {}); + multiAbility = loader.load(MultiAbilityModule.class); + + loadMAModules(); + } + + private void loadMAModules() + { + for(MultiAbilityModule mam : multiAbility) + { + mam.onThisLoad(); + AbilityModuleManager.abilities.add(mam.getName()); + for (StockAbilities a: StockAbilities.values()) { + if (a.name().equalsIgnoreCase(mam.getName())){ + AbilityModuleManager.disabledStockAbilities.add(a.name()); + } + } + if (mam.getElement() == Element.Air.toString()) AbilityModuleManager.airbendingabilities.add(mam.getName()); + if (mam.getElement() == Element.Water.toString()) AbilityModuleManager.waterbendingabilities.add(mam.getName()); + if (mam.getElement() == Element.Earth.toString()) AbilityModuleManager.earthbendingabilities.add(mam.getName()); + if (mam.getElement() == Element.Fire.toString()) AbilityModuleManager.firebendingabilities.add(mam.getName()); + if (mam.getElement() == Element.Chi.toString()) AbilityModuleManager.chiabilities.add(mam.getName()); + AbilityModuleManager.shiftabilities.add(mam.getName()); + if (mam.isHarmlessAbility()) AbilityModuleManager.harmlessabilities.add(mam.getName()); + + if (mam.getSubElement() != null) + { + AbilityModuleManager.subabilities.add(mam.getName()); + switch(mam.getSubElement()) + { + case Bloodbending: + AbilityModuleManager.bloodabilities.add(mam.getName()); + break; + case Combustion: + AbilityModuleManager.combustionabilities.add(mam.getName()); + break; + case Flight: + AbilityModuleManager.flightabilities.add(mam.getName()); + break; + case Healing: + AbilityModuleManager.healingabilities.add(mam.getName()); + break; + case Icebending: + AbilityModuleManager.iceabilities.add(mam.getName()); + break; + case Lavabending: + AbilityModuleManager.lavaabilities.add(mam.getName()); + break; + case Lightning: + AbilityModuleManager.lightningabilities.add(mam.getName()); + break; + case Metalbending: + AbilityModuleManager.metalabilities.add(mam.getName()); + break; + case Plantbending: + AbilityModuleManager.plantabilities.add(mam.getName()); + break; + case Sandbending: + AbilityModuleManager.sandabilities.add(mam.getName()); + break; + case SpiritualProjection: + AbilityModuleManager.spiritualprojectionabilities.add(mam.getName()); + break; + } + } + + MultiAbilityManager.multiAbilityList.add(new MultiAbility(mam.getName(), mam.getAbilities())); + AbilityModuleManager.descriptions.put(mam.getName(), mam.getDescription()); + AbilityModuleManager.authors.put(mam.getName(), mam.getAuthor()); + } + } +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java b/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java index 5d26f7d3..12260353 100644 --- a/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java +++ b/src/com/projectkorra/ProjectKorra/Ability/StockAbilities.java @@ -1,225 +1,237 @@ -package com.projectkorra.ProjectKorra.Ability; - -import java.util.Arrays; - -public enum StockAbilities { - - // Old Bending - AirBlast, AirBubble, AirShield, AirSuction, AirSwipe, Tornado, AirScooter, AirSpout, AirBurst, - - Catapult, RaiseEarth, EarthGrab, EarthTunnel, EarthBlast, Collapse, Tremorsense, EarthArmor, Shockwave, - - HeatControl, Blaze, FireJet, Illumination, WallOfFire, FireBlast, Lightning, FireBurst, FireShield, - - WaterBubble, PhaseChange, HealingWaters, WaterManipulation, Surge, Bloodbending, WaterSpout, IceSpike, OctopusForm, Torrent, - - HighJump, RapidPunch, Paralyze, - - AvatarState, - - // Project Korra - Extraction, MetalClips, Smokescreen, Combustion, LavaFlow, Suffocate, IceBlast, WarriorStance, AcrobatStance, QuickStrike, SwiftKick, EarthSmash, Flight; - - private enum AirbendingAbilities { - AirBlast, AirBubble, AirShield, AirSuction, AirSwipe, Tornado, AirScooter, AirSpout, AirBurst, Suffocate, Flight; - } - - private enum WaterbendingAbilities { - WaterBubble, PhaseChange, HealingWaters, WaterManipulation, Surge, Bloodbending, WaterSpout, IceSpike, IceBlast, OctopusForm, Torrent; - - } - - private enum EarthbendingAbilities { - Catapult, RaiseEarth, EarthGrab, EarthTunnel, EarthBlast, Collapse, Tremorsense, EarthArmor, Shockwave, Extraction, MetalClips, LavaFlow, EarthSmash; - } - - private enum FirebendingAbilities { - HeatControl, Blaze, FireJet, Illumination, WallOfFire, FireBlast, Lightning, FireBurst, FireShield, Combustion; - } - - private enum ChiblockingAbilities { - HighJump, RapidPunch, Paralyze, Smokescreen, WarriorStance, AcrobatStance, QuickStrike, SwiftKick; - } - - private enum FlightAbilities - { - Flight; - } - - private enum SpiritualProjectionAbilities - { - ; - } - - private enum CombustionbendingAbilities - { - Combustion; - } - - private enum LightningbendingAbilities - { - Lightning; - } - - private enum LavabendingAbilities - { - LavaFlow; - } - - private enum MetalbendingAbilities - { - Extraction, MetalClips; - } - - private enum SandbendingAbilities - { - ; - } - - private enum HealingAbilities - { - HealingWaters; - } - - private enum IcebendingAbilities - { - PhaseChange, IceBlast, IceSpike; - } - - private enum BloodbendingAbilities - { - Bloodbending; - } - - private enum PlantbendingAbilities - { - ; - } - - public static boolean isFlightAbility(String ability) - { - for(FlightAbilities a : FlightAbilities.values()) - if(a.name().equalsIgnoreCase(ability)) return true; - return false; - } - - public static boolean isSpiritualProjectionAbility(String ability) - { - for(SpiritualProjectionAbilities a : SpiritualProjectionAbilities.values()) - if(a.name().equalsIgnoreCase(ability)) return true; - return false; - } - - public static boolean isCombustionbendingAbility(String ability) - { - for(CombustionbendingAbilities a : CombustionbendingAbilities.values()) - if(a.name().equalsIgnoreCase(ability)) return true; - return false; - } - - public static boolean isLightningbendingAbility(String ability) - { - for(LightningbendingAbilities a : LightningbendingAbilities.values()) - if(a.name().equalsIgnoreCase(ability)) return true; - return false; - } - - public static boolean isLavabendingAbility(String ability) - { - for(LavabendingAbilities a : LavabendingAbilities.values()) - if(a.name().equalsIgnoreCase(ability)) return true; - return false; - } - - public static boolean isMetalbendingAbility(String ability) - { - for(MetalbendingAbilities a : MetalbendingAbilities.values()) - if(a.name().equalsIgnoreCase(ability)) return true; - return false; - } - - public static boolean isSandbendingAbility(String ability) - { - for(SandbendingAbilities a : SandbendingAbilities.values()) - if(a.name().equalsIgnoreCase(ability)) return true; - return false; - } - - public static boolean isHealingAbility(String ability) - { - for(HealingAbilities a : HealingAbilities.values()) - if(a.name().equalsIgnoreCase(ability)) return true; - return false; - } - - public static boolean isIcebendingAbility(String ability) - { - for(IcebendingAbilities a : IcebendingAbilities.values()) - if(a.name().equalsIgnoreCase(ability)) return true; - return false; - } - - public static boolean isBloodbendingAbility(String ability) - { - for(BloodbendingAbilities a : BloodbendingAbilities.values()) - if(a.name().equalsIgnoreCase(ability)) return true; - return false; - } - - public static boolean isPlantbendingAbility(String ability) - { - for(PlantbendingAbilities a : PlantbendingAbilities.values()) - if(a.name().equalsIgnoreCase(ability)) return true; - return false; - } - - public static boolean isStockAbility(String ability) { - for (StockAbilities a: StockAbilities.values()) { - if (a.name().equalsIgnoreCase(ability)) return true; - } - return false; - } - - public static boolean isAirbending(StockAbilities ability) { - for (AirbendingAbilities a: AirbendingAbilities.values()) { - if (a.name().equalsIgnoreCase(ability.name())) return true; - } - return false; - } - - public static boolean isWaterbending(StockAbilities ability) { - for (WaterbendingAbilities a: WaterbendingAbilities.values()) { - if (a.name().equalsIgnoreCase(ability.name())) return true; - } - return false; - } - - public static boolean isEarthbending(StockAbilities ability) { - for (EarthbendingAbilities a: EarthbendingAbilities.values()) { - if (a.name().equalsIgnoreCase(ability.name())) return true; - } - return false; - } - - public static boolean isFirebending(StockAbilities ability) { - for (FirebendingAbilities a: FirebendingAbilities.values()) { - if (a.name().equalsIgnoreCase(ability.name())) return true; - } - return false; - } - - public static boolean isChiBlocking(StockAbilities ability) { - for (ChiblockingAbilities a: ChiblockingAbilities.values()) { - if (a.name().equalsIgnoreCase(ability.name())) return true; - } - - return false; - } - - public static StockAbilities getAbility(int index) { - if (index == -1) - return null; - if (index > 41) return null; - return Arrays.asList(StockAbilities.values()).get(index); - } -} +package com.projectkorra.ProjectKorra.Ability; + +import java.util.Arrays; + +public enum StockAbilities { + + // Old Bending + AirBlast, AirBubble, AirShield, AirSuction, AirSwipe, Tornado, AirScooter, AirSpout, AirBurst, + + Catapult, RaiseEarth, EarthGrab, EarthTunnel, EarthBlast, Collapse, Tremorsense, EarthArmor, Shockwave, + + HeatControl, Blaze, FireJet, Illumination, WallOfFire, FireBlast, Lightning, FireBurst, FireShield, + + WaterBubble, PhaseChange, HealingWaters, WaterManipulation, Surge, Bloodbending, WaterSpout, IceSpike, OctopusForm, Torrent, + + HighJump, RapidPunch, Paralyze, + + AvatarState, + + // Project Korra + Extraction, MetalClips, Smokescreen, Combustion, LavaFlow, Suffocate, IceBlast, WarriorStance, AcrobatStance, QuickStrike, SwiftKick, EarthSmash, Flight, WaterArms; + + private enum AirbendingAbilities { + AirBlast, AirBubble, AirShield, AirSuction, AirSwipe, Tornado, AirScooter, AirSpout, AirBurst, Suffocate, Flight; + } + + private enum WaterbendingAbilities { + WaterBubble, PhaseChange, HealingWaters, WaterManipulation, Surge, Bloodbending, WaterSpout, IceSpike, IceBlast, OctopusForm, Torrent, WaterArms; + + } + + private enum EarthbendingAbilities { + Catapult, RaiseEarth, EarthGrab, EarthTunnel, EarthBlast, Collapse, Tremorsense, EarthArmor, Shockwave, Extraction, MetalClips, LavaFlow, EarthSmash; + } + + private enum FirebendingAbilities { + HeatControl, Blaze, FireJet, Illumination, WallOfFire, FireBlast, Lightning, FireBurst, FireShield, Combustion; + } + + private enum ChiblockingAbilities { + HighJump, RapidPunch, Paralyze, Smokescreen, WarriorStance, AcrobatStance, QuickStrike, SwiftKick; + } + + private enum FlightAbilities + { + Flight; + } + + private enum SpiritualProjectionAbilities + { + ; + } + + private enum CombustionbendingAbilities + { + Combustion; + } + + private enum LightningbendingAbilities + { + Lightning; + } + + private enum LavabendingAbilities + { + LavaFlow; + } + + private enum MetalbendingAbilities + { + Extraction, MetalClips; + } + + private enum SandbendingAbilities + { + ; + } + + private enum HealingAbilities + { + HealingWaters; + } + + private enum IcebendingAbilities + { + PhaseChange, IceBlast, IceSpike; + } + + private enum BloodbendingAbilities + { + Bloodbending; + } + + private enum PlantbendingAbilities + { + ; + } + + private enum MultiAbilities + { + WaterArms; + } + + public static boolean isFlightAbility(String ability) + { + for(FlightAbilities a : FlightAbilities.values()) + if(a.name().equalsIgnoreCase(ability)) return true; + return false; + } + + public static boolean isSpiritualProjectionAbility(String ability) + { + for(SpiritualProjectionAbilities a : SpiritualProjectionAbilities.values()) + if(a.name().equalsIgnoreCase(ability)) return true; + return false; + } + + public static boolean isCombustionbendingAbility(String ability) + { + for(CombustionbendingAbilities a : CombustionbendingAbilities.values()) + if(a.name().equalsIgnoreCase(ability)) return true; + return false; + } + + public static boolean isLightningbendingAbility(String ability) + { + for(LightningbendingAbilities a : LightningbendingAbilities.values()) + if(a.name().equalsIgnoreCase(ability)) return true; + return false; + } + + public static boolean isLavabendingAbility(String ability) + { + for(LavabendingAbilities a : LavabendingAbilities.values()) + if(a.name().equalsIgnoreCase(ability)) return true; + return false; + } + + public static boolean isMetalbendingAbility(String ability) + { + for(MetalbendingAbilities a : MetalbendingAbilities.values()) + if(a.name().equalsIgnoreCase(ability)) return true; + return false; + } + + public static boolean isSandbendingAbility(String ability) + { + for(SandbendingAbilities a : SandbendingAbilities.values()) + if(a.name().equalsIgnoreCase(ability)) return true; + return false; + } + + public static boolean isHealingAbility(String ability) + { + for(HealingAbilities a : HealingAbilities.values()) + if(a.name().equalsIgnoreCase(ability)) return true; + return false; + } + + public static boolean isIcebendingAbility(String ability) + { + for(IcebendingAbilities a : IcebendingAbilities.values()) + if(a.name().equalsIgnoreCase(ability)) return true; + return false; + } + + public static boolean isBloodbendingAbility(String ability) + { + for(BloodbendingAbilities a : BloodbendingAbilities.values()) + if(a.name().equalsIgnoreCase(ability)) return true; + return false; + } + + public static boolean isPlantbendingAbility(String ability) + { + for(PlantbendingAbilities a : PlantbendingAbilities.values()) + if(a.name().equalsIgnoreCase(ability)) return true; + return false; + } + + public static boolean isStockAbility(String ability) { + for (StockAbilities a: StockAbilities.values()) { + if (a.name().equalsIgnoreCase(ability)) return true; + } + return false; + } + + public static boolean isAirbending(StockAbilities ability) { + for (AirbendingAbilities a: AirbendingAbilities.values()) { + if (a.name().equalsIgnoreCase(ability.name())) return true; + } + return false; + } + + public static boolean isWaterbending(StockAbilities ability) { + for (WaterbendingAbilities a: WaterbendingAbilities.values()) { + if (a.name().equalsIgnoreCase(ability.name())) return true; + } + return false; + } + + public static boolean isEarthbending(StockAbilities ability) { + for (EarthbendingAbilities a: EarthbendingAbilities.values()) { + if (a.name().equalsIgnoreCase(ability.name())) return true; + } + return false; + } + + public static boolean isFirebending(StockAbilities ability) { + for (FirebendingAbilities a: FirebendingAbilities.values()) { + if (a.name().equalsIgnoreCase(ability.name())) return true; + } + return false; + } + + public static boolean isChiBlocking(StockAbilities ability) { + for (ChiblockingAbilities a: ChiblockingAbilities.values()) { + if (a.name().equalsIgnoreCase(ability.name())) return true; + } + + return false; + } + + public static boolean isMultiAbility(StockAbilities ability) { + for(MultiAbilities a: MultiAbilities.values()) { + if (a.name().equalsIgnoreCase(ability.name())) return true; + } + return false; + } + + public static StockAbilities getAbility(int index) { + if (index == -1) + return null; + if (index > 41) return null; + return Arrays.asList(StockAbilities.values()).get(index); + } +} diff --git a/src/com/projectkorra/ProjectKorra/Commands.java b/src/com/projectkorra/ProjectKorra/Commands.java index e20a5391..f0af460a 100644 --- a/src/com/projectkorra/ProjectKorra/Commands.java +++ b/src/com/projectkorra/ProjectKorra/Commands.java @@ -189,6 +189,11 @@ public class Commands { s.sendMessage(ChatColor.RED + "This command is only usable by players."); return true; } + + if (MultiAbilityManager.hasMultiAbilityBound((Player) s)) { + s.sendMessage(ChatColor.RED + "You can't edit your binds right now!"); + return true; + } Player player = (Player) s; @@ -388,6 +393,12 @@ public class Commands { s.sendMessage(ChatColor.RED + "This command is only usable by players."); return true; } + + if (MultiAbilityManager.hasMultiAbilityBound((Player) s)) { + s.sendMessage(ChatColor.RED + "You can't edit your binds right now!"); + return true; + } + BendingPlayer bPlayer = GeneralMethods.getBendingPlayer(s.getName()); if (args.length == 1) { bPlayer.getAbilities().clear(); @@ -1876,4 +1887,4 @@ public class Commands { }; projectkorra.setExecutor(exe); } -} +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/ConfigManager.java b/src/com/projectkorra/ProjectKorra/ConfigManager.java index d610a0fa..e1e3e214 100644 --- a/src/com/projectkorra/ProjectKorra/ConfigManager.java +++ b/src/com/projectkorra/ProjectKorra/ConfigManager.java @@ -1,773 +1,829 @@ -package com.projectkorra.ProjectKorra; - -import org.bukkit.configuration.file.FileConfiguration; - -import java.util.ArrayList; - -public class ConfigManager { - - static ProjectKorra plugin; - - public ConfigManager(ProjectKorra plugin) { - ConfigManager.plugin = plugin; - configCheck(); - } - - public static void configCheck() { - - FileConfiguration config = ProjectKorra.plugin.getConfig(); - - ArrayList earthbendable = new ArrayList(); - earthbendable.add("STONE"); - earthbendable.add("CLAY"); - earthbendable.add("COAL_ORE"); - earthbendable.add("DIAMOND_ORE"); - earthbendable.add("DIRT"); - earthbendable.add("GOLD_ORE"); - earthbendable.add("GRASS"); - earthbendable.add("GRAVEL"); - earthbendable.add("IRON_ORE"); - earthbendable.add("LAPIS_ORE"); - earthbendable.add("NETHERRACK"); - earthbendable.add("REDSTONE_ORE"); - earthbendable.add("SAND"); - earthbendable.add("SANDSTONE"); - earthbendable.add("MYCEL"); - - ArrayList metals = new ArrayList(); - metals.add("IRON_BLOCK"); - metals.add("GOLD_BLOCK"); - metals.add("QUARTZ_BLOCK"); - - config.addDefault("Properties.Chat.Enable", true); - config.addDefault("Properties.Chat.Format", ": "); - config.addDefault("Properties.Chat.Prefixes.Air", "[Airbender]"); - config.addDefault("Properties.Chat.Prefixes.Water", "[Waterbender]"); - config.addDefault("Properties.Chat.Prefixes.Earth", "[Earthbender]"); - config.addDefault("Properties.Chat.Prefixes.Fire", "[Firebender]"); - config.addDefault("Properties.Chat.Prefixes.Chi", "[Chiblocker]"); - config.addDefault("Properties.Chat.Prefixes.Avatar", "[Avatar]"); - config.addDefault("Properties.Chat.Colors.Avatar", "DARK_PURPLE"); - config.addDefault("Properties.Chat.Colors.Air", "GRAY"); - config.addDefault("Properties.Chat.Colors.AirSub", "DARK_GRAY"); - config.addDefault("Properties.Chat.Colors.Water", "AQUA"); - config.addDefault("Properties.Chat.Colors.WaterSub", "DARK_AQUA"); - config.addDefault("Properties.Chat.Colors.Earth", "GREEN"); - config.addDefault("Properties.Chat.Colors.EarthSub", "DARK_GREEN"); - config.addDefault("Properties.Chat.Colors.Fire", "RED"); - config.addDefault("Properties.Chat.Colors.FireSub", "DARK_RED"); - config.addDefault("Properties.Chat.Colors.Chi", "GOLD"); - - config.addDefault("Properties.ImportEnabled", true); - config.addDefault("Properties.BendingAffectFallingSand.Normal", true); - config.addDefault("Properties.BendingAffectFallingSand.NormalStrengthMultiplier", 1.0); - config.addDefault("Properties.BendingAffectFallingSand.TNT", true); - config.addDefault("Properties.BendingAffectFallingSand.TNTStrengthMultiplier", 1.0); - config.addDefault("Properties.GlobalCooldown", 500); - config.addDefault("Properties.SeaLevel", 62); - - config.addDefault("Properties.HorizontalCollisionPhysics.Enabled", true); - config.addDefault("Properties.HorizontalCollisionPhysics.WallDamageMinimumDistance", 5.0); - - config.addDefault("Properties.CustomItems.GrapplingHook.Enable", true); - config.addDefault("Properties.CustomItems.GrapplingHook.IronUses", 25); - config.addDefault("Properties.CustomItems.GrapplingHook.GoldUses", 50); - - config.addDefault("Properties.RegionProtection.AllowHarmlessAbilities", true); - config.addDefault("Properties.RegionProtection.RespectWorldGuard", true); - config.addDefault("Properties.RegionProtection.RespectGriefPrevention", true); - config.addDefault("Properties.RegionProtection.RespectFactions", true); - config.addDefault("Properties.RegionProtection.RespectTowny", true); - config.addDefault("Properties.RegionProtection.RespectPreciousStones", true); - config.addDefault("Properties.RegionProtection.RespectLWC", true); - config.addDefault("Properties.RegionProtection.CacheBlockTime", 5000); - - config.addDefault("Properties.TagAPI.Enabled", true); - - config.addDefault("Properties.Air.CanBendWithWeapons", false); - config.addDefault("Properties.Air.Particles", "smoke"); - config.addDefault("Properties.Air.PlaySound", true); - - config.addDefault("Properties.Water.CanBendWithWeapons", true); - config.addDefault("Properties.Water.NightFactor", 1.5); - config.addDefault("Properties.Water.FullMoonFactor", 3.0); - config.addDefault("Properties.Water.CanBendPackedIce", true); - config.addDefault("Properties.Water.PlaySound", true); - - config.addDefault("Properties.Earth.RevertEarthbending", true); - config.addDefault("Properties.Earth.SafeRevert", true); - config.addDefault("Properties.Earth.RevertCheckTime", 300000); - config.addDefault("Properties.Earth.CanBendWithWeapons", true); - config.addDefault("Properties.Earth.EarthbendableBlocks", earthbendable); - config.addDefault("Properties.Earth.MetalBlocks", metals); - config.addDefault("Properties.Earth.MetalPowerFactor", 1.5); - config.addDefault("Properties.Earth.PlaySound", true); - - config.addDefault("Properties.Fire.CanBendWithWeapons", true); - config.addDefault("Properties.Fire.DayFactor", 1.5); - config.addDefault("Properties.Fire.PlaySound", true); - - 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 " - + "all sources, regenerates health rapidly, and is granted extreme speed. Nearly all abilities " - + "are incredibly amplified in this state. Additionally, AirShield and FireJet become toggle-able " - + "abilities and last until you deactivate them or the Avatar State. Click again with the Avatar " - + "State selected to deactivate it."); - config.addDefault("Abilities.AvatarState.Cooldown", 7200000); - config.addDefault("Abilities.AvatarState.Duration", 480000); - config.addDefault("Abilities.AvatarState.PowerMultiplier", 5); - config.addDefault("Abilities.AvatarState.PotionEffects.Regeneration.Enabled", true); - config.addDefault("Abilities.AvatarState.PotionEffects.Regeneration.Power", 3); - config.addDefault("Abilities.AvatarState.PotionEffects.Speed.Enabled", true); - config.addDefault("Abilities.AvatarState.PotionEffects.Speed.Power", 3); - config.addDefault("Abilities.AvatarState.PotionEffects.DamageResistance.Enabled", true); - config.addDefault("Abilities.AvatarState.PotionEffects.FireResistance.Enabled", true); - config.addDefault("Abilities.AvatarState.PotionEffects.FireResistance.Power", 3); - - config.addDefault("Abilities.Air.Passive.Factor", 0.3); - config.addDefault("Abilities.Air.Passive.Speed", 2); - config.addDefault("Abilities.Air.Passive.Jump", 3); - - config.addDefault("Abilities.Air.AirBlast.Enabled", true); - config.addDefault("Abilities.Air.AirBlast.Description", "AirBlast is the most fundamental bending technique of an airbender." - + " To use, simply left-click in a direction. A gust of wind will be" - + " created at your fingertips, launching anything in its path harmlessly back." - + " A gust of air can extinguish fires on the ground or on a player, can cool lava, and " - + "can flip levers and activate buttons. Additionally, tapping sneak will change the " - + "origin of your next AirBlast to your targeted location."); - config.addDefault("Abilities.Air.AirBlast.Speed", 25); - config.addDefault("Abilities.Air.AirBlast.Range", 20); - config.addDefault("Abilities.Air.AirBlast.Radius", 2); - config.addDefault("Abilities.Air.AirBlast.Push", 3.5); - - config.addDefault("Abilities.Air.AirBubble.Enabled", true); - config.addDefault("Abilities.Air.AirBubble.Description", "To use, the bender must merely have the ability selected. All water around the user in a small bubble will vanish, replacing itself once the user either gets too far away or selects a different ability."); - config.addDefault("Abilities.Air.AirBubble.Radius", 7); - - config.addDefault("Abilities.Air.AirBurst.Enabled", true); - config.addDefault("Abilities.Air.AirBurst.Description", "AirBurst is one of the most powerful abilities in the airbender's arsenal. " - + "To use, press and hold sneak to charge your burst. " - + "Once charged, you can either release sneak to launch a cone-shaped burst " - + "of air in front of you, or click to release the burst in a sphere around you. " - + "Additionally, having this ability selected when you land on the ground from a " - + "large enough fall will create a burst of air around you."); - config.addDefault("Abilities.Air.AirBurst.FallThreshold", 10); - config.addDefault("Abilities.Air.AirBurst.PushFactor", 1.5); - config.addDefault("Abilities.Air.AirBurst.ChargeTime", 1750); - config.addDefault("Abilities.Air.AirBurst.Damage", 0); - - config.addDefault("Abilities.Air.AirScooter.Enabled", true); - config.addDefault("Abilities.Air.AirScooter.Description", "AirScooter is a fast means of transportation. To use, sprint, jump then click with " - + "this ability selected. You will hop on a scooter of air and be propelled forward " - + "in the direction you're looking (you don't need to press anything). " - + "This ability can be used to levitate above liquids, but it cannot go up steep slopes. " - + "Any other actions will deactivate this ability."); - config.addDefault("Abilities.Air.AirScooter.Speed", .675); - - config.addDefault("Abilities.Air.Tornado.Enabled", true); - config.addDefault("Abilities.Air.Tornado.Description", "To use, simply sneak (default: shift). " - + "This will create a swirling vortex at the targeted location. " - + "Any creature or object caught in the vortex will be launched up " - + "and out in some random direction. If another player gets caught " - + "in the vortex, the launching effect is minimal. Tornado can " - + "also be used to transport the user. If the user gets caught in his/her " - + "own tornado, his movements are much more manageable. Provided the user doesn't " - + "fall out of the vortex, it will take him to a maximum height and move him in " - + "the general direction he's looking. Skilled airbenders can scale anything " - + "with this ability."); - - config.addDefault("Abilities.Air.AirShield.Enabled", true); - config.addDefault("Abilities.Air.AirShield.Description", "Air Shield is one of the most powerful defensive techniques in existence. " - + "To use, simply sneak (default: shift). " - + "This will create a whirlwind of air around the user, " - + "with a small pocket of safe space in the center. " - + "This wind will deflect all projectiles and will prevent any creature from " - + "entering it for as long as its maintained."); - config.addDefault("Abilities.Air.AirShield.Radius", 7); - config.addDefault("Abilities.Air.AirShield.IsAvatarStateToggle", true); - - config.addDefault("Abilities.Air.AirSpout.Enabled", true); - config.addDefault("Abilities.Air.AirSpout.Description", "This ability gives the airbender limited sustained levitation. It is a " - + "toggle - click to activate and form a whirling spout of air " - + "beneath you, lifting you up. You can bend other abilities while using AirSpout. " - + "Click again to deactivate this ability."); - config.addDefault("Abilities.Air.AirSpout.Height", 20); - - config.addDefault("Abilities.Air.AirSuction.Enabled", true); - config.addDefault("Abilities.Air.AirSuction.Description", "To use, simply left-click in a direction. A gust of wind will originate as far as it can in that direction and flow towards you, sucking anything in its path harmlessly with it. Skilled benders can use this technique to pull items from precarious locations. Additionally, tapping sneak will change the origin of your next AirSuction to your targeted location."); - config.addDefault("Abilities.Air.AirSuction.Speed", 25); - config.addDefault("Abilities.Air.AirSuction.Range", 20); - config.addDefault("Abilities.Air.AirSuction.Radius", 2); - config.addDefault("Abilities.Air.AirSuction.Push", 3.5); - - config.addDefault("Abilities.Air.AirSwipe.Enabled", true); - config.addDefault("Abilities.Air.AirSwipe.Description", "To use, simply left-click in a direction. An arc of air will flow from you towards that direction, cutting and pushing back anything in its path. Its damage is minimal, but it still sends the message. This ability will extinguish fires, cool lava, and cut things like grass, mushrooms, and flowers. Additionally, you can charge it by holding sneak. Charging before attacking will increase damage and knockback, up to a maximum."); - config.addDefault("Abilities.Air.AirSwipe.Damage", 2); - config.addDefault("Abilities.Air.AirSwipe.Range", 16); - config.addDefault("Abilities.Air.AirSwipe.Radius", 2); - config.addDefault("Abilities.Air.AirSwipe.Push", 1); - config.addDefault("Abilities.Air.AirSwipe.Arc", 20); - config.addDefault("Abilities.Air.AirSwipe.Speed", 25); - config.addDefault("Abilities.Air.AirSwipe.Cooldown", 1500); - config.addDefault("Abilities.Air.AirSwipe.ChargeFactor", 3); - config.addDefault("Abilities.Air.AirSwipe.MaxChargeTime", 3000); - - config.addDefault("Abilities.Air.Flight.Enabled", true); - config.addDefault("Abilities.Air.Flight.Description", "Jump in the air, crouch (default: shift) and hold with this ability bound and you will glide around in the direction you look. While flying, click to Hover. Click again to disable Hovering."); - config.addDefault("Abilities.Air.Flight.HoverEnabled", true); - - config.addDefault("Abilities.Air.Suffocate.Enabled", true); - config.addDefault("Abilities.Air.Suffocate.Description", "This ability is one of the most dangerous abilities an Airbender possesses. To use, simply look at an entity and hold shift. The entity will begin taking damage as you extract the air from their lungs. Any bender caught in this sphere will only be able to use basic moves, such as AirSwipe, WaterManipulation, FireBlast, or EarthBlast. An entity can be knocked out of the sphere by certain bending arts, and your attention will be disrupted if you are hit by bending."); - config.addDefault("Abilities.Air.Suffocate.ChargeTime", 1000); - config.addDefault("Abilities.Air.Suffocate.Cooldown", 0); - config.addDefault("Abilities.Air.Suffocate.Range", 15); - config.addDefault("Abilities.Air.Suffocate.Damage", 2); - config.addDefault("Abilities.Air.Suffocate.DamageInitialDelay", 2); - config.addDefault("Abilities.Air.Suffocate.DamageInterval", 1); - config.addDefault("Abilities.Air.Suffocate.SlowPotency", 1); - config.addDefault("Abilities.Air.Suffocate.SlowDelay", 0.5); - config.addDefault("Abilities.Air.Suffocate.SlowInterval", 1.25); - config.addDefault("Abilities.Air.Suffocate.BlindPotentcy", 30); - config.addDefault("Abilities.Air.Suffocate.BlindDelay", 2); - config.addDefault("Abilities.Air.Suffocate.BlindInterval", 1.5); - config.addDefault("Abilities.Air.Suffocate.CanBeUsedOnUndeadMobs", true); - config.addDefault("Abilities.Air.Suffocate.RequireConstantAim", true); - config.addDefault("Abilities.Air.Suffocate.RequireConstantAimRadius", 5); - config.addDefault("Abilities.Air.Suffocate.AnimationRadius", 2.0); - config.addDefault("Abilities.Air.Suffocate.AnimationParticleAmount", 2); - config.addDefault("Abilities.Air.Suffocate.AnimationSpeed", 1.0); - - config.addDefault("Abilities.Air.Tornado.Radius", 10); - config.addDefault("Abilities.Air.Tornado.Height", 25); - config.addDefault("Abilities.Air.Tornado.Range", 25); - config.addDefault("Abilities.Air.Tornado.MobPushFactor", 1); - config.addDefault("Abilities.Air.Tornado.PlayerPushFactor", 1); - - config.addDefault("Abilities.Air.AirCombo.Enabled", true); - config.addDefault("Abilities.Air.AirCombo.Twister.Speed", 0.35); - config.addDefault("Abilities.Air.AirCombo.Twister.Range", 16); - config.addDefault("Abilities.Air.AirCombo.Twister.Height", 8); - config.addDefault("Abilities.Air.AirCombo.Twister.Radius", 3.5); - config.addDefault("Abilities.Air.AirCombo.Twister.RemoveDelay", 1500); - config.addDefault("Abilities.Air.AirCombo.Twister.Cooldown", 10000); - config.addDefault("Abilities.Air.AirCombo.Twister.DegreesPerParticle", 7); - config.addDefault("Abilities.Air.AirCombo.Twister.HeightPerParticle", 1.25); - config.addDefault("Abilities.Air.AirCombo.AirStream.Speed", 0.5); - config.addDefault("Abilities.Air.AirCombo.AirStream.Range", 40); - config.addDefault("Abilities.Air.AirCombo.AirStream.EntityDuration", 4000); - config.addDefault("Abilities.Air.AirCombo.AirStream.EntityHeight", 14); - config.addDefault("Abilities.Air.AirCombo.AirStream.Cooldown", 6000); - config.addDefault("Abilities.Air.AirCombo.AirSweep.Speed", 1.4); - config.addDefault("Abilities.Air.AirCombo.AirSweep.Range", 14); - config.addDefault("Abilities.Air.AirCombo.AirSweep.Damage", 4); - config.addDefault("Abilities.Air.AirCombo.AirSweep.Knockback", 3.5); - config.addDefault("Abilities.Air.AirCombo.AirSweep.Cooldown", 5000); - - config.addDefault("Abilities.Water.Passive.SwimSpeedFactor", 0.7); - - config.addDefault("Abilities.Water.Bloodbending.Enabled", true); - config.addDefault("Abilities.Water.Bloodbending.Description", "This ability was made illegal for a reason. With this ability selected, sneak while " - + "targetting something and you will bloodbend that target. Bloodbent targets cannot move, " - + "bend or attack. You are free to control their actions by looking elsewhere - they will " - + "be forced to move in that direction. Additionally, clicking while bloodbending will " - + "launch that target off in the direction you're looking. " - + "People who are capable of bloodbending are immune to your technique, and you are immune to theirs."); - config.addDefault("Abilities.Water.Bloodbending.CanOnlyBeUsedAtNight", false); - config.addDefault("Abilities.Water.Bloodbending.CanBeUsedOnUndeadMobs", true); - config.addDefault("Abilities.Water.Bloodbending.ThrowFactor", 2); - config.addDefault("Abilities.Water.Bloodbending.Range", 10); - config.addDefault("Abilities.Water.Bloodbending.HoldTime", 0); - config.addDefault("Abilities.Water.Bloodbending.Cooldown", 0); - config.addDefault("Abilities.Water.Bloodbending.CanOnlyBeUsedDuringFullMoon", false); - - config.addDefault("Abilities.Water.HealingWaters.Enabled", true); - config.addDefault("Abilities.Water.HealingWaters.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."); - config.addDefault("Abilities.Water.HealingWaters.Radius", 5); - config.addDefault("Abilities.Water.HealingWaters.Interval", 750); - config.addDefault("Abilities.Water.HealingWaters.Power", 1); - - 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, " - + "will raise a spike of ice up, damaging and slowing the target. Tapping sneak (shift) while" - + " selecting a water source will select that source that can then 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) while not selecting a source, many ice spikes will erupt from around you, " - + "damaging and slowing those targets."); - config.addDefault("Abilities.Water.IceSpike.Cooldown", 2000); - config.addDefault("Abilities.Water.IceSpike.Damage", 2); - config.addDefault("Abilities.Water.IceSpike.Range", 20); - config.addDefault("Abilities.Water.IceSpike.ThrowingMult", 0.7); - config.addDefault("Abilities.Water.IceSpike.Height", 6); - config.addDefault("Abilities.Water.IceSpike.Projectile.Range", 20); - config.addDefault("Abilities.Water.IceSpike.Projectile.Damage", 1); - - config.addDefault("Abilities.Water.OctopusForm.Enabled", true); - config.addDefault("Abilities.Water.OctopusForm.Description", "This ability allows the waterbender to manipulate a large quantity of water into a form resembling that of an octopus. " - + "To use, click to select a water source. Then, hold sneak to channel this ability. " - + "While channeling, the water will form itself around you and has a chance to block incoming attacks. " - + "Additionally, you can click while channeling to attack things near you, dealing damage and knocking them back. " - + "Releasing shift at any time will dissipate the form."); - config.addDefault("Abilities.Water.OctopusForm.Range", 10); - config.addDefault("Abilities.Water.OctopusForm.AttackRange", 2.5); - config.addDefault("Abilities.Water.OctopusForm.Radius", 3); - config.addDefault("Abilities.Water.OctopusForm.Damage", 3); - config.addDefault("Abilities.Water.OctopusForm.Knockback", 1.75); - config.addDefault("Abilities.Water.OctopusForm.FormDelay", 50); - - config.addDefault("Abilities.Water.PhaseChange.Enabled", true); - config.addDefault("Abilities.Water.PhaseChange.Description", "To use, simply left-click. " - + "Any water you are looking at within range will instantly freeze over into solid ice. " - + "Provided you stay within range of the ice and do not unbind FreezeMelt, " - + "that ice will not thaw. If, however, you do either of those the ice will instantly thaw. " - + "If you sneak (default: shift), anything around where you are looking at will instantly melt. " - + "Since this is a more favorable state for these things, they will never re-freeze unless they " - + "would otherwise by nature or some other bending ability. Additionally, if you tap sneak while " - + "targetting water with FreezeMelt, it will evaporate water around that block that is above " - + "sea level. "); - config.addDefault("Abilities.Water.PhaseChange.Range", 20); - config.addDefault("Abilities.Water.PhaseChange.Radius", 5); - - config.addDefault("Abilities.Water.Surge.Enabled", true); - config.addDefault("Abilities.Water.Surge.Description", "This ability has two distinct features. If you sneak to select a source block, you can then click in a direction and a large wave will be launched in that direction. If you sneak again while the wave is en route, the wave will freeze the next target it hits. If, instead, you click to select a source block, you can hold sneak to form a wall of water at your cursor location. Click to shift between a water wall and an ice wall. Release sneak to dissipate it."); - config.addDefault("Abilities.Water.Surge.Wave.Radius", 3); - config.addDefault("Abilities.Water.Surge.Wave.Range", 20); - config.addDefault("Abilities.Water.Surge.Wave.HorizontalPush", 1); - config.addDefault("Abilities.Water.Surge.VerticalPush", 0.2); - config.addDefault("Abilities.Water.Surge.Wall.Range", 5); - config.addDefault("Abilities.Water.Surge.Wall.Radius", 2); - - config.addDefault("Abilities.Water.Torrent.Enabled", true); - config.addDefault("Abilities.Water.Torrent.Description", "Torrent is one of the strongest moves in a waterbender's arsenal. To use, first click a source block to select it; then hold shift to begin streaming the water around you. Water flowing around you this way will damage and knock back nearby enemies and projectiles. If you release shift during this, you will create a large wave that expands outwards from you, launching anything in its path back. Instead, if you click you release the water and channel it to flow towards your cursor. Anything caught in the blast will be tossed about violently and take damage. Finally, if you click again when the water is torrenting, it will freeze the area around it when it is obstructed."); - config.addDefault("Abilities.Water.Torrent.Range", 25); - config.addDefault("Abilities.Water.Torrent.DeflectDamage", 1); - config.addDefault("Abilities.Water.Torrent.Damage", 2); - config.addDefault("Abilities.Water.Torrent.Wave.Radius", 15); - config.addDefault("Abilities.Water.Torrent.Wave.Knockback", 1.5); - config.addDefault("Abilities.Water.Torrent.Wave.Height", 1); - - config.addDefault("Abilities.Water.Plantbending.RegrowTime", 180000); - - config.addDefault("Abilities.Water.WaterBubble.Enabled", true); - config.addDefault("Abilities.Water.WaterBubble.Description","To use, the bender must merely have the ability selected. All water around the user in a small bubble will vanish, replacing itself once the user either gets too far away or selects a different ability."); - config.addDefault("Abilities.Water.WaterBubble.Radius", 7); - - config.addDefault("Abilities.Water.WaterManipulation.Enabled", true); - config.addDefault("Abilities.Water.WaterManipulation.Description", "To use, place your cursor over a waterbendable object and tap sneak (default: shift). Smoke will appear where you've selected, indicating the origin of your ability. After you have selected an origin, simply left-click in any direction and you will see your water spout off in that direction, slicing any creature in its path. If you look towards a creature when you use this ability, it will target that creature. A collision from Water Manipulation both knocks the target back and deals some damage. Alternatively, if you have the source selected and tap shift again, you will be able to control the water more directly."); - config.addDefault("Abilities.Water.WaterManipulation.Damage", 3.0); - config.addDefault("Abilities.Water.WaterManipulation.Range", 20); - config.addDefault("Abilities.Water.WaterManipulation.Speed", 35); - config.addDefault("Abilities.Water.WaterManipulation.Push", 0.3); - config.addDefault("Abilities.Water.WaterManipulation.Cooldown", 1000); - - config.addDefault("Abilities.Water.WaterSpout.Enabled", true); - config.addDefault("Abilities.Water.WaterSpout.Description", "This ability provides a Waterbender with a means of transportation. To use, simply left click while in or over water to spout water up beneath you, experiencing controlled levitation. Left clicking again while the spout is active will cause it to disappear. Alternatively, tapping a Waterbendable block while not in Water will select a water block as a source, from there, you can tap sneak (Default:Shift) to channel the Water around you. Releasing the sneak will create a wave allowing you a quick burst of controlled transportation. While riding the wave you may press sneak to cause the wave to disappear."); - config.addDefault("Abilities.Water.WaterSpout.Height", 20); - config.addDefault("Abilities.Water.WaterSpout.Wave.Particles", false); - config.addDefault("Abilities.Water.WaterSpout.Wave.Enabled", true); - config.addDefault("Abilities.Water.WaterSpout.Wave.Range", 6); - config.addDefault("Abilities.Water.WaterSpout.Wave.ChargeTime", 1000); - config.addDefault("Abilities.Water.WaterSpout.Wave.FlightTime", 2000); - config.addDefault("Abilities.Water.WaterSpout.Wave.Speed", 1.2); - - config.addDefault("Abilities.Water.WaterCombo.Enabled", true); - config.addDefault("Abilities.Water.WaterCombo.IceWave.Damage", 3); - config.addDefault("Abilities.Water.WaterCombo.IceWave.Cooldown", 6000); - config.addDefault("Abilities.Water.WaterCombo.IceBullet.Damage", 1.5); - config.addDefault("Abilities.Water.WaterCombo.IceBullet.Radius", 2.5); - config.addDefault("Abilities.Water.WaterCombo.IceBullet.Range", 12); - config.addDefault("Abilities.Water.WaterCombo.IceBullet.MaxShots", 30); - config.addDefault("Abilities.Water.WaterCombo.IceBullet.AnimationSpeed", 1); - config.addDefault("Abilities.Water.WaterCombo.IceBullet.ShootTime", 5000); - config.addDefault("Abilities.Water.WaterCombo.IceBullet.Cooldown", 10000); - - config.addDefault("Abilities.Earth.Passive.Duration", 2500); - - config.addDefault("Abilities.Earth.Catapult.Enabled", true); - config.addDefault("Abilities.Earth.Catapult.Description", "To use, left-click while looking in the direction you want to be launched. " - + "A pillar of earth will jut up from under you and launch you in that direction - " - + "if and only if there is enough earth behind where you're looking to launch you. " - + "Skillful use of this ability takes much time and work, and it does result in the " - + "death of certain gung-ho earthbenders. If you plan to use this ability, be sure " - + "you've read about your passive ability you innately have as an earthbender."); - config.addDefault("Abilities.Earth.Catapult.Length", 7); - config.addDefault("Abilities.Earth.Catapult.Speed", 12); - config.addDefault("Abilities.Earth.Catapult.Push", 5); - - config.addDefault("Abilities.Earth.Collapse.Enabled", true); - config.addDefault("Abilities.Earth.Collapse.Description", " To use, simply left-click on an earthbendable block. " - + "That block and the earthbendable blocks above it will be shoved " - + "back into the earth below them, if they can. " - + "This ability does have the capacity to trap something inside of it, " - + "although it is incredibly difficult to do so. " - + "Additionally, press sneak with this ability to affect an area around your targetted location - " - + "all earth that can be moved downwards will be moved downwards. " - + "This ability is especially risky or deadly in caves, depending on the " - + "earthbender's goal and technique."); - config.addDefault("Abilities.Earth.Collapse.Range", 20); - config.addDefault("Abilities.Earth.Collapse.Radius", 7); - config.addDefault("Abilities.Earth.Collapse.Speed", 8); - - config.addDefault("Abilities.Earth.EarthArmor.Enabled", true); - config.addDefault("Abilities.Earth.EarthArmor.Description", "This ability encases the earthbender in temporary armor. To use, click on a block that is earthbendable. If there is another block under it that is earthbendable, the block will fly to you and grant you temporary armor and damage reduction. This ability has a long cooldown."); - config.addDefault("Abilities.Earth.EarthArmor.Duration", 10000); - config.addDefault("Abilities.Earth.EarthArmor.Strength", 2); - config.addDefault("Abilities.Earth.EarthArmor.Duration", 17500); - - config.addDefault("Abilities.Earth.EarthBlast.Enabled", true); - config.addDefault("Abilities.Earth.EarthBlast.Description", "To use, place your cursor over an earthbendable object (dirt, rock, ores, etc) " - + "and tap sneak (default: shift). The object will temporarily turn to stone, " - + "indicating that you have it focused as the source for your ability. " - + "After you have selected an origin (you no longer need to be sneaking), " - + "simply left-click in any direction and you will see your object launch " - + "off in that direction, smashing into any creature in its path. If you look " - + "towards a creature when you use this ability, it will target that creature. " - + "A collision from Earth Blast both knocks the target back and deals some damage. " - + "You cannot have multiple of these abilities flying at the same time."); - config.addDefault("Abilities.Earth.EarthBlast.CanHitSelf", false); - config.addDefault("Abilities.Earth.EarthBlast.PrepareRange", 7); - config.addDefault("Abilities.Earth.EarthBlast.Range", 20); - config.addDefault("Abilities.Earth.EarthBlast.Speed", 35); - config.addDefault("Abilities.Earth.EarthBlast.Revert", true); - config.addDefault("Abilities.Earth.Earthblast.Damage", 4); - config.addDefault("Abilities.Earth.EarthBlast.Push", 0.3); - - config.addDefault("Abilities.Earth.EarthGrab.Enabled", true); - config.addDefault("Abilities.Earth.EarthGrab.Description", "To use, simply left-click while targeting a creature within range. " - + "This ability will erect a circle of earth to trap the creature in."); - config.addDefault("Abilities.Earth.EarthGrab.Range", 15); - - config.addDefault("Abilities.Earth.EarthTunnel.Enabled", true); - config.addDefault("Abilities.Earth.EarthTunnel.Description", "Earth Tunnel is a completely utility ability for earthbenders. To use, simply sneak (default: shift) in the direction you want to tunnel. You will slowly begin tunneling in the direction you're facing for as long as you sneak or if the tunnel has been dug long enough. This ability will be interrupted if it hits a block that cannot be earthbent."); - config.addDefault("Abilities.Earth.EarthTunnel.MaxRadius", 1); - config.addDefault("Abilities.Earth.EarthTunnel.Range", 10); - config.addDefault("Abilities.Earth.EarthTunnel.Radius", 0.25); - config.addDefault("Abilities.Earth.EarthTunnel.Revert", true); - config.addDefault("Abilities.Earth.EarthTunnel.Interval", 30); - - config.addDefault("Abilities.Earth.Extraction.Enabled", true); - config.addDefault("Abilities.Earth.Extraction.Description", "This ability allows metalbenders to extract the minerals from ore blocks. To use, simply tap sneak while looking at an ore block with metal in it (iron, gold, quartz) and the ore will be extracted and drop in front of you. This ability has a small chance of doubling or tripling the loot. This ability has a short cooldown."); - config.addDefault("Abilities.Earth.Extraction.Cooldown", 10000); - config.addDefault("Abilities.Earth.Extraction.TripleLootChance", 15); - config.addDefault("Abilities.Earth.Extraction.DoubleLootChance", 40); - - config.addDefault("Abilities.Earth.LavaFlow.Enabled", true); - config.addDefault("Abilities.Earth.LavaFlow.Description", "This ability allows an Earthbender to create lava using the Earth around them. To use, simply hold sneak (Default: Shift) to create a lava moat that surrounds you, press sneak again to remove the moat. Left click an Earthbendable block to create a pool of lava after a small delay. Additionally, you can left click at any time to turn lava back into its original state -- Earth."); - config.addDefault("Abilities.Earth.LavaFlow.ShiftCooldown", 16000); - config.addDefault("Abilities.Earth.LavaFlow.ClickLavaCooldown", 10000); - config.addDefault("Abilities.Earth.LavaFlow.ClickLandCooldown", 500); - config.addDefault("Abilities.Earth.LavaFlow.ShiftCleanupDelay", 10000); - config.addDefault("Abilities.Earth.LavaFlow.ClickLavaCleanupDelay", 7000); - config.addDefault("Abilities.Earth.LavaFlow.ClickLandCleanupDelay", 20000); - config.addDefault("Abilities.Earth.LavaFlow.ClickRange", 10.0); - config.addDefault("Abilities.Earth.LavaFlow.ShiftRadius", 8.0); - config.addDefault("Abilities.Earth.LavaFlow.ShiftPlatformRadius", 1.5); - config.addDefault("Abilities.Earth.LavaFlow.ClickRadius", 5.0); - config.addDefault("Abilities.Earth.LavaFlow.ClickLavaCreateSpeed", 0.05); - config.addDefault("Abilities.Earth.LavaFlow.ClickLandCreateSpeed", 0.10); - config.addDefault("Abilities.Earth.LavaFlow.ShiftFlowSpeed", 0.1); - config.addDefault("Abilities.Earth.LavaFlow.ShiftRemoveSpeed", 3.0); - config.addDefault("Abilities.Earth.LavaFlow.ClickLavaStartDelay", 1500); - config.addDefault("Abilities.Earth.LavaFlow.ClickLandStartDelay", 0); - config.addDefault("Abilities.Earth.LavaFlow.UpwardFlow", 2); - config.addDefault("Abilities.Earth.LavaFlow.DownwardFlow", 4); - config.addDefault("Abilities.Earth.LavaFlow.AllowNaturalFlow", false); - config.addDefault("Abilities.Earth.LavaFlow.ParticleDensity", 0.33); - - config.addDefault("Abilities.Earth.EarthSmash.Enabled", true); - config.addDefault("Abilities.Earth.EarthSmash.Description", "To raise an EarthSmash hold sneak (default: shift) for approximately 1.5 seconds, " + - "then release while aiming at dirt. To grab the EarthSmash aim at the center and hold sneak, " + - "the EarthSmash will follow your mouse. You can shoot the EarthSmash by grabbing onto it and left clicking. " + - "To ride the EarthSmash simply hop ontop of it and hold sneak while aiming in the direction that you wish to go. " + - "Another way to ride an EarthSmash is to grab it with sneak and then right click it. " + - "Use EarthSmash as a defensive shield, a powerful attack, or an advanced means of transportation."); - config.addDefault("Abilities.Earth.EarthSmash.AllowGrab", true); - config.addDefault("Abilities.Earth.EarthSmash.AllowShooting", true); - config.addDefault("Abilities.Earth.EarthSmash.AllowFlight", true); - config.addDefault("Abilities.Earth.EarthSmash.GrabRange", 10); - config.addDefault("Abilities.Earth.EarthSmash.ChargeTime", 1200); - config.addDefault("Abilities.Earth.EarthSmash.Cooldown", 0); - config.addDefault("Abilities.Earth.EarthSmash.ShotRange", 30); - config.addDefault("Abilities.Earth.EarthSmash.Damage", 6); - config.addDefault("Abilities.Earth.EarthSmash.Knockback", 3.5); - config.addDefault("Abilities.Earth.EarthSmash.Knockup", 0.15); - config.addDefault("Abilities.Earth.EarthSmash.FlightSpeed", 0.72); - config.addDefault("Abilities.Earth.EarthSmash.FlightTimer", 3000); - config.addDefault("Abilities.Earth.EarthSmash.RemoveTimer", 30000); - -// config.addDefault("Abilities.Earth.LavaSurge.Enabled", true); -// config.addDefault("Abilities.Earth.LavaSurge.Description", "LavaSurge is a fundamental move for any Lavabender out there. To use, simply sneak (Default: Shift) while looking at a source of Earth or Lava, then click in a direction. A surge of lava will swiftly travel towards the target you were pointing at, dealing moderate damage, a large knockback, and setting them on fire."); -// config.addDefault("Abilities.Earth.LavaSurge.Damage", 4); -// config.addDefault("Abilities.Earth.LavaSurge.Cooldown", 1000); -// config.addDefault("Abilities.Earth.LavaSurge.FractureRadius", 1); -// config.addDefault("Abilities.Earth.LavaSurge.PrepareRange", 7); -// config.addDefault("Abilities.Earth.LavaSurge.TravelRange", 15); -// config.addDefault("Abilities.Earth.LavaSurge.MaxLavaWaves", 10); -// config.addDefault("Abilities.Earth.LavaSurge.SourceCanBeEarth", true); - - config.addDefault("Abilities.Earth.MetalClips.Enabled", true); - config.addDefault("Abilities.Earth.MetalClips.Description", "MetalClips has the potential to be both an offensive and a utility ability. To start, you must carry smelted Iron Ingots in your inventory. To apply the clips onto an entity, simply click at them. If the entity is a Zombie, a Skeleton, or a Player, the clips will form armor around the entity, giving you some control over them. Each additional clip will give you more control. If you have permission to do so, you may crush the entity against a wall with a 4th clip, hurting them. Without explicit permissions, you will only be able to strap three clips on your target. If the entity is not one of the above, the clip will simply do damage and fall to the ground, to be collected."); - config.addDefault("Abilities.Earth.MetalClips.Damage", 2); - config.addDefault("Abilities.Earth.MetalClips.DamageInterval", 500); - config.addDefault("Abilities.Earth.MetalClips.MagnetRange", 20); - config.addDefault("Abilities.Earth.MetalClips.MagnetPower", 0.6); - config.addDefault("Abilities.Earth.MetalClips.Cooldown", 1000); - config.addDefault("Abilities.Earth.MetalClips.Duration", 10000); - - - 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.Earth.Shockwave.Enabled", true); - config.addDefault("Abilities.Earth.Shockwave.Description", "This is one of the most powerful moves in the earthbender's arsenal. " - + "To use, you must first charge it by holding sneak (default: shift). " - + "Once charged, you can release sneak to create an enormous shockwave of earth, " - + "disturbing all earth around you and expanding radially outwards. " - + "Anything caught in the shockwave will be blasted back and dealt damage. " - + "If you instead click while charged, the disruption is focused in a cone in front of you. " - + "Lastly, if you fall from a great enough height with this ability selected, you will automatically create a shockwave."); - config.addDefault("Abilities.Earth.Shockwave.FallThreshold", 10); - config.addDefault("Abilities.Earth.Shockwave.ChargeTime", 2500); - config.addDefault("Abilities.Earth.Shockwave.Damage", 5); - config.addDefault("Abilities.Earth.Shockwave.Knockback", 1.1); - config.addDefault("Abilities.Earth.Shockwave.Range", 15); - - config.addDefault("Abilities.Earth.Tremorsense.Enabled", true); - config.addDefault("Abilities.Earth.Tremorsense.Description", "This is a pure utility ability for earthbenders. If you are in an area of low-light and are standing on top of an earthbendable block, this ability will automatically turn that block into glowstone, visible *only by you*. If you lose contact with a bendable block, the light will go out as you have lost contact with the earth and cannot 'see' until you can touch earth again. Additionally, if you click with this ability selected, smoke will appear above nearby earth with pockets of air beneath them."); - config.addDefault("Abilities.Earth.Tremorsense.MaxDepth", 10); - config.addDefault("Abilities.Earth.Tremorsense.Radius", 5); - config.addDefault("Abilities.Earth.Tremorsense.LightThreshold", 7); - config.addDefault("Abilities.Earth.Tremorsense.Cooldown", 1000); - - config.addDefault("Abilities.Fire.Blaze.Enabled", true); - config.addDefault("Abilities.Fire.Blaze.Description", "To use, simply left-click in any direction. An arc of fire will flow from your location, igniting anything in its path. Additionally, tap sneak to engulf the area around you in roaring flames."); - config.addDefault("Abilities.Fire.Blaze.ArcOfFire.Arc", 20); - config.addDefault("Abilities.Fire.Blaze.ArcOfFire.Range", 9); - config.addDefault("Abilities.Fire.Blaze.RingOfFire.Range", 7); - - config.addDefault("Abilities.Fire.Combustion.Enabled", true); - config.addDefault("Abilities.Fire.Combustion.Description", "Combustion is a powerful ability only known by a few skilled Firebenders. It allows the bender to Firebend with their mind, concentrating energy to create a powerful blast. To use, simply tap sneak (Default: Shift) to launch the blast. This technique is highly destructive and very effective, it also comes with a long cooldown."); - config.addDefault("Abilities.Fire.Combustion.Cooldown", 15000); - // config.addDefault("Abilities.Fire.Combustion.ChargeTime", 5000); - config.addDefault("Abilities.Fire.Combustion.BreakBlocks", false); - config.addDefault("Abilities.Fire.Combustion.Power", 1.0); - config.addDefault("Abilities.Fire.Combustion.Damage", 5); - config.addDefault("Abilities.Fire.Combustion.Radius", 4); - config.addDefault("Abilities.Fire.Combustion.Range", 20); - config.addDefault("Abilities.Fire.Combustion.Speed", 25); - - config.addDefault("Abilities.Fire.FireBlast.Enabled", true); - config.addDefault("Abilities.Fire.FireBlast.Description","FireBlast is the most fundamental bending technique of a firebender. " - + "To use, simply left-click in a direction. A blast of fire will be created at your fingertips. " - + "If this blast contacts an enemy, it will dissipate and engulf them in flames, " - + "doing additional damage and knocking them back slightly. " - + "If the blast hits terrain, it will ignite the nearby area. " - + "Additionally, if you hold sneak, you will charge up the fireblast. " - + "If you release it when it's charged, it will instead launch a powerful " - + "fireball that explodes on contact."); - config.addDefault("Abilities.Fire.FireBlast.Speed", 15); - config.addDefault("Abilities.Fire.FireBlast.Range", 15); - config.addDefault("Abilities.Fire.FireBlast.Radius", 2); - config.addDefault("Abilities.Fire.FireBlast.Push", 0.3); - config.addDefault("Abilities.Fire.FireBlast.Damage", 2); - config.addDefault("Abilities.Fire.FireBlast.Cooldown", 1500); - config.addDefault("Abilities.Fire.FireBlast.Dissipate", false); - config.addDefault("Abilities.Fire.FireBlast.Charged.ChargeTime", 2000); - config.addDefault("Abilities.Fire.FireBlast.Charged.Damage", 4); - config.addDefault("Abilities.Fire.FireBlast.Charged.DamageRadius", 6); - config.addDefault("Abilities.Fire.FireBlast.Charged.Power", 1); - config.addDefault("Abilities.Fire.FireBlast.Charged.Range", 20); - - config.addDefault("Abilities.Fire.FireBurst.Enabled", true); - config.addDefault("Abilities.Fire.FireBurst.Description", "FireBurst is a very powerful firebending ability. " - + "To use, press and hold sneak to charge your burst. " - + "Once charged, you can either release sneak to launch a cone-shaped burst " - + "of flames in front of you, or click to release the burst in a sphere around you. "); - config.addDefault("Abilities.Fire.FireBurst.Damage", 3); - config.addDefault("Abilities.Fire.FireBurst.ChargeTime", 2500); - config.addDefault("Abilities.Fire.FireBurst.Range", 15); - - 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 " - + "controlled flight for a short time. This ability can be used mid-air to prevent falling " - + "to your death, but on the ground it can only be used if standing on a block that's " - + "ignitable (e.g. not snow or water)."); - config.addDefault("Abilities.Fire.FireJet.Speed", 0.7); - config.addDefault("Abilities.Fire.FireJet.Duration", 1500); - config.addDefault("Abilities.Fire.FireJet.Cooldown", 6000); - config.addDefault("Abilities.Fire.FireJet.IsAvatarStateToggle", true); - - config.addDefault("Abilities.Fire.FireShield.Enabled", true); - config.addDefault("Abilities.Fire.FireShield.Description", "FireShield is a basic defensive ability. " - + "Clicking with this ability selected will create a " - + "small disc of fire in front of you, which will block most " - + "attacks and bending. Alternatively, pressing and holding " - + "sneak creates a very small shield of fire, blocking most attacks. " - + "Creatures that contact this fire are ignited."); - config.addDefault("Abilities.Fire.FireShield.Radius", 3); - config.addDefault("Abilities.Fire.FireShield.DiscRadius", 1.5); - config.addDefault("Abilities.Fire.FireShield.Duration", 1000); - - 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.Solidify.Range", 10); - config.addDefault("Abilities.Fire.HeatControl.Solidify.Radius", 5); - config.addDefault("Abilities.Fire.HeatControl.Solidify.RevertTime", 20000); - config.addDefault("Abilities.Fire.HeatControl.Melt.Range", 15); - config.addDefault("Abilities.Fire.HeatControl.Melt.Radius", 5); - - config.addDefault("Abilities.Fire.Illumination.Enabled", true); - config.addDefault("Abilities.Fire.Illumination.Description", "This ability gives firebenders a means of illuminating the area. It is a toggle - clicking " - + "will create a torch that follows you around. The torch will only appear on objects that are " - + "ignitable and can hold a torch (e.g. not leaves or ice). If you get too far away from the torch, " - + "it will disappear, but will reappear when you get on another ignitable block. Clicking again " - + "dismisses this torch."); - config.addDefault("Abilities.Fire.Illumination.Range", 5); - - config.addDefault("Abilities.Fire.Lightning.Enabled", true); - config.addDefault("Abilities.Fire.Lightning.Description", "Hold sneak while selecting this ability to charge up a lightning strike. Once charged, release sneak to discharge the lightning to the targeted location."); - config.addDefault("Abilities.Fire.Lightning.Damage", 6.0); - config.addDefault("Abilities.Fire.Lightning.Range", 13.0); - config.addDefault("Abilities.Fire.Lightning.ChargeTime", 3500); - config.addDefault("Abilities.Fire.Lightning.Cooldown", 0); - config.addDefault("Abilities.Fire.Lightning.StunChance", 0.20); - config.addDefault("Abilities.Fire.Lightning.StunDuration", 30.0); - config.addDefault("Abilities.Fire.Lightning.MaxArcAngle", 30); - config.addDefault("Abilities.Fire.Lightning.SubArcChance", 0.025); - config.addDefault("Abilities.Fire.Lightning.ChainArcRange", 6.0); - config.addDefault("Abilities.Fire.Lightning.ChainArcChance", 0.50); - config.addDefault("Abilities.Fire.Lightning.MaxChainArcs", 2); - config.addDefault("Abilities.Fire.Lightning.WaterArcs", 4); - config.addDefault("Abilities.Fire.Lightning.WaterArcRange", 12.0); - config.addDefault("Abilities.Fire.Lightning.SelfHitWater", true); - config.addDefault("Abilities.Fire.Lightning.SelfHitClose", true); - config.addDefault("Abilities.Fire.Lightning.ArcOnIce", false); - - - config.addDefault("Abilities.Fire.WallOfFire.Enabled", true); - config.addDefault("Abilities.Fire.WallOfFire.Description", "To use this ability, click at a location. A wall of fire will appear at this location, igniting enemies caught in it and blocking projectiles."); - config.addDefault("Abilities.Fire.WallOfFire.Range", 4); - config.addDefault("Abilities.Fire.WallOfFire.Height", 4); - config.addDefault("Abilities.Fire.WallOfFire.Width", 4); - config.addDefault("Abilities.Fire.WallOfFire.Duration", 5000); - config.addDefault("Abilities.Fire.WallOfFire.Damage", 2); - config.addDefault("Abilities.Fire.WallOfFire.Cooldown", 7500); - config.addDefault("Abilities.Fire.WallOfFire.Interval", 500); - - config.addDefault("Abilities.Fire.FireCombo.Enabled", true); - config.addDefault("Abilities.Fire.FireCombo.FireKick.Range", 7.0); - config.addDefault("Abilities.Fire.FireCombo.FireKick.Damage", 3.0); - config.addDefault("Abilities.Fire.FireCombo.FireKick.Cooldown", 2000); - config.addDefault("Abilities.Fire.FireCombo.FireSpin.Range", 7); - config.addDefault("Abilities.Fire.FireCombo.FireSpin.Damage", 3.0); - config.addDefault("Abilities.Fire.FireCombo.FireSpin.Knockback", 3.2); - config.addDefault("Abilities.Fire.FireCombo.FireSpin.Cooldown", 2000); - config.addDefault("Abilities.Fire.FireCombo.FireWheel.Range", 20.0); - config.addDefault("Abilities.Fire.FireCombo.FireWheel.Damage", 4.0); - config.addDefault("Abilities.Fire.FireCombo.FireWheel.Speed", 0.55); - config.addDefault("Abilities.Fire.FireCombo.FireWheel.Cooldown", 200); - config.addDefault("Abilities.Fire.FireCombo.JetBlast.Speed", 1.2); - config.addDefault("Abilities.Fire.FireCombo.JetBlast.Cooldown", 6000); - config.addDefault("Abilities.Fire.FireCombo.JetBlaze.Speed", 1.1); - config.addDefault("Abilities.Fire.FireCombo.JetBlaze.Damage", 3); - config.addDefault("Abilities.Fire.FireCombo.JetBlaze.Cooldown", 6000); - - config.addDefault("Abilities.Chi.Passive.FallReductionFactor", 0.5); - config.addDefault("Abilities.Chi.Passive.Speed", 1); - config.addDefault("Abilities.Chi.Passive.Jump", 2); - config.addDefault("Abilities.Chi.Passive.BlockChi.Duration", 2500); - config.addDefault("Abilities.Chi.Passive.DodgeChange", 25); - - config.addDefault("Abilities.Chi.AcrobatStance.Enabled", true); - config.addDefault("Abilities.Chi.AcrobatStance.Description", "AcrobatStance gives a Chiblocker a higher probability of blocking a Bender's Chi while granting them a Speed and Jump Boost. It also increases the rate at which the hunger bar depletes. To use, simply left click. Left clicking again will de-activate the stance."); - config.addDefault("Abilities.Chi.ChiBlockBoost", 0.1); - - config.addDefault("Abilities.Chi.HighJump.Enabled", true); - config.addDefault("Abilities.Chi.HighJump.Description", "To use this ability, simply click. You will jump quite high. This ability has a short cooldown."); - config.addDefault("Abilities.Chi.HighJump.Height", 1); - config.addDefault("Abilities.Chi.HighJump.Cooldown", 10000); - - config.addDefault("Abilities.Chi.Paralyze.Enabled", true); - config.addDefault("Abilities.Chi.Paralyze.Description", "Paralyzes the target, making them unable to do anything for a short " - + "period of time. This ability has a long cooldown."); - config.addDefault("Abilities.Chi.Paralyze.Cooldown", 15000); - config.addDefault("Abilities.Chi.Paralyze.Duration", 2000); - - config.addDefault("Abilities.Chi.RapidPunch.Enabled", true); - config.addDefault("Abilities.Chi.RapidPunch.Description", "This ability allows the chiblocker to punch rapidly in a short period. To use, simply punch. This has a short cooldown."); - config.addDefault("Abilities.Chi.RapidPunch.Damage", 1); - config.addDefault("Abilities.Chi.RapidPunch.Distance", 4); - config.addDefault("Abilities.Chi.RapidPunch.Cooldown", 15000); - config.addDefault("Abilities.Chi.RapidPunch.Punches", 4); - - config.addDefault("Abilities.Chi.Smokescreen.Enabled", true); - config.addDefault("Abilities.Chi.Smokescreen.Description", "Smokescren, if used correctly, can serve as a defensive and offensive ability for Chiblockers. To use, simply left click and you will toss out a Smoke Bomb. When the bomb hits the ground, it will explode and give all players within a small radius of the explosion temporary blindness, allowing you to either get away, or move in for the kill. This ability has a long cooldown."); - config.addDefault("Abilities.Chi.Smokescreen.Cooldown", 50000); - config.addDefault("Abilities.Chi.Smokescreen.Radius", 4); - config.addDefault("Abilities.Chi.Smokescreen.Duration", 15); - - config.addDefault("Abilities.Chi.WarriorStance.Enabled", true); - config.addDefault("Abilities.Chi.WarriorStance.Description", "WarriorStance gives a Chiblocker increased damage but makes them a tad more vulnerable. To activate, simply left click."); - config.addDefault("Abilities.Chi.WarriorStance.Strength", 1); - config.addDefault("Abilities.Chi.WarriorStance.Resistance", -1); - - config.addDefault("Abilities.Chi.QuickStrike.Enabled", true); - config.addDefault("Abilities.Chi.QuickStrike.Description", "QuickStrike enables a chiblocker to quickly strike an enemy, potentially blocking their chi."); - config.addDefault("Abilities.Chi.QuickStrike.Damage", 2); - config.addDefault("Abilities.Chi.QuickStrike.ChiBlockChance", 20); - - config.addDefault("Abilities.Chi.SwiftKick.Enabled", true); - config.addDefault("Abilities.Chi.SwiftKick.Description", "SwiftKick allows a chiblocker to swiftly kick an enemy, potentially blocking their chi. The chiblocker must be in the air to use this ability."); - config.addDefault("Abilities.Chi.SwiftKick.Damage", 4); - config.addDefault("Abilities.Chi.SwiftKick.ChiBlockChance", 30); - - config.addDefault("Abilities.Chi.ChiCombo.ParalyzeDuration", 10000); - - config.addDefault("Storage.engine", "sqlite"); - - config.addDefault("Storage.MySQL.host", "localhost"); - config.addDefault("Storage.MySQL.port", 3306); - config.addDefault("Storage.MySQL.pass", ""); - config.addDefault("Storage.MySQL.db", "minecraft"); - config.addDefault("Storage.MySQL.user", "root"); - - config.addDefault("debug", false); - config.options().copyDefaults(true); - plugin.saveConfig(); - } -} +package com.projectkorra.ProjectKorra; + +import java.util.ArrayList; + +import org.bukkit.configuration.file.FileConfiguration; + +public class ConfigManager { + + static ProjectKorra plugin; + + public ConfigManager(ProjectKorra plugin) { + ConfigManager.plugin = plugin; + configCheck(); + } + + public static void configCheck() { + + FileConfiguration config = ProjectKorra.plugin.getConfig(); + + ArrayList earthbendable = new ArrayList(); + earthbendable.add("STONE"); + earthbendable.add("CLAY"); + earthbendable.add("COAL_ORE"); + earthbendable.add("DIAMOND_ORE"); + earthbendable.add("DIRT"); + earthbendable.add("GOLD_ORE"); + earthbendable.add("GRASS"); + earthbendable.add("GRAVEL"); + earthbendable.add("IRON_ORE"); + earthbendable.add("LAPIS_ORE"); + earthbendable.add("NETHERRACK"); + earthbendable.add("REDSTONE_ORE"); + earthbendable.add("SAND"); + earthbendable.add("SANDSTONE"); + earthbendable.add("MYCEL"); + + ArrayList metals = new ArrayList(); + metals.add("IRON_BLOCK"); + metals.add("GOLD_BLOCK"); + metals.add("QUARTZ_BLOCK"); + + config.addDefault("Properties.Chat.Enable", true); + config.addDefault("Properties.Chat.Format", ": "); + config.addDefault("Properties.Chat.Prefixes.Air", "[Airbender]"); + config.addDefault("Properties.Chat.Prefixes.Water", "[Waterbender]"); + config.addDefault("Properties.Chat.Prefixes.Earth", "[Earthbender]"); + config.addDefault("Properties.Chat.Prefixes.Fire", "[Firebender]"); + config.addDefault("Properties.Chat.Prefixes.Chi", "[Chiblocker]"); + config.addDefault("Properties.Chat.Prefixes.Avatar", "[Avatar]"); + config.addDefault("Properties.Chat.Colors.Avatar", "DARK_PURPLE"); + config.addDefault("Properties.Chat.Colors.Air", "GRAY"); + config.addDefault("Properties.Chat.Colors.AirSub", "DARK_GRAY"); + config.addDefault("Properties.Chat.Colors.Water", "AQUA"); + config.addDefault("Properties.Chat.Colors.WaterSub", "DARK_AQUA"); + config.addDefault("Properties.Chat.Colors.Earth", "GREEN"); + config.addDefault("Properties.Chat.Colors.EarthSub", "DARK_GREEN"); + config.addDefault("Properties.Chat.Colors.Fire", "RED"); + config.addDefault("Properties.Chat.Colors.FireSub", "DARK_RED"); + config.addDefault("Properties.Chat.Colors.Chi", "GOLD"); + + config.addDefault("Properties.ImportEnabled", true); + config.addDefault("Properties.BendingAffectFallingSand.Normal", true); + config.addDefault("Properties.BendingAffectFallingSand.NormalStrengthMultiplier", 1.0); + config.addDefault("Properties.BendingAffectFallingSand.TNT", true); + config.addDefault("Properties.BendingAffectFallingSand.TNTStrengthMultiplier", 1.0); + config.addDefault("Properties.GlobalCooldown", 500); + config.addDefault("Properties.SeaLevel", 62); + + config.addDefault("Properties.HorizontalCollisionPhysics.Enabled", true); + config.addDefault("Properties.HorizontalCollisionPhysics.WallDamageMinimumDistance", 5.0); + + config.addDefault("Properties.CustomItems.GrapplingHook.Enable", true); + config.addDefault("Properties.CustomItems.GrapplingHook.IronUses", 25); + config.addDefault("Properties.CustomItems.GrapplingHook.GoldUses", 50); + + config.addDefault("Properties.RegionProtection.AllowHarmlessAbilities", true); + config.addDefault("Properties.RegionProtection.RespectWorldGuard", true); + config.addDefault("Properties.RegionProtection.RespectGriefPrevention", true); + config.addDefault("Properties.RegionProtection.RespectFactions", true); + config.addDefault("Properties.RegionProtection.RespectTowny", true); + config.addDefault("Properties.RegionProtection.RespectPreciousStones", true); + config.addDefault("Properties.RegionProtection.RespectLWC", true); + config.addDefault("Properties.RegionProtection.CacheBlockTime", 5000); + + config.addDefault("Properties.TagAPI.Enabled", true); + + config.addDefault("Properties.Air.CanBendWithWeapons", false); + config.addDefault("Properties.Air.Particles", "smoke"); + config.addDefault("Properties.Air.PlaySound", true); + + config.addDefault("Properties.Water.CanBendWithWeapons", true); + config.addDefault("Properties.Water.NightFactor", 1.5); + config.addDefault("Properties.Water.FullMoonFactor", 3.0); + config.addDefault("Properties.Water.CanBendPackedIce", true); + config.addDefault("Properties.Water.PlaySound", true); + + config.addDefault("Properties.Earth.RevertEarthbending", true); + config.addDefault("Properties.Earth.SafeRevert", true); + config.addDefault("Properties.Earth.RevertCheckTime", 300000); + config.addDefault("Properties.Earth.CanBendWithWeapons", true); + config.addDefault("Properties.Earth.EarthbendableBlocks", earthbendable); + config.addDefault("Properties.Earth.MetalBlocks", metals); + config.addDefault("Properties.Earth.MetalPowerFactor", 1.5); + config.addDefault("Properties.Earth.PlaySound", true); + + config.addDefault("Properties.Fire.CanBendWithWeapons", true); + config.addDefault("Properties.Fire.DayFactor", 1.5); + config.addDefault("Properties.Fire.PlaySound", true); + + 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 " + + "all sources, regenerates health rapidly, and is granted extreme speed. Nearly all abilities " + + "are incredibly amplified in this state. Additionally, AirShield and FireJet become toggle-able " + + "abilities and last until you deactivate them or the Avatar State. Click again with the Avatar " + + "State selected to deactivate it."); + config.addDefault("Abilities.AvatarState.Cooldown", 7200000); + config.addDefault("Abilities.AvatarState.Duration", 480000); + config.addDefault("Abilities.AvatarState.PowerMultiplier", 5); + config.addDefault("Abilities.AvatarState.PotionEffects.Regeneration.Enabled", true); + config.addDefault("Abilities.AvatarState.PotionEffects.Regeneration.Power", 3); + config.addDefault("Abilities.AvatarState.PotionEffects.Speed.Enabled", true); + config.addDefault("Abilities.AvatarState.PotionEffects.Speed.Power", 3); + config.addDefault("Abilities.AvatarState.PotionEffects.DamageResistance.Enabled", true); + config.addDefault("Abilities.AvatarState.PotionEffects.FireResistance.Enabled", true); + config.addDefault("Abilities.AvatarState.PotionEffects.FireResistance.Power", 3); + + config.addDefault("Abilities.Air.Passive.Factor", 0.3); + config.addDefault("Abilities.Air.Passive.Speed", 2); + config.addDefault("Abilities.Air.Passive.Jump", 3); + + config.addDefault("Abilities.Air.AirBlast.Enabled", true); + config.addDefault("Abilities.Air.AirBlast.Description", "AirBlast is the most fundamental bending technique of an airbender." + + " To use, simply left-click in a direction. A gust of wind will be" + + " created at your fingertips, launching anything in its path harmlessly back." + + " A gust of air can extinguish fires on the ground or on a player, can cool lava, and " + + "can flip levers and activate buttons. Additionally, tapping sneak will change the " + + "origin of your next AirBlast to your targeted location."); + config.addDefault("Abilities.Air.AirBlast.Speed", 25); + config.addDefault("Abilities.Air.AirBlast.Range", 20); + config.addDefault("Abilities.Air.AirBlast.Radius", 2); + config.addDefault("Abilities.Air.AirBlast.Push", 3.5); + + config.addDefault("Abilities.Air.AirBubble.Enabled", true); + config.addDefault("Abilities.Air.AirBubble.Description", "To use, the bender must merely have the ability selected. All water around the user in a small bubble will vanish, replacing itself once the user either gets too far away or selects a different ability."); + config.addDefault("Abilities.Air.AirBubble.Radius", 7); + + config.addDefault("Abilities.Air.AirBurst.Enabled", true); + config.addDefault("Abilities.Air.AirBurst.Description", "AirBurst is one of the most powerful abilities in the airbender's arsenal. " + + "To use, press and hold sneak to charge your burst. " + + "Once charged, you can either release sneak to launch a cone-shaped burst " + + "of air in front of you, or click to release the burst in a sphere around you. " + + "Additionally, having this ability selected when you land on the ground from a " + + "large enough fall will create a burst of air around you."); + config.addDefault("Abilities.Air.AirBurst.FallThreshold", 10); + config.addDefault("Abilities.Air.AirBurst.PushFactor", 1.5); + config.addDefault("Abilities.Air.AirBurst.ChargeTime", 1750); + config.addDefault("Abilities.Air.AirBurst.Damage", 0); + + config.addDefault("Abilities.Air.AirScooter.Enabled", true); + config.addDefault("Abilities.Air.AirScooter.Description", "AirScooter is a fast means of transportation. To use, sprint, jump then click with " + + "this ability selected. You will hop on a scooter of air and be propelled forward " + + "in the direction you're looking (you don't need to press anything). " + + "This ability can be used to levitate above liquids, but it cannot go up steep slopes. " + + "Any other actions will deactivate this ability."); + config.addDefault("Abilities.Air.AirScooter.Speed", .675); + + config.addDefault("Abilities.Air.Tornado.Enabled", true); + config.addDefault("Abilities.Air.Tornado.Description", "To use, simply sneak (default: shift). " + + "This will create a swirling vortex at the targeted location. " + + "Any creature or object caught in the vortex will be launched up " + + "and out in some random direction. If another player gets caught " + + "in the vortex, the launching effect is minimal. Tornado can " + + "also be used to transport the user. If the user gets caught in his/her " + + "own tornado, his movements are much more manageable. Provided the user doesn't " + + "fall out of the vortex, it will take him to a maximum height and move him in " + + "the general direction he's looking. Skilled airbenders can scale anything " + + "with this ability."); + + config.addDefault("Abilities.Air.AirShield.Enabled", true); + config.addDefault("Abilities.Air.AirShield.Description", "Air Shield is one of the most powerful defensive techniques in existence. " + + "To use, simply sneak (default: shift). " + + "This will create a whirlwind of air around the user, " + + "with a small pocket of safe space in the center. " + + "This wind will deflect all projectiles and will prevent any creature from " + + "entering it for as long as its maintained."); + config.addDefault("Abilities.Air.AirShield.Radius", 7); + config.addDefault("Abilities.Air.AirShield.IsAvatarStateToggle", true); + + config.addDefault("Abilities.Air.AirSpout.Enabled", true); + config.addDefault("Abilities.Air.AirSpout.Description", "This ability gives the airbender limited sustained levitation. It is a " + + "toggle - click to activate and form a whirling spout of air " + + "beneath you, lifting you up. You can bend other abilities while using AirSpout. " + + "Click again to deactivate this ability."); + config.addDefault("Abilities.Air.AirSpout.Height", 20); + + config.addDefault("Abilities.Air.AirSuction.Enabled", true); + config.addDefault("Abilities.Air.AirSuction.Description", "To use, simply left-click in a direction. A gust of wind will originate as far as it can in that direction and flow towards you, sucking anything in its path harmlessly with it. Skilled benders can use this technique to pull items from precarious locations. Additionally, tapping sneak will change the origin of your next AirSuction to your targeted location."); + config.addDefault("Abilities.Air.AirSuction.Speed", 25); + config.addDefault("Abilities.Air.AirSuction.Range", 20); + config.addDefault("Abilities.Air.AirSuction.Radius", 2); + config.addDefault("Abilities.Air.AirSuction.Push", 3.5); + + config.addDefault("Abilities.Air.AirSwipe.Enabled", true); + config.addDefault("Abilities.Air.AirSwipe.Description", "To use, simply left-click in a direction. An arc of air will flow from you towards that direction, cutting and pushing back anything in its path. Its damage is minimal, but it still sends the message. This ability will extinguish fires, cool lava, and cut things like grass, mushrooms, and flowers. Additionally, you can charge it by holding sneak. Charging before attacking will increase damage and knockback, up to a maximum."); + config.addDefault("Abilities.Air.AirSwipe.Damage", 2); + config.addDefault("Abilities.Air.AirSwipe.Range", 16); + config.addDefault("Abilities.Air.AirSwipe.Radius", 2); + config.addDefault("Abilities.Air.AirSwipe.Push", 1); + config.addDefault("Abilities.Air.AirSwipe.Arc", 20); + config.addDefault("Abilities.Air.AirSwipe.Speed", 25); + config.addDefault("Abilities.Air.AirSwipe.Cooldown", 1500); + config.addDefault("Abilities.Air.AirSwipe.ChargeFactor", 3); + config.addDefault("Abilities.Air.AirSwipe.MaxChargeTime", 3000); + + config.addDefault("Abilities.Air.Flight.Enabled", true); + config.addDefault("Abilities.Air.Flight.Description", "Jump in the air, crouch (default: shift) and hold with this ability bound and you will glide around in the direction you look. While flying, click to Hover. Click again to disable Hovering."); + config.addDefault("Abilities.Air.Flight.HoverEnabled", true); + + config.addDefault("Abilities.Air.Suffocate.Enabled", true); + config.addDefault("Abilities.Air.Suffocate.Description", "This ability is one of the most dangerous abilities an Airbender possesses. To use, simply look at an entity and hold shift. The entity will begin taking damage as you extract the air from their lungs. Any bender caught in this sphere will only be able to use basic moves, such as AirSwipe, WaterManipulation, FireBlast, or EarthBlast. An entity can be knocked out of the sphere by certain bending arts, and your attention will be disrupted if you are hit by bending."); + config.addDefault("Abilities.Air.Suffocate.ChargeTime", 1000); + config.addDefault("Abilities.Air.Suffocate.Cooldown", 0); + config.addDefault("Abilities.Air.Suffocate.Range", 15); + config.addDefault("Abilities.Air.Suffocate.Damage", 2); + config.addDefault("Abilities.Air.Suffocate.DamageInitialDelay", 2); + config.addDefault("Abilities.Air.Suffocate.DamageInterval", 1); + config.addDefault("Abilities.Air.Suffocate.SlowPotency", 1); + config.addDefault("Abilities.Air.Suffocate.SlowDelay", 0.5); + config.addDefault("Abilities.Air.Suffocate.SlowInterval", 1.25); + config.addDefault("Abilities.Air.Suffocate.BlindPotentcy", 30); + config.addDefault("Abilities.Air.Suffocate.BlindDelay", 2); + config.addDefault("Abilities.Air.Suffocate.BlindInterval", 1.5); + config.addDefault("Abilities.Air.Suffocate.CanBeUsedOnUndeadMobs", true); + config.addDefault("Abilities.Air.Suffocate.RequireConstantAim", true); + config.addDefault("Abilities.Air.Suffocate.RequireConstantAimRadius", 5); + config.addDefault("Abilities.Air.Suffocate.AnimationRadius", 2.0); + config.addDefault("Abilities.Air.Suffocate.AnimationParticleAmount", 2); + config.addDefault("Abilities.Air.Suffocate.AnimationSpeed", 1.0); + + config.addDefault("Abilities.Air.Tornado.Radius", 10); + config.addDefault("Abilities.Air.Tornado.Height", 25); + config.addDefault("Abilities.Air.Tornado.Range", 25); + config.addDefault("Abilities.Air.Tornado.MobPushFactor", 1); + config.addDefault("Abilities.Air.Tornado.PlayerPushFactor", 1); + + config.addDefault("Abilities.Air.AirCombo.Enabled", true); + config.addDefault("Abilities.Air.AirCombo.Twister.Speed", 0.35); + config.addDefault("Abilities.Air.AirCombo.Twister.Range", 16); + config.addDefault("Abilities.Air.AirCombo.Twister.Height", 8); + config.addDefault("Abilities.Air.AirCombo.Twister.Radius", 3.5); + config.addDefault("Abilities.Air.AirCombo.Twister.RemoveDelay", 1500); + config.addDefault("Abilities.Air.AirCombo.Twister.Cooldown", 10000); + config.addDefault("Abilities.Air.AirCombo.Twister.DegreesPerParticle", 7); + config.addDefault("Abilities.Air.AirCombo.Twister.HeightPerParticle", 1.25); + config.addDefault("Abilities.Air.AirCombo.AirStream.Speed", 0.5); + config.addDefault("Abilities.Air.AirCombo.AirStream.Range", 40); + config.addDefault("Abilities.Air.AirCombo.AirStream.EntityDuration", 4000); + config.addDefault("Abilities.Air.AirCombo.AirStream.EntityHeight", 14); + config.addDefault("Abilities.Air.AirCombo.AirStream.Cooldown", 6000); + config.addDefault("Abilities.Air.AirCombo.AirSweep.Speed", 1.4); + config.addDefault("Abilities.Air.AirCombo.AirSweep.Range", 14); + config.addDefault("Abilities.Air.AirCombo.AirSweep.Damage", 4); + config.addDefault("Abilities.Air.AirCombo.AirSweep.Knockback", 3.5); + config.addDefault("Abilities.Air.AirCombo.AirSweep.Cooldown", 5000); + + config.addDefault("Abilities.Water.Passive.SwimSpeedFactor", 0.7); + + config.addDefault("Abilities.Water.Bloodbending.Enabled", true); + config.addDefault("Abilities.Water.Bloodbending.Description", "This ability was made illegal for a reason. With this ability selected, sneak while " + + "targetting something and you will bloodbend that target. Bloodbent targets cannot move, " + + "bend or attack. You are free to control their actions by looking elsewhere - they will " + + "be forced to move in that direction. Additionally, clicking while bloodbending will " + + "launch that target off in the direction you're looking. " + + "People who are capable of bloodbending are immune to your technique, and you are immune to theirs."); + config.addDefault("Abilities.Water.Bloodbending.CanOnlyBeUsedAtNight", false); + config.addDefault("Abilities.Water.Bloodbending.CanBeUsedOnUndeadMobs", true); + config.addDefault("Abilities.Water.Bloodbending.ThrowFactor", 2); + config.addDefault("Abilities.Water.Bloodbending.Range", 10); + config.addDefault("Abilities.Water.Bloodbending.HoldTime", 0); + config.addDefault("Abilities.Water.Bloodbending.Cooldown", 0); + config.addDefault("Abilities.Water.Bloodbending.CanOnlyBeUsedDuringFullMoon", false); + + config.addDefault("Abilities.Water.HealingWaters.Enabled", true); + config.addDefault("Abilities.Water.HealingWaters.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."); + config.addDefault("Abilities.Water.HealingWaters.Radius", 5); + config.addDefault("Abilities.Water.HealingWaters.Interval", 750); + config.addDefault("Abilities.Water.HealingWaters.Power", 1); + + 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, " + + "will raise a spike of ice up, damaging and slowing the target. Tapping sneak (shift) while" + + " selecting a water source will select that source that can then 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) while not selecting a source, many ice spikes will erupt from around you, " + + "damaging and slowing those targets."); + config.addDefault("Abilities.Water.IceSpike.Cooldown", 2000); + config.addDefault("Abilities.Water.IceSpike.Damage", 2); + config.addDefault("Abilities.Water.IceSpike.Range", 20); + config.addDefault("Abilities.Water.IceSpike.ThrowingMult", 0.7); + config.addDefault("Abilities.Water.IceSpike.Height", 6); + config.addDefault("Abilities.Water.IceSpike.Projectile.Range", 20); + config.addDefault("Abilities.Water.IceSpike.Projectile.Damage", 1); + + config.addDefault("Abilities.Water.OctopusForm.Enabled", true); + config.addDefault("Abilities.Water.OctopusForm.Description", "This ability allows the waterbender to manipulate a large quantity of water into a form resembling that of an octopus. " + + "To use, click to select a water source. Then, hold sneak to channel this ability. " + + "While channeling, the water will form itself around you and has a chance to block incoming attacks. " + + "Additionally, you can click while channeling to attack things near you, dealing damage and knocking them back. " + + "Releasing shift at any time will dissipate the form."); + config.addDefault("Abilities.Water.OctopusForm.Range", 10); + config.addDefault("Abilities.Water.OctopusForm.AttackRange", 2.5); + config.addDefault("Abilities.Water.OctopusForm.Radius", 3); + config.addDefault("Abilities.Water.OctopusForm.Damage", 3); + config.addDefault("Abilities.Water.OctopusForm.Knockback", 1.75); + config.addDefault("Abilities.Water.OctopusForm.FormDelay", 50); + + config.addDefault("Abilities.Water.PhaseChange.Enabled", true); + config.addDefault("Abilities.Water.PhaseChange.Description", "To use, simply left-click. " + + "Any water you are looking at within range will instantly freeze over into solid ice. " + + "Provided you stay within range of the ice and do not unbind FreezeMelt, " + + "that ice will not thaw. If, however, you do either of those the ice will instantly thaw. " + + "If you sneak (default: shift), anything around where you are looking at will instantly melt. " + + "Since this is a more favorable state for these things, they will never re-freeze unless they " + + "would otherwise by nature or some other bending ability. Additionally, if you tap sneak while " + + "targetting water with FreezeMelt, it will evaporate water around that block that is above " + + "sea level. "); + config.addDefault("Abilities.Water.PhaseChange.Range", 20); + config.addDefault("Abilities.Water.PhaseChange.Radius", 5); + + config.addDefault("Abilities.Water.Surge.Enabled", true); + config.addDefault("Abilities.Water.Surge.Description", "This ability has two distinct features. If you sneak to select a source block, you can then click in a direction and a large wave will be launched in that direction. If you sneak again while the wave is en route, the wave will freeze the next target it hits. If, instead, you click to select a source block, you can hold sneak to form a wall of water at your cursor location. Click to shift between a water wall and an ice wall. Release sneak to dissipate it."); + config.addDefault("Abilities.Water.Surge.Wave.Radius", 3); + config.addDefault("Abilities.Water.Surge.Wave.Range", 20); + config.addDefault("Abilities.Water.Surge.Wave.HorizontalPush", 1); + config.addDefault("Abilities.Water.Surge.VerticalPush", 0.2); + config.addDefault("Abilities.Water.Surge.Wall.Range", 5); + config.addDefault("Abilities.Water.Surge.Wall.Radius", 2); + + config.addDefault("Abilities.Water.Torrent.Enabled", true); + config.addDefault("Abilities.Water.Torrent.Description", "Torrent is one of the strongest moves in a waterbender's arsenal. To use, first click a source block to select it; then hold shift to begin streaming the water around you. Water flowing around you this way will damage and knock back nearby enemies and projectiles. If you release shift during this, you will create a large wave that expands outwards from you, launching anything in its path back. Instead, if you click you release the water and channel it to flow towards your cursor. Anything caught in the blast will be tossed about violently and take damage. Finally, if you click again when the water is torrenting, it will freeze the area around it when it is obstructed."); + config.addDefault("Abilities.Water.Torrent.Range", 25); + config.addDefault("Abilities.Water.Torrent.DeflectDamage", 1); + config.addDefault("Abilities.Water.Torrent.Damage", 2); + config.addDefault("Abilities.Water.Torrent.Wave.Radius", 15); + config.addDefault("Abilities.Water.Torrent.Wave.Knockback", 1.5); + config.addDefault("Abilities.Water.Torrent.Wave.Height", 1); + + config.addDefault("Abilities.Water.Plantbending.RegrowTime", 180000); + + config.addDefault("Abilities.Water.WaterArms.Enabled", true); + config.addDefault("Abilities.Water.WaterArms.Description", "One of the most diverse moves in a Waterbender's arsenal, this move creates tendrils " + + "of water from the players arms to emulate their actual arms. Each water arms mode will be binded to a slot, switch slots to change mode. " + + "To deactive the arms, hold Sneak and Double Left-Click." + + "\nPull - Use your Arms to pull blocks, items, mobs or even players towards you!" + + "\nPunch - An offensive attack, harming players or mobs!" + + "\nGrapple - Scale walls and speed across battlefields, using your Arms as a grappling hook!" + + "\nGrab - Grab an entity with your arm, and swing them about!" + + "\nFreeze - Use your Arms to fire small blasts of ice in any direction!" + + "\nSpear - Throw your Arms in any direction, freezing whatever it hits!"); + config.addDefault("Abilities.Water.WaterArms.SneakMessage", "Active Ability:"); + + config.addDefault("Abilities.Water.WaterArms.Arms.InitialLength", 4); + config.addDefault("Abilities.Water.WaterArms.Arms.SourceGrabRange", 4); + config.addDefault("Abilities.Water.WaterArms.Arms.MaxAttacks", 10); + config.addDefault("Abilities.Water.WaterArms.Arms.MaxAlternateUsage", 50); + config.addDefault("Abilities.Water.WaterArms.Arms.MaxIceShots", 5); + config.addDefault("Abilities.Water.WaterArms.Arms.Cooldown", 20000); + config.addDefault("Abilities.Water.WaterArms.Arms.AllowPlantSource", true); + + config.addDefault("Abilities.Water.WaterArms.Arms.Lightning.Enabled", true); + config.addDefault("Abilities.Water.WaterArms.Arms.Lightning.Damage", Double.valueOf(10.0)); + config.addDefault("Abilities.Water.WaterArms.Arms.Lightning.KillUser", false); + + config.addDefault("Abilities.Water.WaterArms.Arms.Cooldowns.UsageCooldownEnabled", false); + config.addDefault("Abilities.Water.WaterArms.Arms.Cooldowns.UsageCooldown", 200); + + config.addDefault("Abilities.Water.WaterArms.Whip.MaxLength", 20); + config.addDefault("Abilities.Water.WaterArms.Whip.MaxLengthWeak", 12); + + config.addDefault("Abilities.Water.WaterArms.Whip.NightAugments.MaxLength.Normal", 24); + config.addDefault("Abilities.Water.WaterArms.Whip.NightAugments.MaxLength.FullMoon", 30); + + config.addDefault("Abilities.Water.WaterArms.Whip.Punch.PunchDamage", Double.valueOf(3.0)); + + config.addDefault("Abilities.Water.WaterArms.Whip.Grapple.RespectRegions", false); + + config.addDefault("Abilities.Water.WaterArms.Whip.Grab.HoldTime", 10000); + + config.addDefault("Abilities.Water.WaterArms.Freeze.Range", 20); + config.addDefault("Abilities.Water.WaterArms.Freeze.Damage", Double.valueOf(2.0)); + + config.addDefault("Abilities.Water.WaterArms.Spear.Range", 40); + config.addDefault("Abilities.Water.WaterArms.Spear.Damage", Double.valueOf(4.0)); + config.addDefault("Abilities.Water.WaterArms.Spear.DamageEnabled", true); + config.addDefault("Abilities.Water.WaterArms.Spear.Sphere", 2); + config.addDefault("Abilities.Water.WaterArms.Spear.Duration", 6000); + config.addDefault("Abilities.Water.WaterArms.Spear.Length", 18); + + config.addDefault("Abilities.Water.WaterArms.Spear.NightAugments.Range.Normal", 45); + config.addDefault("Abilities.Water.WaterArms.Spear.NightAugments.Range.FullMoon", 60); + config.addDefault("Abilities.Water.WaterArms.Spear.NightAugments.Sphere.Normal", 3); + config.addDefault("Abilities.Water.WaterArms.Spear.NightAugments.Sphere.FullMoon", 6); + config.addDefault("Abilities.Water.WaterArms.Spear.NightAugments.Duration.Normal", 7000); + config.addDefault("Abilities.Water.WaterArms.Spear.NightAugments.Duration.FullMoon", 12000); + + config.addDefault("Abilities.Water.WaterBubble.Enabled", true); + config.addDefault("Abilities.Water.WaterBubble.Description","To use, the bender must merely have the ability selected. All water around the user in a small bubble will vanish, replacing itself once the user either gets too far away or selects a different ability."); + config.addDefault("Abilities.Water.WaterBubble.Radius", 7); + + config.addDefault("Abilities.Water.WaterManipulation.Enabled", true); + config.addDefault("Abilities.Water.WaterManipulation.Description", "To use, place your cursor over a waterbendable object and tap sneak (default: shift). Smoke will appear where you've selected, indicating the origin of your ability. After you have selected an origin, simply left-click in any direction and you will see your water spout off in that direction, slicing any creature in its path. If you look towards a creature when you use this ability, it will target that creature. A collision from Water Manipulation both knocks the target back and deals some damage. Alternatively, if you have the source selected and tap shift again, you will be able to control the water more directly."); + config.addDefault("Abilities.Water.WaterManipulation.Damage", 3.0); + config.addDefault("Abilities.Water.WaterManipulation.Range", 20); + config.addDefault("Abilities.Water.WaterManipulation.Speed", 35); + config.addDefault("Abilities.Water.WaterManipulation.Push", 0.3); + config.addDefault("Abilities.Water.WaterManipulation.Cooldown", 1000); + + config.addDefault("Abilities.Water.WaterSpout.Enabled", true); + config.addDefault("Abilities.Water.WaterSpout.Description", "This ability provides a Waterbender with a means of transportation. To use, simply left click while in or over water to spout water up beneath you, experiencing controlled levitation. Left clicking again while the spout is active will cause it to disappear. Alternatively, tapping a Waterbendable block while not in Water will select a water block as a source, from there, you can tap sneak (Default:Shift) to channel the Water around you. Releasing the sneak will create a wave allowing you a quick burst of controlled transportation. While riding the wave you may press sneak to cause the wave to disappear."); + config.addDefault("Abilities.Water.WaterSpout.Height", 20); + config.addDefault("Abilities.Water.WaterSpout.Wave.Particles", false); + config.addDefault("Abilities.Water.WaterSpout.Wave.Enabled", true); + config.addDefault("Abilities.Water.WaterSpout.Wave.Range", 6); + config.addDefault("Abilities.Water.WaterSpout.Wave.ChargeTime", 1000); + config.addDefault("Abilities.Water.WaterSpout.Wave.FlightTime", 2000); + config.addDefault("Abilities.Water.WaterSpout.Wave.Speed", 1.2); + + config.addDefault("Abilities.Water.WaterCombo.Enabled", true); + config.addDefault("Abilities.Water.WaterCombo.IceWave.Damage", 3); + config.addDefault("Abilities.Water.WaterCombo.IceWave.Cooldown", 6000); + config.addDefault("Abilities.Water.WaterCombo.IceBullet.Damage", 1.5); + config.addDefault("Abilities.Water.WaterCombo.IceBullet.Radius", 2.5); + config.addDefault("Abilities.Water.WaterCombo.IceBullet.Range", 12); + config.addDefault("Abilities.Water.WaterCombo.IceBullet.MaxShots", 30); + config.addDefault("Abilities.Water.WaterCombo.IceBullet.AnimationSpeed", 1); + config.addDefault("Abilities.Water.WaterCombo.IceBullet.ShootTime", 5000); + config.addDefault("Abilities.Water.WaterCombo.IceBullet.Cooldown", 10000); + + config.addDefault("Abilities.Earth.Passive.Duration", 2500); + + config.addDefault("Abilities.Earth.Catapult.Enabled", true); + config.addDefault("Abilities.Earth.Catapult.Description", "To use, left-click while looking in the direction you want to be launched. " + + "A pillar of earth will jut up from under you and launch you in that direction - " + + "if and only if there is enough earth behind where you're looking to launch you. " + + "Skillful use of this ability takes much time and work, and it does result in the " + + "death of certain gung-ho earthbenders. If you plan to use this ability, be sure " + + "you've read about your passive ability you innately have as an earthbender."); + config.addDefault("Abilities.Earth.Catapult.Length", 7); + config.addDefault("Abilities.Earth.Catapult.Speed", 12); + config.addDefault("Abilities.Earth.Catapult.Push", 5); + + config.addDefault("Abilities.Earth.Collapse.Enabled", true); + config.addDefault("Abilities.Earth.Collapse.Description", " To use, simply left-click on an earthbendable block. " + + "That block and the earthbendable blocks above it will be shoved " + + "back into the earth below them, if they can. " + + "This ability does have the capacity to trap something inside of it, " + + "although it is incredibly difficult to do so. " + + "Additionally, press sneak with this ability to affect an area around your targetted location - " + + "all earth that can be moved downwards will be moved downwards. " + + "This ability is especially risky or deadly in caves, depending on the " + + "earthbender's goal and technique."); + config.addDefault("Abilities.Earth.Collapse.Range", 20); + config.addDefault("Abilities.Earth.Collapse.Radius", 7); + config.addDefault("Abilities.Earth.Collapse.Speed", 8); + + config.addDefault("Abilities.Earth.EarthArmor.Enabled", true); + config.addDefault("Abilities.Earth.EarthArmor.Description", "This ability encases the earthbender in temporary armor. To use, click on a block that is earthbendable. If there is another block under it that is earthbendable, the block will fly to you and grant you temporary armor and damage reduction. This ability has a long cooldown."); + config.addDefault("Abilities.Earth.EarthArmor.Duration", 10000); + config.addDefault("Abilities.Earth.EarthArmor.Strength", 2); + config.addDefault("Abilities.Earth.EarthArmor.Duration", 17500); + + config.addDefault("Abilities.Earth.EarthBlast.Enabled", true); + config.addDefault("Abilities.Earth.EarthBlast.Description", "To use, place your cursor over an earthbendable object (dirt, rock, ores, etc) " + + "and tap sneak (default: shift). The object will temporarily turn to stone, " + + "indicating that you have it focused as the source for your ability. " + + "After you have selected an origin (you no longer need to be sneaking), " + + "simply left-click in any direction and you will see your object launch " + + "off in that direction, smashing into any creature in its path. If you look " + + "towards a creature when you use this ability, it will target that creature. " + + "A collision from Earth Blast both knocks the target back and deals some damage. " + + "You cannot have multiple of these abilities flying at the same time."); + config.addDefault("Abilities.Earth.EarthBlast.CanHitSelf", false); + config.addDefault("Abilities.Earth.EarthBlast.PrepareRange", 7); + config.addDefault("Abilities.Earth.EarthBlast.Range", 20); + config.addDefault("Abilities.Earth.EarthBlast.Speed", 35); + config.addDefault("Abilities.Earth.EarthBlast.Revert", true); + config.addDefault("Abilities.Earth.Earthblast.Damage", 4); + config.addDefault("Abilities.Earth.EarthBlast.Push", 0.3); + + config.addDefault("Abilities.Earth.EarthGrab.Enabled", true); + config.addDefault("Abilities.Earth.EarthGrab.Description", "To use, simply left-click while targeting a creature within range. " + + "This ability will erect a circle of earth to trap the creature in."); + config.addDefault("Abilities.Earth.EarthGrab.Range", 15); + + config.addDefault("Abilities.Earth.EarthTunnel.Enabled", true); + config.addDefault("Abilities.Earth.EarthTunnel.Description", "Earth Tunnel is a completely utility ability for earthbenders. To use, simply sneak (default: shift) in the direction you want to tunnel. You will slowly begin tunneling in the direction you're facing for as long as you sneak or if the tunnel has been dug long enough. This ability will be interrupted if it hits a block that cannot be earthbent."); + config.addDefault("Abilities.Earth.EarthTunnel.MaxRadius", 1); + config.addDefault("Abilities.Earth.EarthTunnel.Range", 10); + config.addDefault("Abilities.Earth.EarthTunnel.Radius", 0.25); + config.addDefault("Abilities.Earth.EarthTunnel.Revert", true); + config.addDefault("Abilities.Earth.EarthTunnel.Interval", 30); + + config.addDefault("Abilities.Earth.Extraction.Enabled", true); + config.addDefault("Abilities.Earth.Extraction.Description", "This ability allows metalbenders to extract the minerals from ore blocks. To use, simply tap sneak while looking at an ore block with metal in it (iron, gold, quartz) and the ore will be extracted and drop in front of you. This ability has a small chance of doubling or tripling the loot. This ability has a short cooldown."); + config.addDefault("Abilities.Earth.Extraction.Cooldown", 10000); + config.addDefault("Abilities.Earth.Extraction.TripleLootChance", 15); + config.addDefault("Abilities.Earth.Extraction.DoubleLootChance", 40); + + config.addDefault("Abilities.Earth.LavaFlow.Enabled", true); + config.addDefault("Abilities.Earth.LavaFlow.Description", "This ability allows an Earthbender to create lava using the Earth around them. To use, simply hold sneak (Default: Shift) to create a lava moat that surrounds you, press sneak again to remove the moat. Left click an Earthbendable block to create a pool of lava after a small delay. Additionally, you can left click at any time to turn lava back into its original state -- Earth."); + config.addDefault("Abilities.Earth.LavaFlow.ShiftCooldown", 16000); + config.addDefault("Abilities.Earth.LavaFlow.ClickLavaCooldown", 10000); + config.addDefault("Abilities.Earth.LavaFlow.ClickLandCooldown", 500); + config.addDefault("Abilities.Earth.LavaFlow.ShiftCleanupDelay", 10000); + config.addDefault("Abilities.Earth.LavaFlow.ClickLavaCleanupDelay", 7000); + config.addDefault("Abilities.Earth.LavaFlow.ClickLandCleanupDelay", 20000); + config.addDefault("Abilities.Earth.LavaFlow.ClickRange", 10.0); + config.addDefault("Abilities.Earth.LavaFlow.ShiftRadius", 8.0); + config.addDefault("Abilities.Earth.LavaFlow.ShiftPlatformRadius", 1.5); + config.addDefault("Abilities.Earth.LavaFlow.ClickRadius", 5.0); + config.addDefault("Abilities.Earth.LavaFlow.ClickLavaCreateSpeed", 0.05); + config.addDefault("Abilities.Earth.LavaFlow.ClickLandCreateSpeed", 0.10); + config.addDefault("Abilities.Earth.LavaFlow.ShiftFlowSpeed", 0.1); + config.addDefault("Abilities.Earth.LavaFlow.ShiftRemoveSpeed", 3.0); + config.addDefault("Abilities.Earth.LavaFlow.ClickLavaStartDelay", 1500); + config.addDefault("Abilities.Earth.LavaFlow.ClickLandStartDelay", 0); + config.addDefault("Abilities.Earth.LavaFlow.UpwardFlow", 2); + config.addDefault("Abilities.Earth.LavaFlow.DownwardFlow", 4); + config.addDefault("Abilities.Earth.LavaFlow.AllowNaturalFlow", false); + config.addDefault("Abilities.Earth.LavaFlow.ParticleDensity", 0.33); + + config.addDefault("Abilities.Earth.EarthSmash.Enabled", true); + config.addDefault("Abilities.Earth.EarthSmash.Description", "To raise an EarthSmash hold sneak (default: shift) for approximately 1.5 seconds, " + + "then release while aiming at dirt. To grab the EarthSmash aim at the center and hold sneak, " + + "the EarthSmash will follow your mouse. You can shoot the EarthSmash by grabbing onto it and left clicking. " + + "To ride the EarthSmash simply hop ontop of it and hold sneak while aiming in the direction that you wish to go. " + + "Another way to ride an EarthSmash is to grab it with sneak and then right click it. " + + "Use EarthSmash as a defensive shield, a powerful attack, or an advanced means of transportation."); + config.addDefault("Abilities.Earth.EarthSmash.AllowGrab", true); + config.addDefault("Abilities.Earth.EarthSmash.AllowShooting", true); + config.addDefault("Abilities.Earth.EarthSmash.AllowFlight", true); + config.addDefault("Abilities.Earth.EarthSmash.GrabRange", 10); + config.addDefault("Abilities.Earth.EarthSmash.ChargeTime", 1200); + config.addDefault("Abilities.Earth.EarthSmash.Cooldown", 0); + config.addDefault("Abilities.Earth.EarthSmash.ShotRange", 30); + config.addDefault("Abilities.Earth.EarthSmash.Damage", 6); + config.addDefault("Abilities.Earth.EarthSmash.Knockback", 3.5); + config.addDefault("Abilities.Earth.EarthSmash.Knockup", 0.15); + config.addDefault("Abilities.Earth.EarthSmash.FlightSpeed", 0.72); + config.addDefault("Abilities.Earth.EarthSmash.FlightTimer", 3000); + config.addDefault("Abilities.Earth.EarthSmash.RemoveTimer", 30000); + +// config.addDefault("Abilities.Earth.LavaSurge.Enabled", true); +// config.addDefault("Abilities.Earth.LavaSurge.Description", "LavaSurge is a fundamental move for any Lavabender out there. To use, simply sneak (Default: Shift) while looking at a source of Earth or Lava, then click in a direction. A surge of lava will swiftly travel towards the target you were pointing at, dealing moderate damage, a large knockback, and setting them on fire."); +// config.addDefault("Abilities.Earth.LavaSurge.Damage", 4); +// config.addDefault("Abilities.Earth.LavaSurge.Cooldown", 1000); +// config.addDefault("Abilities.Earth.LavaSurge.FractureRadius", 1); +// config.addDefault("Abilities.Earth.LavaSurge.PrepareRange", 7); +// config.addDefault("Abilities.Earth.LavaSurge.TravelRange", 15); +// config.addDefault("Abilities.Earth.LavaSurge.MaxLavaWaves", 10); +// config.addDefault("Abilities.Earth.LavaSurge.SourceCanBeEarth", true); + + config.addDefault("Abilities.Earth.MetalClips.Enabled", true); + config.addDefault("Abilities.Earth.MetalClips.Description", "MetalClips has the potential to be both an offensive and a utility ability. To start, you must carry smelted Iron Ingots in your inventory. To apply the clips onto an entity, simply click at them. If the entity is a Zombie, a Skeleton, or a Player, the clips will form armor around the entity, giving you some control over them. Each additional clip will give you more control. If you have permission to do so, you may crush the entity against a wall with a 4th clip, hurting them. Without explicit permissions, you will only be able to strap three clips on your target. If the entity is not one of the above, the clip will simply do damage and fall to the ground, to be collected."); + config.addDefault("Abilities.Earth.MetalClips.Damage", 2); + config.addDefault("Abilities.Earth.MetalClips.DamageInterval", 500); + config.addDefault("Abilities.Earth.MetalClips.MagnetRange", 20); + config.addDefault("Abilities.Earth.MetalClips.MagnetPower", 0.6); + config.addDefault("Abilities.Earth.MetalClips.Cooldown", 1000); + config.addDefault("Abilities.Earth.MetalClips.Duration", 10000); + + + 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.Earth.Shockwave.Enabled", true); + config.addDefault("Abilities.Earth.Shockwave.Description", "This is one of the most powerful moves in the earthbender's arsenal. " + + "To use, you must first charge it by holding sneak (default: shift). " + + "Once charged, you can release sneak to create an enormous shockwave of earth, " + + "disturbing all earth around you and expanding radially outwards. " + + "Anything caught in the shockwave will be blasted back and dealt damage. " + + "If you instead click while charged, the disruption is focused in a cone in front of you. " + + "Lastly, if you fall from a great enough height with this ability selected, you will automatically create a shockwave."); + config.addDefault("Abilities.Earth.Shockwave.FallThreshold", 10); + config.addDefault("Abilities.Earth.Shockwave.ChargeTime", 2500); + config.addDefault("Abilities.Earth.Shockwave.Damage", 5); + config.addDefault("Abilities.Earth.Shockwave.Knockback", 1.1); + config.addDefault("Abilities.Earth.Shockwave.Range", 15); + + config.addDefault("Abilities.Earth.Tremorsense.Enabled", true); + config.addDefault("Abilities.Earth.Tremorsense.Description", "This is a pure utility ability for earthbenders. If you are in an area of low-light and are standing on top of an earthbendable block, this ability will automatically turn that block into glowstone, visible *only by you*. If you lose contact with a bendable block, the light will go out as you have lost contact with the earth and cannot 'see' until you can touch earth again. Additionally, if you click with this ability selected, smoke will appear above nearby earth with pockets of air beneath them."); + config.addDefault("Abilities.Earth.Tremorsense.MaxDepth", 10); + config.addDefault("Abilities.Earth.Tremorsense.Radius", 5); + config.addDefault("Abilities.Earth.Tremorsense.LightThreshold", 7); + config.addDefault("Abilities.Earth.Tremorsense.Cooldown", 1000); + + config.addDefault("Abilities.Fire.Blaze.Enabled", true); + config.addDefault("Abilities.Fire.Blaze.Description", "To use, simply left-click in any direction. An arc of fire will flow from your location, igniting anything in its path. Additionally, tap sneak to engulf the area around you in roaring flames."); + config.addDefault("Abilities.Fire.Blaze.ArcOfFire.Arc", 20); + config.addDefault("Abilities.Fire.Blaze.ArcOfFire.Range", 9); + config.addDefault("Abilities.Fire.Blaze.RingOfFire.Range", 7); + + config.addDefault("Abilities.Fire.Combustion.Enabled", true); + config.addDefault("Abilities.Fire.Combustion.Description", "Combustion is a powerful ability only known by a few skilled Firebenders. It allows the bender to Firebend with their mind, concentrating energy to create a powerful blast. To use, simply tap sneak (Default: Shift) to launch the blast. This technique is highly destructive and very effective, it also comes with a long cooldown."); + config.addDefault("Abilities.Fire.Combustion.Cooldown", 15000); + // config.addDefault("Abilities.Fire.Combustion.ChargeTime", 5000); + config.addDefault("Abilities.Fire.Combustion.BreakBlocks", false); + config.addDefault("Abilities.Fire.Combustion.Power", 1.0); + config.addDefault("Abilities.Fire.Combustion.Damage", 5); + config.addDefault("Abilities.Fire.Combustion.Radius", 4); + config.addDefault("Abilities.Fire.Combustion.Range", 20); + config.addDefault("Abilities.Fire.Combustion.Speed", 25); + + config.addDefault("Abilities.Fire.FireBlast.Enabled", true); + config.addDefault("Abilities.Fire.FireBlast.Description","FireBlast is the most fundamental bending technique of a firebender. " + + "To use, simply left-click in a direction. A blast of fire will be created at your fingertips. " + + "If this blast contacts an enemy, it will dissipate and engulf them in flames, " + + "doing additional damage and knocking them back slightly. " + + "If the blast hits terrain, it will ignite the nearby area. " + + "Additionally, if you hold sneak, you will charge up the fireblast. " + + "If you release it when it's charged, it will instead launch a powerful " + + "fireball that explodes on contact."); + config.addDefault("Abilities.Fire.FireBlast.Speed", 15); + config.addDefault("Abilities.Fire.FireBlast.Range", 15); + config.addDefault("Abilities.Fire.FireBlast.Radius", 2); + config.addDefault("Abilities.Fire.FireBlast.Push", 0.3); + config.addDefault("Abilities.Fire.FireBlast.Damage", 2); + config.addDefault("Abilities.Fire.FireBlast.Cooldown", 1500); + config.addDefault("Abilities.Fire.FireBlast.Dissipate", false); + config.addDefault("Abilities.Fire.FireBlast.Charged.ChargeTime", 2000); + config.addDefault("Abilities.Fire.FireBlast.Charged.Damage", 4); + config.addDefault("Abilities.Fire.FireBlast.Charged.DamageRadius", 6); + config.addDefault("Abilities.Fire.FireBlast.Charged.Power", 1); + config.addDefault("Abilities.Fire.FireBlast.Charged.Range", 20); + + config.addDefault("Abilities.Fire.FireBurst.Enabled", true); + config.addDefault("Abilities.Fire.FireBurst.Description", "FireBurst is a very powerful firebending ability. " + + "To use, press and hold sneak to charge your burst. " + + "Once charged, you can either release sneak to launch a cone-shaped burst " + + "of flames in front of you, or click to release the burst in a sphere around you. "); + config.addDefault("Abilities.Fire.FireBurst.Damage", 3); + config.addDefault("Abilities.Fire.FireBurst.ChargeTime", 2500); + config.addDefault("Abilities.Fire.FireBurst.Range", 15); + + 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 " + + "controlled flight for a short time. This ability can be used mid-air to prevent falling " + + "to your death, but on the ground it can only be used if standing on a block that's " + + "ignitable (e.g. not snow or water)."); + config.addDefault("Abilities.Fire.FireJet.Speed", 0.7); + config.addDefault("Abilities.Fire.FireJet.Duration", 1500); + config.addDefault("Abilities.Fire.FireJet.Cooldown", 6000); + config.addDefault("Abilities.Fire.FireJet.IsAvatarStateToggle", true); + + config.addDefault("Abilities.Fire.FireShield.Enabled", true); + config.addDefault("Abilities.Fire.FireShield.Description", "FireShield is a basic defensive ability. " + + "Clicking with this ability selected will create a " + + "small disc of fire in front of you, which will block most " + + "attacks and bending. Alternatively, pressing and holding " + + "sneak creates a very small shield of fire, blocking most attacks. " + + "Creatures that contact this fire are ignited."); + config.addDefault("Abilities.Fire.FireShield.Radius", 3); + config.addDefault("Abilities.Fire.FireShield.DiscRadius", 1.5); + config.addDefault("Abilities.Fire.FireShield.Duration", 1000); + + 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.Solidify.Range", 10); + config.addDefault("Abilities.Fire.HeatControl.Solidify.Radius", 5); + config.addDefault("Abilities.Fire.HeatControl.Solidify.RevertTime", 20000); + config.addDefault("Abilities.Fire.HeatControl.Melt.Range", 15); + config.addDefault("Abilities.Fire.HeatControl.Melt.Radius", 5); + + config.addDefault("Abilities.Fire.Illumination.Enabled", true); + config.addDefault("Abilities.Fire.Illumination.Description", "This ability gives firebenders a means of illuminating the area. It is a toggle - clicking " + + "will create a torch that follows you around. The torch will only appear on objects that are " + + "ignitable and can hold a torch (e.g. not leaves or ice). If you get too far away from the torch, " + + "it will disappear, but will reappear when you get on another ignitable block. Clicking again " + + "dismisses this torch."); + config.addDefault("Abilities.Fire.Illumination.Range", 5); + + config.addDefault("Abilities.Fire.Lightning.Enabled", true); + config.addDefault("Abilities.Fire.Lightning.Description", "Hold sneak while selecting this ability to charge up a lightning strike. Once charged, release sneak to discharge the lightning to the targeted location."); + config.addDefault("Abilities.Fire.Lightning.Damage", 6.0); + config.addDefault("Abilities.Fire.Lightning.Range", 13.0); + config.addDefault("Abilities.Fire.Lightning.ChargeTime", 3500); + config.addDefault("Abilities.Fire.Lightning.Cooldown", 0); + config.addDefault("Abilities.Fire.Lightning.StunChance", 0.20); + config.addDefault("Abilities.Fire.Lightning.StunDuration", 30.0); + config.addDefault("Abilities.Fire.Lightning.MaxArcAngle", 30); + config.addDefault("Abilities.Fire.Lightning.SubArcChance", 0.025); + config.addDefault("Abilities.Fire.Lightning.ChainArcRange", 6.0); + config.addDefault("Abilities.Fire.Lightning.ChainArcChance", 0.50); + config.addDefault("Abilities.Fire.Lightning.MaxChainArcs", 2); + config.addDefault("Abilities.Fire.Lightning.WaterArcs", 4); + config.addDefault("Abilities.Fire.Lightning.WaterArcRange", 12.0); + config.addDefault("Abilities.Fire.Lightning.SelfHitWater", true); + config.addDefault("Abilities.Fire.Lightning.SelfHitClose", true); + config.addDefault("Abilities.Fire.Lightning.ArcOnIce", false); + + + config.addDefault("Abilities.Fire.WallOfFire.Enabled", true); + config.addDefault("Abilities.Fire.WallOfFire.Description", "To use this ability, click at a location. A wall of fire will appear at this location, igniting enemies caught in it and blocking projectiles."); + config.addDefault("Abilities.Fire.WallOfFire.Range", 4); + config.addDefault("Abilities.Fire.WallOfFire.Height", 4); + config.addDefault("Abilities.Fire.WallOfFire.Width", 4); + config.addDefault("Abilities.Fire.WallOfFire.Duration", 5000); + config.addDefault("Abilities.Fire.WallOfFire.Damage", 2); + config.addDefault("Abilities.Fire.WallOfFire.Cooldown", 7500); + config.addDefault("Abilities.Fire.WallOfFire.Interval", 500); + + config.addDefault("Abilities.Fire.FireCombo.Enabled", true); + config.addDefault("Abilities.Fire.FireCombo.FireKick.Range", 7.0); + config.addDefault("Abilities.Fire.FireCombo.FireKick.Damage", 3.0); + config.addDefault("Abilities.Fire.FireCombo.FireKick.Cooldown", 2000); + config.addDefault("Abilities.Fire.FireCombo.FireSpin.Range", 7); + config.addDefault("Abilities.Fire.FireCombo.FireSpin.Damage", 3.0); + config.addDefault("Abilities.Fire.FireCombo.FireSpin.Knockback", 3.2); + config.addDefault("Abilities.Fire.FireCombo.FireSpin.Cooldown", 2000); + config.addDefault("Abilities.Fire.FireCombo.FireWheel.Range", 20.0); + config.addDefault("Abilities.Fire.FireCombo.FireWheel.Damage", 4.0); + config.addDefault("Abilities.Fire.FireCombo.FireWheel.Speed", 0.55); + config.addDefault("Abilities.Fire.FireCombo.FireWheel.Cooldown", 200); + config.addDefault("Abilities.Fire.FireCombo.JetBlast.Speed", 1.2); + config.addDefault("Abilities.Fire.FireCombo.JetBlast.Cooldown", 6000); + config.addDefault("Abilities.Fire.FireCombo.JetBlaze.Speed", 1.1); + config.addDefault("Abilities.Fire.FireCombo.JetBlaze.Damage", 3); + config.addDefault("Abilities.Fire.FireCombo.JetBlaze.Cooldown", 6000); + + config.addDefault("Abilities.Chi.Passive.FallReductionFactor", 0.5); + config.addDefault("Abilities.Chi.Passive.Speed", 1); + config.addDefault("Abilities.Chi.Passive.Jump", 2); + config.addDefault("Abilities.Chi.Passive.BlockChi.Duration", 2500); + config.addDefault("Abilities.Chi.Passive.DodgeChange", 25); + + config.addDefault("Abilities.Chi.AcrobatStance.Enabled", true); + config.addDefault("Abilities.Chi.AcrobatStance.Description", "AcrobatStance gives a Chiblocker a higher probability of blocking a Bender's Chi while granting them a Speed and Jump Boost. It also increases the rate at which the hunger bar depletes. To use, simply left click. Left clicking again will de-activate the stance."); + config.addDefault("Abilities.Chi.ChiBlockBoost", 0.1); + + config.addDefault("Abilities.Chi.HighJump.Enabled", true); + config.addDefault("Abilities.Chi.HighJump.Description", "To use this ability, simply click. You will jump quite high. This ability has a short cooldown."); + config.addDefault("Abilities.Chi.HighJump.Height", 1); + config.addDefault("Abilities.Chi.HighJump.Cooldown", 10000); + + config.addDefault("Abilities.Chi.Paralyze.Enabled", true); + config.addDefault("Abilities.Chi.Paralyze.Description", "Paralyzes the target, making them unable to do anything for a short " + + "period of time. This ability has a long cooldown."); + config.addDefault("Abilities.Chi.Paralyze.Cooldown", 15000); + config.addDefault("Abilities.Chi.Paralyze.Duration", 2000); + + config.addDefault("Abilities.Chi.RapidPunch.Enabled", true); + config.addDefault("Abilities.Chi.RapidPunch.Description", "This ability allows the chiblocker to punch rapidly in a short period. To use, simply punch. This has a short cooldown."); + config.addDefault("Abilities.Chi.RapidPunch.Damage", 1); + config.addDefault("Abilities.Chi.RapidPunch.Distance", 4); + config.addDefault("Abilities.Chi.RapidPunch.Cooldown", 15000); + config.addDefault("Abilities.Chi.RapidPunch.Punches", 4); + + config.addDefault("Abilities.Chi.Smokescreen.Enabled", true); + config.addDefault("Abilities.Chi.Smokescreen.Description", "Smokescren, if used correctly, can serve as a defensive and offensive ability for Chiblockers. To use, simply left click and you will toss out a Smoke Bomb. When the bomb hits the ground, it will explode and give all players within a small radius of the explosion temporary blindness, allowing you to either get away, or move in for the kill. This ability has a long cooldown."); + config.addDefault("Abilities.Chi.Smokescreen.Cooldown", 50000); + config.addDefault("Abilities.Chi.Smokescreen.Radius", 4); + config.addDefault("Abilities.Chi.Smokescreen.Duration", 15); + + config.addDefault("Abilities.Chi.WarriorStance.Enabled", true); + config.addDefault("Abilities.Chi.WarriorStance.Description", "WarriorStance gives a Chiblocker increased damage but makes them a tad more vulnerable. To activate, simply left click."); + config.addDefault("Abilities.Chi.WarriorStance.Strength", 1); + config.addDefault("Abilities.Chi.WarriorStance.Resistance", -1); + + config.addDefault("Abilities.Chi.QuickStrike.Enabled", true); + config.addDefault("Abilities.Chi.QuickStrike.Description", "QuickStrike enables a chiblocker to quickly strike an enemy, potentially blocking their chi."); + config.addDefault("Abilities.Chi.QuickStrike.Damage", 2); + config.addDefault("Abilities.Chi.QuickStrike.ChiBlockChance", 20); + + config.addDefault("Abilities.Chi.SwiftKick.Enabled", true); + config.addDefault("Abilities.Chi.SwiftKick.Description", "SwiftKick allows a chiblocker to swiftly kick an enemy, potentially blocking their chi. The chiblocker must be in the air to use this ability."); + config.addDefault("Abilities.Chi.SwiftKick.Damage", 4); + config.addDefault("Abilities.Chi.SwiftKick.ChiBlockChance", 30); + + config.addDefault("Abilities.Chi.ChiCombo.ParalyzeDuration", 10000); + + config.addDefault("Storage.engine", "sqlite"); + + config.addDefault("Storage.MySQL.host", "localhost"); + config.addDefault("Storage.MySQL.port", 3306); + config.addDefault("Storage.MySQL.pass", ""); + config.addDefault("Storage.MySQL.db", "minecraft"); + config.addDefault("Storage.MySQL.user", "root"); + + config.addDefault("debug", false); + config.options().copyDefaults(true); + plugin.saveConfig(); + } +} diff --git a/src/com/projectkorra/ProjectKorra/GeneralMethods.java b/src/com/projectkorra/ProjectKorra/GeneralMethods.java index 271ad2ac..7cb39250 100644 --- a/src/com/projectkorra/ProjectKorra/GeneralMethods.java +++ b/src/com/projectkorra/ProjectKorra/GeneralMethods.java @@ -115,7 +115,7 @@ public class GeneralMethods { static ProjectKorra plugin; private static FileConfiguration config = ProjectKorra.plugin.getConfig(); - + public static Random rand = new Random(); public static double CACHE_TIME = config.getDouble("Properties.RegionProtection.CacheBlockTime"); @@ -128,7 +128,7 @@ public class GeneralMethods { // Stands for toggled = false while logging out public static List toggedOut = new ArrayList(); - + /** * Checks to see if an AbilityExists. Uses method {@link #getAbility(String)} to check if it exists. * @param string Ability Name @@ -187,6 +187,12 @@ public class GeneralMethods { * @see {@link #bindAbility(Player, String)} */ public static void bindAbility(Player player, String ability, int slot) { + + if(MultiAbilityManager.playerAbilities.containsKey(player)){ + player.sendMessage(ChatColor.RED + "You can't edit your binds right now!"); + return; + } + BendingPlayer bPlayer = getBendingPlayer(player.getName()); bPlayer.getAbilities().put(slot, ability); if (AirMethods.isAirAbility(ability)) { @@ -229,7 +235,7 @@ public class GeneralMethods { if (ChiMethods.isChiAbility(ability) && !isBender(player, Element.Chi)) return false; return true; } - + /** * Checks to see if a Player can bend a specific Ability. * @param player The player name to check @@ -258,21 +264,21 @@ public class GeneralMethods { if (EarthMethods.isEarthAbility(ability) && !isBender(player, Element.Earth)) return false; if (FireMethods.isFireAbility(ability) && !isBender(player, Element.Fire)) return false; if (ChiMethods.isChiAbility(ability) && !isBender(player, Element.Chi)) return false; - -// if (isFlightAbility(ability) && !canAirFlight(plugin.getServer().getPlayer(player))) return false; -// if (isSpiritualProjectionAbility(ability) && !canUseSpiritualProjection(plugin.getServer().getPlayer(player))) return false; -// if (isCombustionbendingAbility(ability) && !canCombustionbend(plugin.getServer().getPlayer(player))) return false; -// if (isLightningbendingAbility(ability) && !canLightningbend(plugin.getServer().getPlayer(player))) return false; -// if (isSandbendingAbility(ability) && !canSandbend(plugin.getServer().getPlayer(player))) return false; -// if (isMetalbendingAbility(ability) && !canMetalbend(plugin.getServer().getPlayer(player))) return false; -// if (isLavabendingAbility(ability) && !canLavabend(plugin.getServer().getPlayer(player))) return false; -// if (isIcebendingAbility(ability) && !canIcebend(plugin.getServer().getPlayer(player))) return false; -// if (isHealingAbility(ability) && !canWaterHeal(plugin.getServer().getPlayer(player))) return false; -// if (isPlantbendingAbility(ability) && !canPlantbend(plugin.getServer().getPlayer(player))) return false; -// if (isBloodbendingAbility(ability) && !canBloodbend(plugin.getServer().getPlayer(player))) return false; - - - + + // if (isFlightAbility(ability) && !canAirFlight(plugin.getServer().getPlayer(player))) return false; + // if (isSpiritualProjectionAbility(ability) && !canUseSpiritualProjection(plugin.getServer().getPlayer(player))) return false; + // if (isCombustionbendingAbility(ability) && !canCombustionbend(plugin.getServer().getPlayer(player))) return false; + // if (isLightningbendingAbility(ability) && !canLightningbend(plugin.getServer().getPlayer(player))) return false; + // if (isSandbendingAbility(ability) && !canSandbend(plugin.getServer().getPlayer(player))) return false; + // if (isMetalbendingAbility(ability) && !canMetalbend(plugin.getServer().getPlayer(player))) return false; + // if (isLavabendingAbility(ability) && !canLavabend(plugin.getServer().getPlayer(player))) return false; + // if (isIcebendingAbility(ability) && !canIcebend(plugin.getServer().getPlayer(player))) return false; + // if (isHealingAbility(ability) && !canWaterHeal(plugin.getServer().getPlayer(player))) return false; + // if (isPlantbendingAbility(ability) && !canPlantbend(plugin.getServer().getPlayer(player))) return false; + // if (isBloodbendingAbility(ability) && !canBloodbend(plugin.getServer().getPlayer(player))) return false; + + + if (isRegionProtectedFromBuild(p, ability, p.getLocation())) return false; if (Paralyze.isParalyzed(p) || Bloodbending.isBloodbended(p)) return false; if (MetalClips.isControlled(p)) return false; @@ -313,66 +319,66 @@ public class GeneralMethods { } }.runTaskAsynchronously(ProjectKorra.plugin); } - + private static void createBendingPlayerAsynchronously(final UUID uuid, final String player) { - ResultSet rs2 = DBConnection.sql.readQuery("SELECT * FROM pk_players WHERE uuid = '" + uuid.toString() + "'"); - try { - if (!rs2.next()) { // Data doesn't exist, we want a completely new - // player. - new BendingPlayer(uuid, player, new ArrayList(), new HashMap(), false); - DBConnection.sql.modifyQuery("INSERT INTO pk_players (uuid, player) VALUES ('" + uuid.toString() + "', '" + player + "')"); - ProjectKorra.log.info("Created new BendingPlayer for " + player); - } else { - // The player has at least played before. - String player2 = rs2.getString("player"); - if (!player.equalsIgnoreCase(player2)) { - DBConnection.sql.modifyQuery("UPDATE pk_players SET player = '" + player + "' WHERE uuid = '" + uuid.toString() + "'"); - // They have changed names. - - ProjectKorra.log.info("Updating Player Name for " + player); - } - - String element = rs2.getString("element"); - String permaremoved = rs2.getString("permaremoved"); - boolean p = false; - final ArrayList elements = new ArrayList(); - if (element != null) { // Player has an element. - if (element.contains("a")) - elements.add(Element.Air); - if (element.contains("w")) - elements.add(Element.Water); - if (element.contains("e")) - elements.add(Element.Earth); - if (element.contains("f")) - elements.add(Element.Fire); - if (element.contains("c")) - elements.add(Element.Chi); - } - - final HashMap abilities = new HashMap(); - for (int i = 1; i <= 9; i++) { - String slot = rs2.getString("slot" + i); - - if (slot != null) { - abilities.put(i, slot); - } - } - - p = (permaremoved == null ? false : (permaremoved.equals("true") ? true : (permaremoved.equals("false") ? false : p))); - - final boolean boolean_p = p; - new BukkitRunnable() { - @Override - public void run() { - new BendingPlayer(uuid, player, elements, abilities, boolean_p); - } - }.runTask(ProjectKorra.plugin); - } - } catch (SQLException ex) { - ex.printStackTrace(); - GeneralMethods.logError(ex); - } - } + ResultSet rs2 = DBConnection.sql.readQuery("SELECT * FROM pk_players WHERE uuid = '" + uuid.toString() + "'"); + try { + if (!rs2.next()) { // Data doesn't exist, we want a completely new + // player. + new BendingPlayer(uuid, player, new ArrayList(), new HashMap(), false); + DBConnection.sql.modifyQuery("INSERT INTO pk_players (uuid, player) VALUES ('" + uuid.toString() + "', '" + player + "')"); + ProjectKorra.log.info("Created new BendingPlayer for " + player); + } else { + // The player has at least played before. + String player2 = rs2.getString("player"); + if (!player.equalsIgnoreCase(player2)) { + DBConnection.sql.modifyQuery("UPDATE pk_players SET player = '" + player + "' WHERE uuid = '" + uuid.toString() + "'"); + // They have changed names. + + ProjectKorra.log.info("Updating Player Name for " + player); + } + + String element = rs2.getString("element"); + String permaremoved = rs2.getString("permaremoved"); + boolean p = false; + final ArrayList elements = new ArrayList(); + if (element != null) { // Player has an element. + if (element.contains("a")) + elements.add(Element.Air); + if (element.contains("w")) + elements.add(Element.Water); + if (element.contains("e")) + elements.add(Element.Earth); + if (element.contains("f")) + elements.add(Element.Fire); + if (element.contains("c")) + elements.add(Element.Chi); + } + + final HashMap abilities = new HashMap(); + for (int i = 1; i <= 9; i++) { + String slot = rs2.getString("slot" + i); + + if (slot != null) { + abilities.put(i, slot); + } + } + + p = (permaremoved == null ? false : (permaremoved.equals("true") ? true : (permaremoved.equals("false") ? false : p))); + + final boolean boolean_p = p; + new BukkitRunnable() { + @Override + public void run() { + new BendingPlayer(uuid, player, elements, abilities, boolean_p); + } + }.runTask(ProjectKorra.plugin); + } + } catch (SQLException ex) { + ex.printStackTrace(); + GeneralMethods.logError(ex); + } + } /** * Damages an Entity by amount of damage specified. Starts a {@link EntityDamageByEntityEvent}. @@ -406,13 +412,13 @@ public class GeneralMethods { File writeFile = new File(".", "converted.yml"); if (readFile.exists()) { try ( - DataInputStream input = new DataInputStream(new FileInputStream(readFile)); - BufferedReader reader = new BufferedReader(new InputStreamReader(input)); + DataInputStream input = new DataInputStream(new FileInputStream(readFile)); + BufferedReader reader = new BufferedReader(new InputStreamReader(input)); + + DataOutputStream output = new DataOutputStream(new FileOutputStream(writeFile)); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output)); + ){ - DataOutputStream output = new DataOutputStream(new FileOutputStream(writeFile)); - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output)); - ){ - String line; while ((line = reader.readLine()) != null) { if (!line.trim().contains("==: BendingPlayer")) { @@ -486,7 +492,7 @@ public class GeneralMethods { if (AbilityModuleManager.subabilities.contains(ability)) return getSubBendingColor(Element.Fire); return FireMethods.getFireColor(); } - + else return getAvatarColor(); } @@ -585,7 +591,7 @@ public class GeneralMethods { return faces[besti]; } - + public static List getCircle(Location loc, int radius, int height, boolean hollow, boolean sphere, int plusY){ List circleblocks = new ArrayList(); int cx = loc.getBlockX(); @@ -711,22 +717,22 @@ public class GeneralMethods { return 4; } - + @SuppressWarnings("incomplete-switch") public static ChatColor getSubBendingColor(Element element) { switch(element) { - case Fire: - return ChatColor.valueOf(plugin.getConfig().getString("Properties.Chat.Colors.FireSub")); - case Air: - return ChatColor.valueOf(plugin.getConfig().getString("Properties.Chat.Colors.AirSub")); - case Water: - return ChatColor.valueOf(plugin.getConfig().getString("Properties.Chat.Colors.WaterSub")); - case Earth: - return ChatColor.valueOf(plugin.getConfig().getString("Properties.Chat.Colors.EarthSub")); + case Fire: + return ChatColor.valueOf(plugin.getConfig().getString("Properties.Chat.Colors.FireSub")); + case Air: + return ChatColor.valueOf(plugin.getConfig().getString("Properties.Chat.Colors.AirSub")); + case Water: + return ChatColor.valueOf(plugin.getConfig().getString("Properties.Chat.Colors.WaterSub")); + case Earth: + return ChatColor.valueOf(plugin.getConfig().getString("Properties.Chat.Colors.EarthSub")); } - + return getAvatarColor(); } @@ -866,7 +872,7 @@ public class GeneralMethods { if (player.hasPermission("bending.ability." + ability) && canBind(player.getName(), ability)) return true; return false; } - + public static boolean canView(Player player, String ability) { if (player.hasPermission("bending.ability." + ability)) return true; return false; @@ -878,7 +884,7 @@ public class GeneralMethods { if (AbilityModuleManager.authors.get(name).equalsIgnoreCase(author)) return true; return false; } - + public static boolean isAdjacentToThreeOrMoreSources(Block block) { if (TempBlock.isTempBlock(block)) return false; @@ -922,7 +928,7 @@ public class GeneralMethods { public static boolean isImportEnabled() { return plugin.getConfig().getBoolean("Properties.ImportEnabled"); } - + public static boolean isObstructed(Location location1, Location location2) { Vector loc1 = location1.toVector(); Vector loc2 = location2.toVector(); @@ -945,7 +951,7 @@ public class GeneralMethods { return false; } - + /* * isRegionProtectedFromBuild is one of the most server intensive methods in the * plugin. It uses a blockCache that keeps track of recent blocks that may have already been checked. @@ -955,12 +961,12 @@ public class GeneralMethods { public static boolean isRegionProtectedFromBuild(Player player, String ability, Location loc) { if(!blockProtectionCache.containsKey(player.getName())) blockProtectionCache.put(player.getName(), new ConcurrentHashMap()); - + ConcurrentHashMap blockMap = blockProtectionCache.get(player.getName()); Block block = loc.getBlock(); if(blockMap.containsKey(block)) { BlockCacheElement elem = blockMap.get(block); - + // both abilities must be equal to each other to use the cache if((ability == null && elem.getAbility() == null) || (ability != null && elem.getAbility() != null && elem.getAbility().equals(ability))) { @@ -972,7 +978,7 @@ public class GeneralMethods { blockMap.put(block, new BlockCacheElement(player, block, ability, value, System.currentTimeMillis())); return value; } - + public static boolean isRegionProtectedFromBuildPostCache(Player player, String ability, Location loc) { boolean allowharmless = plugin.getConfig().getBoolean("Properties.RegionProtection.AllowHarmlessAbilities"); @@ -1054,10 +1060,10 @@ public class GeneralMethods { return true; } -// if (ps.getForceFieldManager().hasSourceField(location, -// FieldFlag.PREVENT_PLACE)) -// return true; - + // if (ps.getForceFieldManager().hasSourceField(location, + // FieldFlag.PREVENT_PLACE)) + // return true; + if (!PreciousStones.API().canBreak(player, location)) { return true; } @@ -1150,7 +1156,7 @@ public class GeneralMethods { return false; } - + public static boolean isSolid(Block block) { if (Arrays.asList(nonOpaque).contains(block.getTypeId())) return false; return true; @@ -1182,12 +1188,12 @@ public class GeneralMethods { } return players; } - + public static void displayColoredParticle(Location loc, String hexVal) { int R = 0; int G = 0; int B = 0; - + if(hexVal.length() <= 6){ R = Integer.valueOf(hexVal.substring( 0, 2 ), 16); G = Integer.valueOf(hexVal.substring( 2, 4 ), 16); @@ -1201,15 +1207,15 @@ public class GeneralMethods { if(R <= 0) R=1; } - + ParticleEffect.RED_DUST.display((float) R, (float) G, (float) B, 0.004F, 0, loc, 256D); } - + public static void displayColoredParticle(Location loc, String hexVal, float xOffset, float yOffset, float zOffset) { int R = 0; int G = 0; int B = 0; - + if(hexVal.length() <= 6){ R = Integer.valueOf(hexVal.substring( 0, 2 ), 16); G = Integer.valueOf(hexVal.substring( 2, 4 ), 16); @@ -1223,19 +1229,19 @@ public class GeneralMethods { if(R <= 0) R=1; } - + loc.setX(loc.getX() + Math.random() * (xOffset/2 - -(xOffset/2))); loc.setY(loc.getY() + Math.random() * (yOffset/2 - -(yOffset/2))); loc.setZ(loc.getZ() + Math.random() * (zOffset/2 - -(zOffset/2))); - + ParticleEffect.RED_DUST.display((float) R, (float) G, (float) B, 0.004F, 0, loc, 256D); } - + public static void displayColoredParticle(Location loc, ParticleEffect type, String hexVal, float xOffset, float yOffset, float zOffset) { int R = 0; int G = 0; int B = 0; - + if(hexVal.length() <= 6){ R = Integer.valueOf(hexVal.substring( 0, 2 ), 16); G = Integer.valueOf(hexVal.substring( 2, 4 ), 16); @@ -1249,11 +1255,11 @@ public class GeneralMethods { if(R <= 0) R=1; } - + loc.setX(loc.getX() + Math.random() * (xOffset/2 - -(xOffset/2))); loc.setY(loc.getY() + Math.random() * (yOffset/2 - -(yOffset/2))); loc.setZ(loc.getZ() + Math.random() * (zOffset/2 - -(zOffset/2))); - + if(type == ParticleEffect.RED_DUST || type == ParticleEffect.REDSTONE) ParticleEffect.RED_DUST.display((float) R, (float) G, (float) B, 0.004F, 0, loc, 256D); else if(type == ParticleEffect.SPELL_MOB || type == ParticleEffect.MOB_SPELL) @@ -1263,7 +1269,7 @@ public class GeneralMethods { else ParticleEffect.RED_DUST.display((float) 0, (float) 0, (float) 0, 0.004F, 0, loc, 256D); } - + public static void displayParticleVector(Location loc, ParticleEffect type, float xTrans, float yTrans, float zTrans) { if(type == ParticleEffect.FIREWORKS_SPARK) ParticleEffect.FIREWORKS_SPARK.display((float) xTrans, (float) yTrans, (float) zTrans, 0.09F, 0, loc, 256D); @@ -1283,7 +1289,7 @@ public class GeneralMethods { ParticleEffect.SNOW_SHOVEL.display((float) xTrans, (float) yTrans, (float) zTrans, 0.2F, 0, loc, 256D); else ParticleEffect.RED_DUST.display((float) 0, (float) 0, (float) 0, 0.004F, 0, loc, 256D); - + } public static void reloadPlugin() { @@ -1301,7 +1307,7 @@ public class GeneralMethods { GeneralMethods.createBendingPlayer(player.getUniqueId(), player.getName()); } } - + public static void removeBlock(Block block) { if (isAdjacentToThreeOrMoreSources(block)) { block.setType(Material.WATER); @@ -1327,7 +1333,7 @@ public class GeneralMethods { } } - + public static Vector rotateVectorAroundVector(Vector axis, Vector rotator, double degrees) { double angle = Math.toRadians(degrees); @@ -1360,6 +1366,9 @@ public class GeneralMethods { if (bPlayer == null) return; String uuid = bPlayer.uuid.toString(); + //Temp code to block modifications of binds, Should be replaced when bind event is added. + if(MultiAbilityManager.playerAbilities.containsKey(Bukkit.getPlayer(bPlayer.getPlayerName()))) + return; HashMap abilities = bPlayer.getAbilities(); DBConnection.sql.modifyQuery("UPDATE pk_players SET slot" + slot + " = '" + (abilities.get(slot) == null ? null : abilities.get(slot)) + "' WHERE uuid = '" + uuid + "'"); @@ -1385,7 +1394,7 @@ public class GeneralMethods { ((ComboAbilityModule) c.getComboType()).stop(); AirMethods.stopBending(); - + EarthMethods.stopBending(); WaterMethods.stopBending(); @@ -1396,9 +1405,11 @@ public class GeneralMethods { Flight.removeAll(); TempBlock.removeAll(); + + MultiAbilityManager.removeAll(); } - + public static void setVelocity(Entity entity, Vector velocity){ if (entity instanceof TNTPrimed){ if (plugin.getConfig().getBoolean("Properties.BendingAffectFallingSand.TNT")) @@ -1421,24 +1432,24 @@ public class GeneralMethods { new FireMethods(plugin); new WaterMethods(plugin); } - + public static FallingBlock spawnFallingBlock(Location loc, int type) { return spawnFallingBlock(loc, type, (byte) 0); } - + public static FallingBlock spawnFallingBlock(Location loc, Material type) { return spawnFallingBlock(loc, type, (byte) 0); } - - + + public static FallingBlock spawnFallingBlock(Location loc, int type, byte data) { return loc.getWorld().spawnFallingBlock(loc, type, data); } - - + + public static FallingBlock spawnFallingBlock(Location loc, Material type, byte data) { return loc.getWorld().spawnFallingBlock(loc, type, data); @@ -1572,12 +1583,12 @@ public class GeneralMethods { } return null; } - + public static boolean hasItems() { if (Bukkit.getServer().getPluginManager().getPlugin("ProjectKorraItems") != null) return true; return false; } - + public static Plugin getItems() { if (hasItems()) { return Bukkit.getServer().getPluginManager().getPlugin("ProjectKorraItems"); @@ -1602,7 +1613,7 @@ public class GeneralMethods { pw.println(message); pw.flush(); pw.close(); - + } catch (IOException e) { e.printStackTrace(); } @@ -1705,14 +1716,14 @@ public class GeneralMethods { } } } - + public static class BlockCacheElement { private Player player; private Block block; private String ability; private boolean allowed; private long time; - + public BlockCacheElement(Player player, Block block, String ability, boolean allowed, long time) { this.player = player; this.block = block; @@ -1762,7 +1773,7 @@ public class GeneralMethods { } } - + public static void startCacheCleaner(final double period) { new BukkitRunnable() { public void run() { @@ -1770,7 +1781,7 @@ public class GeneralMethods { for(Iterator i = map.keySet().iterator(); i.hasNext();) { Block key = i.next(); BlockCacheElement value = map.get(key); - + if(System.currentTimeMillis() - value.getTime() > period) { map.remove(key); } @@ -1779,7 +1790,7 @@ public class GeneralMethods { } }.runTaskTimer(ProjectKorra.plugin, 0, (long) (period / 20)); } - + /** Checks if an entity is Undead **/ public static boolean isUndead(Entity entity) { if (entity == null) return false; @@ -1797,7 +1808,7 @@ public class GeneralMethods { } return false; } - + /** * Logs a throwable into an ERROR.log file in the ProjectKorra root folder. *

@@ -1809,7 +1820,7 @@ public class GeneralMethods { public static void logError(Throwable e) { logError(e, true); } - + /** * Logs a throwable into an ERROR.log file in the ProjectKorra root folder. *

@@ -1849,4 +1860,26 @@ public class GeneralMethods { } } } -} + + /** + * Returns a location with a specified distance away from the left side of a location. + * @param location + * @param distance + * @return + */ + public static Location getLeftSide(Location location, double distance){ + float angle = location.getYaw()/60; + return location.clone().add(new Vector(Math.cos(angle), 0, Math.sin(angle)).normalize().multiply(distance)); + } + + /** + * Returns a location with a specified distance away from the right side of a location. + * @param location + * @param distance + * @return + */ + public static Location getRightSide(Location location, double distance){ + float angle = location.getYaw()/60; + return location.clone().subtract(new Vector(Math.cos(angle), 0, Math.sin(angle)).normalize().multiply(distance)); + } +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/MultiAbilityManager.java b/src/com/projectkorra/ProjectKorra/MultiAbilityManager.java new file mode 100644 index 00000000..51102ebd --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/MultiAbilityManager.java @@ -0,0 +1,303 @@ +package com.projectkorra.ProjectKorra; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import com.projectkorra.ProjectKorra.Ability.MultiAbility.MultiAbilityModule; +import com.projectkorra.ProjectKorra.Ability.MultiAbility.MultiAbilityModuleManager; +import com.projectkorra.ProjectKorra.airbending.AirMethods; +import com.projectkorra.ProjectKorra.chiblocking.ChiMethods; +import com.projectkorra.ProjectKorra.earthbending.EarthMethods; +import com.projectkorra.ProjectKorra.firebending.FireMethods; +import com.projectkorra.ProjectKorra.waterbending.WaterMethods; + +public class MultiAbilityManager { + + public static ConcurrentHashMap> playerAbilities = new ConcurrentHashMap>(); + public static ConcurrentHashMap playerSlot = new ConcurrentHashMap(); + public static ConcurrentHashMap playerBoundAbility = new ConcurrentHashMap(); + public static ArrayList multiAbilityList = new ArrayList(); + + public MultiAbilityManager() { + ArrayList waterArms = new ArrayList(); + waterArms.add(new MultiAbilitySub("Pull", Element.Water, null)); + waterArms.add(new MultiAbilitySub("Punch", Element.Water, null)); + waterArms.add(new MultiAbilitySub("Grapple", Element.Water, null)); + waterArms.add(new MultiAbilitySub("Grab", Element.Water, null)); + waterArms.add(new MultiAbilitySub("Freeze", Element.Water, SubElement.Icebending)); + waterArms.add(new MultiAbilitySub("Spear", Element.Water, SubElement.Icebending)); + multiAbilityList.add(new MultiAbility("WaterArms", waterArms)); + manage(); + } + + /** + * MultiAbility class. + * Manages each MultiAbility's sub abilities. + * + */ + public static class MultiAbility { + private String name; + private ArrayList abilities; + + public MultiAbility(String name, ArrayList abilities){ + this.name = name; + this.abilities = abilities; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ArrayList getAbilities(){ + return abilities; + } + + public void setAbilities(ArrayList abilities){ + this.abilities = abilities; + } + } + + public static class MultiAbilitySub { + private String name; + private Element element; + private SubElement sub; + + public MultiAbilitySub(String name, Element element, SubElement sub){ + this.name = name; + this.element = element; + this.sub = sub; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Element getElement(){ + return element; + } + + public void setElement(Element element){ + this.element = element; + } + + public SubElement getSubElement(){ + return sub; + } + + public void setSubElement(SubElement sub){ + this.sub = sub; + } + + public ChatColor getAbilityColor(){ + if(sub == null){ + switch(element){ + case Air: + return AirMethods.getAirColor(); + case Water: + return WaterMethods.getWaterColor(); + case Fire: + return FireMethods.getFireColor(); + case Earth: + return EarthMethods.getEarthColor(); + case Chi: + return ChiMethods.getChiColor(); + default: + return GeneralMethods.getAvatarColor(); + + } + }else{ + return GeneralMethods.getSubBendingColor(element); + } + } + } + + /** + * Returns a MultiAbility based on name. + * @param multiAbility + * @return + */ + public static MultiAbility getMultiAbility(String multiAbility){ + for(MultiAbility ma: multiAbilityList){ + if(ma.getName().equalsIgnoreCase(multiAbility)) + return ma; + } + return null; + } + + /** + * Sets up a player's binds for a MultiAbility. + * @param player + * @param multiAbility + */ + public static void bindMultiAbility(Player player, String multiAbility){ + if(playerAbilities.containsKey(player)) + unbindMultiAbility(player); + playerSlot.put(player, player.getInventory().getHeldItemSlot()); + playerBoundAbility.put(player, multiAbility); + BendingPlayer bPlayer = GeneralMethods.getBendingPlayer(player.getName()); + HashMap currAbilities = new HashMap(); + for(int i : bPlayer.getAbilities().keySet()){ + currAbilities.put(i, bPlayer.getAbilities().get(i)); + } + playerAbilities.put(player, currAbilities); + + List modes = getMultiAbility(multiAbility).getAbilities(); + + bPlayer.getAbilities().clear(); + for(int i = 0; i < modes.size(); i++){ + if(!player.hasPermission("bending.ability." + multiAbility + "." + modes.get(i).getName())) + bPlayer.getAbilities().put(i+1, new StringBuilder().append(modes.get(i).getAbilityColor()).append(ChatColor.STRIKETHROUGH).append(modes.get(i).getName()).toString()); + else + bPlayer.getAbilities().put(i+1, modes.get(i).getAbilityColor() + modes.get(i).getName()); + } + + if(player.isOnline()){ + bPlayer.addCooldown("MAM_Setup", 1L); //Support for bending scoreboards. + player.getInventory().setHeldItemSlot(0); + } + } + + /** + * Reverts a player's binds to a previous state before use of a MultiAbility. + * @param player + */ + public static void unbindMultiAbility(Player player){ + if(playerAbilities.containsKey(player)){ + HashMap prevBinds = playerAbilities.get(player); + BendingPlayer bPlayer = GeneralMethods.getBendingPlayer(player.getName()); + int lastNonNull = -1; + for(int i = 1; i < 10; i++){ + if(prevBinds.get(i) != null) + lastNonNull = i; + bPlayer.getAbilities().put(i, prevBinds.get(i)); + } + if(lastNonNull > -1) + GeneralMethods.saveAbility(bPlayer, lastNonNull, prevBinds.get(lastNonNull)); + + if(player.isOnline()) + bPlayer.addCooldown("MAM_Setup", 1L); //Support for bending scoreboards. + playerAbilities.remove(player); + } + + if(playerSlot.containsKey(player)){ + if(player.isOnline()) + player.getInventory().setHeldItemSlot(playerSlot.get(player)); + playerSlot.remove(player); + }else{ + if(player.isOnline()) + player.getInventory().setHeldItemSlot(0); + } + + if(playerBoundAbility.containsKey(player)) + playerBoundAbility.remove(player); + } + + /** + * MultiAbility equivalent of GeneralMethods.getBoundAbility(). + * Returns a boolean based on whether a player has a specific MultiAbility active. + * @param player + * @param multiAbility + * @return + */ + public static boolean hasMultiAbilityBound(Player player, String multiAbility){ + if(playerAbilities.containsKey(player)){ + if(!playerBoundAbility.get(player).equals(multiAbility) && GeneralMethods.getBoundAbility(player) != null) + return false; + return true; + } + return false; + } + + /** + * Returns a boolean based on whether a player has a MultiAbility active. + * @param player + * @return + */ + public static boolean hasMultiAbilityBound(Player player){ + if(playerAbilities.containsKey(player)) + return true; + return false; + } + + /** + * Returns the MultiAbility the player has bound. + * Returns null if no multiability is bound and active. + * @param player + * @return + */ + public static String getBoundMultiAbility(Player player){ + if(playerBoundAbility.containsKey(player)) + return playerBoundAbility.get(player); + return null; + } + + public static void manage(){ + new BukkitRunnable() { + public void run() { + scrollHotBarSlots(); + } + }.runTaskTimer(ProjectKorra.plugin, 0, 1); + } + + /** + * Keeps track of the player's selected slot while a MultiAbility is active. + */ + public static void scrollHotBarSlots(){ + if(!playerAbilities.isEmpty()){ + for(Player player : playerAbilities.keySet()){ + if(playerBoundAbility.containsKey(player)){ + if(GeneralMethods.getBoundAbility(player) == null){ + if(multiAbilityList.contains(getMultiAbility(playerBoundAbility.get(player)))){ + if(player.getInventory().getHeldItemSlot() > getMultiAbility(playerBoundAbility.get(player)).getAbilities().size()){ + player.getInventory().setHeldItemSlot(getMultiAbility(playerBoundAbility.get(player)).getAbilities().size() - 1); + }else{ + player.getInventory().setHeldItemSlot(0); + } + } + } + } + } + } + } + + /** + * Clears all MultiAbility data for a player. + * Called on player quit event. + * @param player + */ + public static void remove(Player player){ + if(hasMultiAbilityBound(player)) + unbindMultiAbility(player); + + playerAbilities.remove(player); + playerBoundAbility.remove(player); + playerSlot.remove(player); + } + + /** + * Cleans up all MultiAbilities. + */ + public static void removeAll(){ + List abilities = MultiAbilityModuleManager.multiAbility; + for(MultiAbilityModule mam: abilities) + mam.stop(); + + playerAbilities.clear(); + playerSlot.clear(); + playerBoundAbility.clear(); + } +} diff --git a/src/com/projectkorra/ProjectKorra/PKListener.java b/src/com/projectkorra/ProjectKorra/PKListener.java index b1090ec4..5f3b2e82 100644 --- a/src/com/projectkorra/ProjectKorra/PKListener.java +++ b/src/com/projectkorra/ProjectKorra/PKListener.java @@ -132,6 +132,7 @@ import com.projectkorra.ProjectKorra.waterbending.IceSpike2; import com.projectkorra.ProjectKorra.waterbending.Melt; import com.projectkorra.ProjectKorra.waterbending.OctopusForm; import com.projectkorra.ProjectKorra.waterbending.Torrent; +import com.projectkorra.ProjectKorra.waterbending.WaterArms; import com.projectkorra.ProjectKorra.waterbending.WaterManipulation; import com.projectkorra.ProjectKorra.waterbending.WaterMethods; import com.projectkorra.ProjectKorra.waterbending.WaterPassive; @@ -404,6 +405,7 @@ public class PKListener implements Listener { } } + MultiAbilityManager.remove(player); FlightAbility.remove(event.getPlayer()); } @@ -440,6 +442,11 @@ public class PKListener implements Listener { BlockSource.update(player, ClickType.SHIFT_DOWN); } + if(!player.isSneaking() && WaterArms.hasPlayer(player)){ + WaterArms.displayBoundMsg(player); + return; + } + AirScooter.check(player); String abil = GeneralMethods.getBoundAbility(player); @@ -515,6 +522,10 @@ public class PKListener implements Listener { if (abil.equalsIgnoreCase("Torrent")) { Torrent.create(player); } + + if (abil.equalsIgnoreCase("WaterArms")) { + new WaterArms(player); + } } if (EarthMethods.isEarthAbility(abil)) { @@ -820,6 +831,7 @@ public class PKListener implements Listener { AirScooter.check(player); String abil = GeneralMethods.getBoundAbility(player); + if (abil == null && !MultiAbilityManager.hasMultiAbilityBound(player)) return; if (abil == null) return; if (GeneralMethods.canBend(player.getName(), abil)) { if (GeneralMethods.isDisabledStockAbility(abil)) @@ -1020,6 +1032,13 @@ public class PKListener implements Listener { if (abil.equalsIgnoreCase("AvatarState")) { new AvatarState(player); } + + if(MultiAbilityManager.hasMultiAbilityBound(player)){ + abil = MultiAbilityManager.getBoundMultiAbility(player); + if (abil.equalsIgnoreCase("WaterArms")) { + new WaterArms(player); + } + } } } diff --git a/src/com/projectkorra/ProjectKorra/ProjectKorra.java b/src/com/projectkorra/ProjectKorra/ProjectKorra.java index bf992d59..4fcef288 100644 --- a/src/com/projectkorra/ProjectKorra/ProjectKorra.java +++ b/src/com/projectkorra/ProjectKorra/ProjectKorra.java @@ -2,6 +2,7 @@ package com.projectkorra.ProjectKorra; import com.projectkorra.ProjectKorra.Ability.AbilityModuleManager; import com.projectkorra.ProjectKorra.Ability.Combo.ComboModuleManager; +import com.projectkorra.ProjectKorra.Ability.MultiAbility.MultiAbilityModuleManager; import com.projectkorra.ProjectKorra.Objects.Preset; import com.projectkorra.ProjectKorra.Utilities.CraftingRecipes; import com.projectkorra.ProjectKorra.airbending.AirbendingManager; @@ -33,6 +34,8 @@ public class ProjectKorra extends JavaPlugin { new GeneralMethods(this); new Commands(this); new AbilityModuleManager(this); + new MultiAbilityModuleManager(); + new MultiAbilityManager(); new ComboModuleManager(); new ComboManager(); new ChiComboManager(); @@ -87,4 +90,4 @@ public class ProjectKorra extends JavaPlugin { public void stopPlugin() { getServer().getPluginManager().disablePlugin(plugin); } -} +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/chiblocking/HighJump.java b/src/com/projectkorra/ProjectKorra/chiblocking/HighJump.java index 47af4f29..b93eafab 100644 --- a/src/com/projectkorra/ProjectKorra/chiblocking/HighJump.java +++ b/src/com/projectkorra/ProjectKorra/chiblocking/HighJump.java @@ -1,38 +1,45 @@ -package com.projectkorra.ProjectKorra.chiblocking; - -import org.bukkit.block.BlockFace; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; - -import com.projectkorra.ProjectKorra.BendingPlayer; -import com.projectkorra.ProjectKorra.GeneralMethods; -import com.projectkorra.ProjectKorra.ProjectKorra; - -public class HighJump { - - private int jumpheight = ProjectKorra.plugin.getConfig().getInt("Abilities.Chi.HighJump.Height"); - private long cooldown = ProjectKorra.plugin.getConfig().getInt("Abilities.Chi.HighJump.Cooldown"); - - public HighJump(Player p) { - BendingPlayer bPlayer = GeneralMethods.getBendingPlayer(p.getName()); - - if (bPlayer.isOnCooldown("HighJump")) return; - jump(p); - bPlayer.addCooldown("HighJump", cooldown); - - } - - private void jump(Player p) { - if (!GeneralMethods.isSolid(p.getLocation().getBlock() - .getRelative(BlockFace.DOWN))) - return; - Vector vec = p.getVelocity(); - vec.setY(jumpheight); - p.setVelocity(vec); - return; - } - - public static String getDescription() { - return "To use this ability, simply click. You will jump quite high. This ability has a short cooldown."; - } -} +package com.projectkorra.ProjectKorra.chiblocking; + +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.BendingPlayer; +import com.projectkorra.ProjectKorra.GeneralMethods; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.waterbending.WaterArmsWhip; + +public class HighJump { + + private int jumpheight = ProjectKorra.plugin.getConfig().getInt("Abilities.Chi.HighJump.Height"); + private long cooldown = ProjectKorra.plugin.getConfig().getInt("Abilities.Chi.HighJump.Cooldown"); + + public HighJump(Player p) { + BendingPlayer bPlayer = GeneralMethods.getBendingPlayer(p.getName()); + + if (bPlayer.isOnCooldown("HighJump")) return; + if (WaterArmsWhip.grabbedEntities.containsKey(p)) { + WaterArmsWhip waw = WaterArmsWhip.instances.get(WaterArmsWhip.grabbedEntities.get(p)); + if (waw != null) { + waw.setGrabbed(false); + } + } + jump(p); + bPlayer.addCooldown("HighJump", cooldown); + + } + + private void jump(Player p) { + if (!GeneralMethods.isSolid(p.getLocation().getBlock() + .getRelative(BlockFace.DOWN))) + return; + Vector vec = p.getVelocity(); + vec.setY(jumpheight); + p.setVelocity(vec); + return; + } + + public static String getDescription() { + return "To use this ability, simply click. You will jump quite high. This ability has a short cooldown."; + } +} diff --git a/src/com/projectkorra/ProjectKorra/waterbending/WaterArms.java b/src/com/projectkorra/ProjectKorra/waterbending/WaterArms.java new file mode 100644 index 00000000..f5106e9f --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/waterbending/WaterArms.java @@ -0,0 +1,665 @@ +package com.projectkorra.ProjectKorra.waterbending; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; + +import com.projectkorra.ProjectKorra.GeneralMethods; +import com.projectkorra.ProjectKorra.MultiAbilityManager; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.TempBlock; +import com.projectkorra.ProjectKorra.Utilities.ParticleEffect; +import com.projectkorra.ProjectKorra.earthbending.EarthMethods; +import com.projectkorra.ProjectKorra.firebending.FireMethods; +import com.projectkorra.ProjectKorra.firebending.Lightning; +import com.projectkorra.ProjectKorra.waterbending.WaterArmsWhip.Whip; + +public class WaterArms { + + /** + * Arm Enum value for deciding which arm is being used. + */ + public enum Arm { + Right, Left; + } + + private static FileConfiguration config = ProjectKorra.plugin.getConfig(); + + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + public static ConcurrentHashMap revert = new ConcurrentHashMap(); + + private static Integer[] unbreakable = { 7, 8, 9, 10, 11, 49, 54, 90, 119, + 120, 130, 146 }; + + private Player player; + private World world; + + private Arm activeArm = Arm.Right; + + private boolean cooldownLeft; + private boolean cooldownRight; + private boolean fullSource = true; + + private boolean leftArmConsumed = false; + private boolean rightArmConsumed = false; + + private int lengthReduction = 0; + + private int initLength = config + .getInt("Abilities.Water.WaterArms.Arms.InitialLength"); + private int sourceGrabRange = config + .getInt("Abilities.Water.WaterArms.Arms.SourceGrabRange"); + private int maxPunches = config + .getInt("Abilities.Water.WaterArms.Arms.MaxAttacks"); + private int maxIceBlasts = config + .getInt("Abilities.Water.WaterArms.Arms.MaxIceShots"); + private int maxUses = config + .getInt("Abilities.Water.WaterArms.Arms.MaxAlternateUsage"); + private long cooldown = config + .getLong("Abilities.Water.WaterArms.Arms.Cooldown"); + private boolean canUsePlantSource = config + .getBoolean("Abilities.Water.WaterArms.Arms.AllowPlantSource"); + + private boolean lightningEnabled = config + .getBoolean("Abilities.Water.WaterArms.Arms.Lightning.Enabled"); + private double lightningDamage = config + .getDouble("Abilities.Water.WaterArms.Arms.Lightning.Damage"); + private boolean lightningKill = config + .getBoolean("Abilities.Water.WaterArms.Arms.Lightning.KillUser"); + + private static String sneakMsg = config + .getString("Abilities.Water.WaterArms.SneakMessage"); + + private int selectedSlot = 0; + private int freezeSlot = 4; + + private long lastClickTime; + + public WaterArms(Player player) { + if (instances.containsKey(player)) { + if (player.isSneaking()) { + instances.get(player).prepareCancel(); + } else { + switch (player.getInventory().getHeldItemSlot()) { + case 0: + if (player.hasPermission("bending.ability.WaterArms.Pull")) { + new WaterArmsWhip(player, Whip.Pull); + } + break; + case 1: + if (player.hasPermission("bending.ability.WaterArms.Punch")) { + new WaterArmsWhip(player, Whip.Punch); + } + break; + case 2: + if (player + .hasPermission("bending.ability.WaterArms.Grapple")) { + new WaterArmsWhip(player, Whip.Grapple); + } + break; + case 3: + if (player.hasPermission("bending.ability.WaterArms.Grab")) { + new WaterArmsWhip(player, Whip.Grab); + } + break; + case 4: + if (player + .hasPermission("bending.ability.WaterArms.Freeze") + && WaterMethods.canIcebend(player)) { + new WaterArmsFreeze(player); + } + break; + case 5: + if (player.hasPermission("bending.ability.WaterArms.Spear")) { + if (WaterMethods.canIcebend(player)) { + new WaterArmsSpear(player, true); + } else { + new WaterArmsSpear(player, false); + } + } + break; + default: + break; + } + } + return; + } + this.player = player; + if (canUse(player) && prepare()) { + world = player.getWorld(); + instances.put(player, this); + MultiAbilityManager.bindMultiAbility(player, "WaterArms"); + if (ChatColor.stripColor(GeneralMethods.getBoundAbility(player)) == null) { + remove(); + return; + } + player.sendMessage(WaterMethods.getWaterColor() + sneakMsg + " " + + GeneralMethods.getBoundAbility(player)); + } + } + + private boolean canUse(Player player) { + if (GeneralMethods.getBoundAbility(player) == null) + return false; + if (!GeneralMethods.canBend(player.getName(), "WaterArms")) + return false; + if (GeneralMethods.isRegionProtectedFromBuild(player, "WaterArms", + player.getLocation())) + return false; + if (GeneralMethods.getBendingPlayer(player.getName()).isOnCooldown( + "WaterArms")) + return false; + if (GeneralMethods.getBoundAbility(player) + .equalsIgnoreCase("WaterArms")) + return true; + return false; + } + + private boolean prepare() { + Block sourceblock = WaterMethods.getWaterSourceBlock(player, + sourceGrabRange, canUsePlantSource); + if (sourceblock != null) { + if (WaterMethods.isPlant(sourceblock)) { + fullSource = false; + } + ParticleEffect.LARGE_SMOKE.display( + WaterMethods + .getWaterSourceBlock(player, sourceGrabRange, + canUsePlantSource).getLocation().clone() + .add(0.5, 0.5, 0.5), 0, 0, 0, 0F, 4); + return true; + } else if (WaterReturn.hasWaterBottle(player)) { + WaterReturn.emptyWaterBottle(player); + fullSource = false; + return true; + } + return false; + } + + private void progress() { + if (!instances.containsKey(player)) { + return; + } + if (player.isDead() || !player.isOnline() || world != player.getWorld()) { + remove(); + return; + } + if (!GeneralMethods.getBendingPlayer(player.getName()).isToggled()) { + remove(); + return; + } + if (!MultiAbilityManager.hasMultiAbilityBound(player, "WaterArms")) { + remove(); + return; + } + if (maxPunches == 0 || maxUses == 0 || maxIceBlasts == 0 + || (leftArmConsumed && rightArmConsumed)) { + remove(); + return; + } + + selectedSlot = player.getInventory().getHeldItemSlot(); + displayRightArm(); + displayLeftArm(); + + if (lightningEnabled) + checkIfZapped(); + } + + private boolean canPlaceBlock(Block block) { + if (!EarthMethods.isTransparentToEarthbending(player, block) + && !(WaterMethods.isWater(block) && TempBlock + .isTempBlock(block))) + return false; + return true; + } + + /** + * Displays the right arm. Returns false if the arm cannot be fully + * displayed. + * + * @return + */ + public boolean displayRightArm() { + if (rightArmConsumed) + return false; + + Location r1 = GeneralMethods.getRightSide(player.getLocation(), 1).add( + 0, 1.5, 0); + if (!canPlaceBlock(r1.getBlock())) + return false; + + if (!(getRightHandPos().getBlock().getLocation().equals(r1.getBlock() + .getLocation()))) { + new TempBlock(r1.getBlock(), Material.STATIONARY_WATER, (byte) 5); + revert.put(r1.getBlock(), 0L); + } + + Location r2 = GeneralMethods.getRightSide(player.getLocation(), 2).add( + 0, 1.5, 0); + if (!canPlaceBlock(r2.getBlock())) + return false; + + new TempBlock(r2.getBlock(), Material.STATIONARY_WATER, (byte) 0); + revert.put(r2.getBlock(), 0L); + + for (int j = 0; j <= initLength; j++) { + Location r3 = r2 + .clone() + .toVector() + .add(player.getLocation().clone().getDirection() + .multiply(j)).toLocation(player.getWorld()); + if (!canPlaceBlock(r3.getBlock())) { + if (selectedSlot == freezeSlot + && r3.getBlock().getType().equals(Material.ICE)) + continue; + return false; + } + + if (j >= 1 && selectedSlot == freezeSlot + && WaterMethods.canIcebend(player)) { + new TempBlock(r3.getBlock(), Material.ICE, (byte) 0); + revert.put(r3.getBlock(), 0L); + } else { + new TempBlock(r3.getBlock(), Material.STATIONARY_WATER, + (byte) 0); + revert.put(r3.getBlock(), 0L); + } + } + + return true; + } + + /** + * Displays the left arm. Returns false if the arm cannot be fully + * displayed. + * + * @return + */ + public boolean displayLeftArm() { + if (leftArmConsumed) + return false; + + Location l1 = GeneralMethods.getLeftSide(player.getLocation(), 1).add( + 0, 1.5, 0); + if (!canPlaceBlock(l1.getBlock())) + return false; + + if (!(getLeftHandPos().getBlock().getLocation().equals(l1.getBlock() + .getLocation()))) { + new TempBlock(l1.getBlock(), Material.STATIONARY_WATER, (byte) 5); + revert.put(l1.getBlock(), 0L); + } + + Location l2 = GeneralMethods.getLeftSide(player.getLocation(), 2).add( + 0, 1.5, 0); + if (!canPlaceBlock(l2.getBlock())) + return false; + + new TempBlock(l2.getBlock(), Material.STATIONARY_WATER, (byte) 0); + revert.put(l2.getBlock(), 0L); + + for (int j = 0; j <= initLength; j++) { + Location l3 = l2 + .clone() + .toVector() + .add(player.getLocation().clone().getDirection() + .multiply(j)).toLocation(player.getWorld()); + if (!canPlaceBlock(l3.getBlock())) { + if (selectedSlot == freezeSlot + && l3.getBlock().getType().equals(Material.ICE)) + continue; + return false; + } + + if (j >= 1 && selectedSlot == freezeSlot + && WaterMethods.canIcebend(player)) { + new TempBlock(l3.getBlock(), Material.ICE, (byte) 0); + revert.put(l3.getBlock(), 0L); + } else { + new TempBlock(l3.getBlock(), Material.STATIONARY_WATER, + (byte) 0); + revert.put(l3.getBlock(), 0L); + } + } + + return true; + } + + /** + * Calculate roughly where the player's right hand is. + * + * @return + */ + private Location getRightHandPos() { + return GeneralMethods.getRightSide(player.getLocation(), .34).add(0, + 1.5, 0); + } + + /** + * Calculate roughly where the player's left hand is. + * + * @return + */ + private Location getLeftHandPos() { + return GeneralMethods.getLeftSide(player.getLocation(), .34).add(0, + 1.5, 0); + } + + /** + * Returns the location of the tip of the right arm, assuming it is fully + * extended. Use the displayRightArm() check to see if it is fully extended. + * + * @return + */ + public Location getRightArmEnd() { + Location r1 = GeneralMethods.getRightSide(player.getLocation(), 2).add( + 0, 1.5, 0); + return r1.clone().add( + player.getLocation().getDirection().normalize() + .multiply(initLength)); + } + + /** + * Returns the location of the tip of the left arm assuming it is fully + * extended. Use the displayLeftArm() check to see if it is fully extended. + * + * @return + */ + public Location getLeftArmEnd() { + Location l1 = GeneralMethods.getLeftSide(player.getLocation(), 2).add( + 0, 1.5, 0); + return l1.clone().add( + player.getLocation().getDirection().normalize() + .multiply(initLength)); + } + + private static void progressRevert(boolean ignoreTime) { + for (Block block : revert.keySet()) { + long time = revert.get(block); + if (System.currentTimeMillis() > time || ignoreTime) { + if (TempBlock.isTempBlock(block)) + TempBlock.revertBlock(block, Material.AIR); + revert.remove(block); + } + } + } + + private void checkIfZapped() { + for (int i = 0; i < Lightning.instances.size(); i++) { + Lightning l = Lightning.instances.get(i); + for (Lightning.Arc arc : l.getArcs()) { + for (Block arm : revert.keySet()) { + for (Location loc : arc.getPoints()) { + if (arm.getLocation().getWorld() == loc.getWorld() + && loc.distance(arm.getLocation()) <= 2.5) { + for (Location l1 : getOffsetLocations(4, + arm.getLocation(), 1.25)) + FireMethods.playLightningbendingParticle(l1); + if (lightningKill) + GeneralMethods.damageEntity(Lightning.instances + .get(i).getPlayer(), player, 60D); + else + GeneralMethods.damageEntity(Lightning.instances + .get(i).getPlayer(), player, + lightningDamage); + } + } + } + } + } + } + + private static List getOffsetLocations(int amount, + Location location, double offset) { + List locations = new ArrayList(); + for (int i = 0; i < amount; i++) + locations.add(location.clone().add( + (float) (Math.random() * offset), + (float) (Math.random() * offset), + (float) (Math.random() * offset))); + return locations; + } + + public static void remove(Player player) { + if (instances.containsKey(player)) + instances.get(player).remove(); + } + + public void remove() { + MultiAbilityManager.unbindMultiAbility(player); + if (player.isOnline()) + GeneralMethods.getBendingPlayer(player.getName()).addCooldown( + "WaterArms", cooldown); + instances.remove(player); + } + + public void prepareCancel() { + if (System.currentTimeMillis() < lastClickTime + 500L) { + remove(); + } else { + lastClickTime = System.currentTimeMillis(); + } + } + + public static void progressAll() { + progressRevert(false); + for (Player p : instances.keySet()) + instances.get(p).progress(); + WaterArmsWhip.progressAll(); + WaterArmsFreeze.progressAll(); + WaterArmsSpear.progressAll(); + } + + public static void removeAll() { + progressRevert(true); + revert.clear(); + instances.clear(); + WaterArmsWhip.removeAll(); + WaterArmsFreeze.removeAll(); + WaterArmsSpear.removeAll(); + } + + @SuppressWarnings("deprecation") + public static boolean isUnbreakable(Block block) { + if (Arrays.asList(unbreakable).contains(block.getTypeId())) + return true; + return false; + } + + public static void displayBoundMsg(Player player){ + player.sendMessage(WaterMethods.getWaterColor() + sneakMsg + " " + + GeneralMethods.getBoundAbility(player)); + } + + public void displayBoundMsg(){ + player.sendMessage(WaterMethods.getWaterColor() + sneakMsg + " " + + GeneralMethods.getBoundAbility(player)); + } + + /** + * Returns the active arm of the player. + * + * @return + */ + public Arm getActiveArm() { + return activeArm; + } + + /** + * Switches the active arm of a player. + */ + public void switchActiveArm() { + if (activeArm.equals(Arm.Right)) + activeArm = Arm.Left; + else + activeArm = Arm.Right; + } + + /** + * Switches to the most suitable arm for the player. + * + * @return + */ + public Arm switchPreferredArm() { + switchActiveArm(); + if (activeArm.equals(Arm.Left)) { + if (!displayLeftArm()) { + switchActiveArm(); + } + } + if (activeArm.equals(Arm.Right)) { + if (!displayRightArm()) { + switchActiveArm(); + } + } + return getActiveArm(); + } + + public boolean canDisplayActiveArm() { + switch (activeArm) { + case Left: + return displayLeftArm(); + case Right: + return displayRightArm(); + default: + return false; + } + } + + public Location getActiveArmEnd() { + switch (activeArm) { + case Left: + return getLeftArmEnd(); + case Right: + return getRightArmEnd(); + default: + return null; + } + } + + public static boolean hasPlayer(Player player) { + if (instances.containsKey(player)) { + return true; + } + return false; + } + + public Player getPlayer() { + return player; + } + + public Boolean isFullSource() { + return fullSource; + } + + public boolean getLeftArmConsumed() { + return leftArmConsumed; + } + + public void setLeftArmConsumed(boolean consumed) { + this.leftArmConsumed = consumed; + } + + public boolean getRightArmConsumed() { + return rightArmConsumed; + } + + public void setRightArmConsumed(boolean consumed) { + this.rightArmConsumed = consumed; + } + + public Integer getLengthReduction() { + return lengthReduction; + } + + public void setLengthReduction(int lengthReduction) { + this.lengthReduction = lengthReduction; + } + + public Integer getMaxPunches() { + return maxPunches; + } + + public void setMaxPunches(int maxPunches) { + this.maxPunches = maxPunches; + } + + public Integer getMaxUses() { + return maxUses; + } + + public void setMaxUses(int maxUses) { + this.maxUses = maxUses; + } + + public Integer getMaxIceBlasts() { + return maxIceBlasts; + } + + public void setMaxIceBlasts(int maxIceBlasts) { + this.maxIceBlasts = maxIceBlasts; + } + + public boolean canLightningDamage() { + return lightningEnabled; + } + + public void setCanLightningDamage(boolean lightningEnabled) { + this.lightningEnabled = lightningEnabled; + } + + public double getLightningDamage() { + return lightningDamage; + } + + public void setLightningDamage(double lightningDamage) { + this.lightningDamage = lightningDamage; + } + + public boolean isLeftArmCooldown() { + return cooldownLeft; + } + + public void setLeftArmCooldown(boolean cooldown) { + this.cooldownLeft = cooldown; + } + + public boolean isRightArmCooldown() { + return cooldownRight; + } + + public void setRightArmCooldown(boolean cooldown) { + this.cooldownRight = cooldown; + } + + public void setActiveArmCooldown(boolean cooldown) { + switch (activeArm) { + case Left: + setLeftArmCooldown(cooldown); + return; + case Right: + setRightArmCooldown(cooldown); + return; + default: + break; + } + } + + public long getCooldown() { + return cooldown; + } + + public void setCooldown(long cooldown) { + this.cooldown = cooldown; + } +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/waterbending/WaterArmsFreeze.java b/src/com/projectkorra/ProjectKorra/waterbending/WaterArmsFreeze.java new file mode 100644 index 00000000..562d5345 --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/waterbending/WaterArmsFreeze.java @@ -0,0 +1,209 @@ +package com.projectkorra.ProjectKorra.waterbending; + +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.ArmorStand; +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.GeneralMethods; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.TempBlock; +import com.projectkorra.ProjectKorra.TempPotionEffect; +import com.projectkorra.ProjectKorra.Utilities.ParticleEffect; +import com.projectkorra.ProjectKorra.earthbending.EarthMethods; +import com.projectkorra.ProjectKorra.waterbending.WaterArms.Arm; + +public class WaterArmsFreeze { + + private static FileConfiguration config = ProjectKorra.plugin.getConfig(); + + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + + private Player player; + private WaterArms waterArms; + + private int iceRange = config + .getInt("Abilities.Water.WaterArms.Freeze.Range"); + private double iceDamage = config + .getInt("Abilities.Water.WaterArms.Freeze.Damage"); + + private boolean usageCooldownEnabled = config + .getBoolean("Abilities.Water.WaterArms.Arms.Cooldowns.UsageCooldownEnabled"); + private long usageCooldown = config + .getLong("Abilities.Water.WaterArms.Arms.Cooldowns.UsageCooldown"); + + private Location location; + private Vector direction; + private int distanceTravelled; + private Arm arm; + private boolean cancelled; + + private int id; + private static int ID = Integer.MIN_VALUE; + + public WaterArmsFreeze(Player player) { + this.player = player; + direction = player.getEyeLocation().getDirection(); + createInstance(); + } + + private void createInstance() { + if (WaterArms.instances.containsKey(player)) { + waterArms = WaterArms.instances.get(player); + waterArms.switchPreferredArm(); + arm = waterArms.getActiveArm(); + BendingPlayer bPlayer = GeneralMethods.getBendingPlayer(player + .getName()); + if (arm.equals(Arm.Left)) { + if (waterArms.isLeftArmCooldown() + || bPlayer.isOnCooldown("WaterArms_LEFT")) { + return; + } else { + if (usageCooldownEnabled) { + bPlayer.addCooldown("WaterArms_LEFT", usageCooldown); + } + waterArms.setLeftArmCooldown(true); + } + } + if (arm.equals(Arm.Right)) { + if (waterArms.isRightArmCooldown() + || bPlayer.isOnCooldown("WaterArms_RIGHT")) { + return; + } else { + if (usageCooldownEnabled) { + bPlayer.addCooldown("WaterArms_RIGHT", usageCooldown); + } + waterArms.setRightArmCooldown(true); + } + } + Vector dir = player.getLocation().getDirection(); + location = waterArms.getActiveArmEnd().add( + dir.normalize().multiply(1)); + direction = GeneralMethods.getDirection( + location, + GeneralMethods.getTargetedLocation(player, iceRange, + new Integer[] { 8, 9, 79, 174 })).normalize(); + } else { + return; + } + id = ID; + instances.put(id, this); + if (ID == Integer.MAX_VALUE) + ID = Integer.MIN_VALUE; + ID++; + } + + private void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (distanceTravelled > iceRange) { + remove(); + return; + } + if (distanceTravelled >= 5 && !cancelled) { + cancelled = true; + if (WaterArms.instances.containsKey(player)) { + if (arm.equals(Arm.Left)) { + waterArms.setLeftArmCooldown(false); + } else { + waterArms.setRightArmCooldown(false); + } + waterArms.setMaxIceBlasts(waterArms.getMaxIceBlasts() - 1); + } + } + if (!canPlaceBlock(location.getBlock())) { + remove(); + return; + } + progressIce(); + } + + private boolean canPlaceBlock(Block block) { + if (!EarthMethods.isTransparentToEarthbending(player, block) + && !((WaterMethods.isWater(block) || WaterMethods + .isIcebendable(block)) && TempBlock.isTempBlock(block))) { + return false; + } + if (GeneralMethods.isRegionProtectedFromBuild(player, "WaterArms", + block.getLocation())) { + return false; + } + return true; + } + + private void progressIce() { + ParticleEffect.SNOW_SHOVEL.display(location, (float) Math.random(), + (float) Math.random(), (float) Math.random(), (float) 0.05, 5); + new TempBlock(location.getBlock(), Material.ICE, (byte) 0); + WaterArms.revert.put(location.getBlock(), + System.currentTimeMillis() + 10L); + + for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, + 2.5)) { + if (entity instanceof LivingEntity + && entity.getEntityId() != player.getEntityId() + && !(entity instanceof ArmorStand)) { + GeneralMethods.damageEntity(player, entity, iceDamage); + PotionEffect effect = new PotionEffect(PotionEffectType.SLOW, + 40, 2); + new TempPotionEffect((LivingEntity) entity, effect); + remove(); + return; + } + } + + for (int i = 0; i < 2; i++) { + location = location.add(direction.clone().multiply(1)); + if (!canPlaceBlock(location.getBlock())) + return; + distanceTravelled++; + } + } + + private void remove() { + if (WaterArms.instances.containsKey(player)) { + if (!cancelled) { + if (arm.equals(Arm.Left)) { + waterArms.setLeftArmCooldown(false); + } else { + waterArms.setRightArmCooldown(false); + } + waterArms.setMaxIceBlasts(waterArms.getMaxIceBlasts() - 1); + } + } + instances.remove(id); + } + + public static void progressAll() { + for (int ID : instances.keySet()) + instances.get(ID).progress(); + } + + public static void removeAll() { + instances.clear(); + } + + public Player getPlayer() { + return player; + } + + public boolean getCancelled() { + return cancelled; + } + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/waterbending/WaterArmsSpear.java b/src/com/projectkorra/ProjectKorra/waterbending/WaterArmsSpear.java new file mode 100644 index 00000000..66874f7a --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/waterbending/WaterArmsSpear.java @@ -0,0 +1,321 @@ +package com.projectkorra.ProjectKorra.waterbending; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.BendingManager; +import com.projectkorra.ProjectKorra.BendingPlayer; +import com.projectkorra.ProjectKorra.GeneralMethods; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.TempBlock; +import com.projectkorra.ProjectKorra.earthbending.EarthMethods; +import com.projectkorra.ProjectKorra.waterbending.WaterArms.Arm; +import com.projectkorra.rpg.WorldEvents; + +public class WaterArmsSpear { + + private static FileConfiguration config = ProjectKorra.plugin.getConfig(); + + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + + private Player player; + private WaterArms waterArms; + + private List spearLocations = new ArrayList<>(); + + private int spearRange = config + .getInt("Abilities.Water.WaterArms.Spear.Range"); + private double spearDamage = config + .getDouble("Abilities.Water.WaterArms.Spear.Damage"); + private boolean spearDamageEnabled = config + .getBoolean("Abilities.Water.WaterArms.Spear.DamageEnabled"); + private int spearSphere = config + .getInt("Abilities.Water.WaterArms.Spear.Sphere"); + private long spearDuration = config + .getLong("Abilities.Water.WaterArms.Spear.Duration"); + private int spearLength = config + .getInt("Abilities.Water.WaterArms.Spear.Length"); + + private int spearRangeNight = config + .getInt("Abilities.Water.WaterArms.Spear.NightAugments.Range.Normal"); + private int spearRangeFullMoon = config + .getInt("Abilities.Water.WaterArms.Spear.NightAugments.Range.FullMoon"); + private int spearSphereNight = config + .getInt("Abilities.Water.WaterArms.Spear.NightAugments.Sphere.Normal"); + private int spearSphereFullMoon = config + .getInt("Abilities.Water.WaterArms.Spear.NightAugments.Sphere.FullMoon"); + private long spearDurationNight = config + .getLong("Abilities.Water.WaterArms.Spear.NightAugments.Duration.Normal"); + private long spearDurationFullMoon = config + .getLong("Abilities.Water.WaterArms.Spear.NightAugments.Duration.FullMoon"); + + private boolean usageCooldownEnabled = config + .getBoolean("Abilities.Water.WaterArms.Arms.Cooldowns.UsageCooldownEnabled"); + private long usageCooldown = config + .getLong("Abilities.Water.WaterArms.Arms.Cooldowns.UsageCooldown"); + + private Location location; + private Location initLocation; + private int distanceTravelled; + private Arm arm; + private int layer; + private boolean hitEntity; + private boolean canFreeze; + + private int id; + private static int ID = Integer.MIN_VALUE; + + Random rand = new Random(); + + public WaterArmsSpear(Player player, boolean freeze) { + this.player = player; + this.canFreeze = freeze; + getNightAugments(); + createInstance(); + } + + private void getNightAugments() { + World world = player.getWorld(); + if (WaterMethods.isNight(world)) { + if (GeneralMethods.hasRPG()) { + if (BendingManager.events.get(world).equalsIgnoreCase( + WorldEvents.LunarEclipse.toString())) { + spearRange = spearRangeFullMoon; + spearSphere = spearSphereFullMoon; + spearDuration = spearDurationFullMoon; + } else if (BendingManager.events.get(world).equalsIgnoreCase( + "FullMoon")) { + spearRange = spearRangeFullMoon; + spearSphere = spearSphereFullMoon; + spearDuration = spearDurationFullMoon; + } else { + spearRange = spearRangeNight; + spearSphere = spearSphereNight; + spearDuration = spearDurationNight; + } + } else { + if (WaterMethods.isFullMoon(world)) { + spearRange = spearRangeFullMoon; + spearSphere = spearSphereFullMoon; + spearDuration = spearDurationFullMoon; + } else { + spearRange = spearRangeNight; + spearSphere = spearSphereNight; + spearDuration = spearDurationNight; + } + } + } + } + + private void createInstance() { + if (WaterArms.instances.containsKey(player)) { + waterArms = WaterArms.instances.get(player); + waterArms.switchPreferredArm(); + arm = waterArms.getActiveArm(); + BendingPlayer bPlayer = GeneralMethods.getBendingPlayer(player + .getName()); + if (arm.equals(Arm.Left)) { + if (waterArms.isLeftArmCooldown() + || bPlayer.isOnCooldown("WaterArms_LEFT") + || !waterArms.displayLeftArm()) { + return; + } else { + if (usageCooldownEnabled) { + bPlayer.addCooldown("WaterArms_LEFT", usageCooldown); + } + waterArms.setLeftArmConsumed(true); + waterArms.setLeftArmCooldown(true); + } + } + if (arm.equals(Arm.Right)) { + if (waterArms.isRightArmCooldown() + || bPlayer.isOnCooldown("WaterArms_RIGHT") + || !waterArms.displayRightArm()) { + return; + } else { + if (usageCooldownEnabled) { + bPlayer.addCooldown("WaterArms_RIGHT", usageCooldown); + } + waterArms.setRightArmConsumed(true); + waterArms.setRightArmCooldown(true); + } + } + Vector dir = player.getLocation().getDirection(); + location = waterArms.getActiveArmEnd().add( + dir.normalize().multiply(1)); + initLocation = location.clone(); + } else { + return; + } + id = ID; + instances.put(id, this); + if (ID == Integer.MAX_VALUE) + ID = Integer.MIN_VALUE; + ID++; + } + + private void progress() { + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (distanceTravelled > spearRange) { + remove(); + return; + } + if (!hitEntity) { + progressSpear(); + } else { + createIceBall(); + } + if (layer >= spearSphere) { + remove(); + return; + } + if (!canPlaceBlock(location.getBlock())) { + if (canFreeze) { + createSpear(); + } + remove(); + return; + } + } + + private void progressSpear() { + for (int i = 0; i < 2; i++) { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint( + location, 2)) { + if (entity instanceof LivingEntity + && entity.getEntityId() != player.getEntityId() + && !(entity instanceof ArmorStand)) { + hitEntity = true; + location = entity.getLocation(); + + if (spearDamageEnabled) { + GeneralMethods + .damageEntity(player, entity, spearDamage); + } + + return; + } + } + new TempBlock(location.getBlock(), Material.STATIONARY_WATER, + (byte) 0); + WaterArms.revert.put(location.getBlock(), + System.currentTimeMillis() + 600L); + Vector direction = GeneralMethods.getDirection( + initLocation, + GeneralMethods.getTargetedLocation(player, spearRange, + new Integer[] { 8, 9, 79, 174 })).normalize(); + location = location.add(direction.clone().multiply(1)); + spearLocations.add(location.clone()); + if (!canPlaceBlock(location.getBlock())) { + return; + } + distanceTravelled++; + } + } + + private void createSpear() { + for (int i = spearLocations.size() - spearLength; i < spearLocations + .size(); i++) { + if (i >= 0) { + Block block = spearLocations.get(i).getBlock(); + if (canPlaceBlock(block)) { + WaterMethods.playIcebendingSound(block.getLocation()); + if (WaterArms.revert.containsKey(block)) { + WaterArms.revert.remove(block); + } + new TempBlock(block, Material.ICE, (byte) 0); + WaterArms.revert.put(block, System.currentTimeMillis() + + spearDuration + (long) (Math.random() * 500)); + } + } + } + } + + private void createIceBall() { + layer++; + for (Block block : GeneralMethods.getBlocksAroundPoint(location, layer)) { + if (EarthMethods.isTransparentToEarthbending(player, block) + && block.getType() != Material.ICE + && !WaterArms.isUnbreakable(block)) { + WaterMethods.playIcebendingSound(block.getLocation()); + new TempBlock(block, Material.ICE, (byte) 0); + WaterArms.revert.put(block, System.currentTimeMillis() + + spearDuration + (long) (Math.random() * 500)); + } + } + } + + private boolean canPlaceBlock(Block block) { + if (!EarthMethods.isTransparentToEarthbending(player, block) + && !((WaterMethods.isWater(block) || WaterMethods + .isIcebendable(block)) && (TempBlock.isTempBlock(block) && !WaterArms.revert + .containsKey(block)))) { + return false; + } + if (GeneralMethods.isRegionProtectedFromBuild(player, "WaterArms", + block.getLocation())) { + return false; + } + if (WaterArms.isUnbreakable(block) && !WaterMethods.isWater(block)) { + return false; + } + return true; + } + + private void remove() { + if (WaterArms.instances.containsKey(player)) { + if (arm.equals(Arm.Left)) { + waterArms.setLeftArmCooldown(false); + } else { + waterArms.setRightArmCooldown(false); + } + waterArms.setMaxUses(waterArms.getMaxUses() - 1); + } + instances.remove(id); + } + + public static void progressAll() { + for (int ID : instances.keySet()) + instances.get(ID).progress(); + } + + public static void removeAll() { + instances.clear(); + } + + public Player getPlayer() { + return player; + } + + public boolean getCanFreeze() { + return canFreeze; + } + + public void setCanFreeze(boolean freeze) { + this.canFreeze = freeze; + } + + public boolean getHasHitEntity() { + return hitEntity; + } + + public void setHitEntity(boolean hit) { + this.hitEntity = hit; + } +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/waterbending/WaterArmsWhip.java b/src/com/projectkorra/ProjectKorra/waterbending/WaterArmsWhip.java new file mode 100644 index 00000000..9e293efa --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/waterbending/WaterArmsWhip.java @@ -0,0 +1,479 @@ +package com.projectkorra.ProjectKorra.waterbending; + +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Creature; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.BendingManager; +import com.projectkorra.ProjectKorra.BendingPlayer; +import com.projectkorra.ProjectKorra.Commands; +import com.projectkorra.ProjectKorra.GeneralMethods; +import com.projectkorra.ProjectKorra.MultiAbilityManager; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.TempBlock; +import com.projectkorra.ProjectKorra.earthbending.EarthMethods; +import com.projectkorra.ProjectKorra.waterbending.WaterArms.Arm; +import com.projectkorra.rpg.WorldEvents; + +public class WaterArmsWhip { + + /** + * Whip Enum value for deciding what ability should be executed. + */ + public enum Whip { + Pull, Punch, Grapple, Grab; + } + + private static FileConfiguration config = ProjectKorra.plugin.getConfig(); + + public static ConcurrentHashMap instances = new ConcurrentHashMap(); + public static HashMap grabbedEntities = new HashMap(); + + private Player player; + private WaterArms waterArms; + + private int whipLength = config + .getInt("Abilities.Water.WaterArms.Whip.MaxLength"); + private int whipLengthWeak = config + .getInt("Abilities.Water.WaterArms.Whip.MaxLengthWeak"); + + private int whipLengthNight = config + .getInt("Abilities.Water.WaterArms.Whip.NightAugments.MaxLength.Normal"); + private int whipLengthFullMoon = config + .getInt("Abilities.Water.WaterArms.Whip.NightAugments.MaxLength.FullMoon"); + + private int initLength = config + .getInt("Abilities.Water.WaterArms.Arms.InitialLength"); + private double punchDamage = config + .getDouble("Abilities.Water.WaterArms.Whip.Punch.PunchDamage"); + private boolean grappleRespectRegions = config + .getBoolean("Abilities.Water.WaterArms.Whip.Grapple.RespectRegions"); + private long holdTime = config + .getLong("Abilities.Water.WaterArms.Whip.Grab.HoldTime"); + private boolean usageCooldownEnabled = config + .getBoolean("Abilities.Water.WaterArms.Arms.Cooldowns.UsageCooldownEnabled"); + private long usageCooldown = config + .getLong("Abilities.Water.WaterArms.Arms.Cooldowns.UsageCooldown"); + + private int activeLength = initLength; + private int whipSpeed = 2; + private boolean reverting = false; + private boolean hasDamaged = false; + private boolean grappled = false; + private boolean grabbed = false; + private double playerHealth; + private long time; + + private LivingEntity grabbedEntity; + private Location end; + private Arm arm; + private Whip ability; + + private int id; + private static int ID = Integer.MIN_VALUE; + + public WaterArmsWhip(Player player, Whip ability) { + if (instances.containsKey(getId(player))) { + WaterArmsWhip waw = instances.get(getId(player)); + if (waw.grabbed) { + waw.grabbed = false; + if (waw.grabbedEntity != null) { + grabbedEntities.remove(waw.grabbedEntity); + waw.grabbedEntity.setVelocity(waw.grabbedEntity + .getVelocity().multiply(2.5)); + } + return; + } + if (!waw.arm.equals(WaterArms.instances.get(player).getActiveArm())) { + return; + } + } + this.player = player; + this.ability = ability; + getNightAugments(); + createInstance(); + } + + private void getNightAugments() { + World world = player.getWorld(); + if (WaterMethods.isNight(world)) { + if (GeneralMethods.hasRPG()) { + if (BendingManager.events.get(world).equalsIgnoreCase( + WorldEvents.LunarEclipse.toString())) { + whipLength = whipLengthFullMoon; + } else if (BendingManager.events.get(world).equalsIgnoreCase( + "FullMoon")) { + whipLength = whipLengthFullMoon; + } else { + whipLength = whipLengthNight; + } + } else { + if (WaterMethods.isFullMoon(world)) { + whipLength = whipLengthFullMoon; + } else { + whipLength = whipLengthNight; + } + } + } + } + + private void createInstance() { + if (WaterArms.instances.containsKey(player)) { + waterArms = WaterArms.instances.get(player); + waterArms.switchPreferredArm(); + arm = waterArms.getActiveArm(); + time = System.currentTimeMillis() + holdTime; + playerHealth = player.getHealth(); + BendingPlayer bPlayer = GeneralMethods.getBendingPlayer(player + .getName()); + if (arm.equals(Arm.Left)) { + if (waterArms.isLeftArmCooldown() + || bPlayer.isOnCooldown("WaterArms_LEFT")) { + return; + } else { + if (usageCooldownEnabled) { + bPlayer.addCooldown("WaterArms_LEFT", usageCooldown); + } + waterArms.setLeftArmCooldown(true); + } + } + if (arm.equals(Arm.Right)) { + if (waterArms.isRightArmCooldown() + || bPlayer.isOnCooldown("WaterArms_RIGHT")) { + return; + } else { + if (usageCooldownEnabled) { + bPlayer.addCooldown("WaterArms_RIGHT", usageCooldown); + } + waterArms.setRightArmCooldown(true); + } + } + } else { + return; + } + if (!waterArms.isFullSource()) { + whipLength = whipLengthWeak; + } + id = ID; + instances.put(id, this); + if (ID == Integer.MAX_VALUE) + ID = Integer.MIN_VALUE; + ID++; + } + + private void progress() { + if (!WaterArms.instances.containsKey(player)) { + remove(); + return; + } + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + if (!MultiAbilityManager.hasMultiAbilityBound(player, "WaterArms")) { + remove(); + return; + } + + if (activeLength < whipLength && !reverting) { + activeLength += whipSpeed; + } else if (activeLength > initLength) { + if (!grabbed) { + activeLength -= whipSpeed; + } + } else { + remove(); + return; + } + + if (activeLength == whipLength && !grabbed) { + reverting = true; + } + + if (grabbed + && (System.currentTimeMillis() > time || playerHealth > player + .getHealth())) { + grabbed = false; + reverting = true; + } + + useArm(); + dragEntity(end); + grapplePlayer(end); + } + + private boolean canPlaceBlock(Block block) { + if (!EarthMethods.isTransparentToEarthbending(player, block) + && !(WaterMethods.isWater(block) && TempBlock + .isTempBlock(block))) { + return false; + } + if (GeneralMethods.isRegionProtectedFromBuild(player, "WaterArms", + block.getLocation())) { + return false; + } + return true; + } + + private void useArm() { + if (waterArms.canDisplayActiveArm()) { + Location l1 = null; + if (arm.equals(Arm.Left)) { + l1 = waterArms.getLeftArmEnd().clone(); + } else { + l1 = waterArms.getRightArmEnd().clone(); + } + Vector dir = player.getLocation().getDirection(); + for (int i = 1; i <= activeLength; i++) { + Location l2 = l1.clone().add(dir.normalize().multiply(i)); + + if (!canPlaceBlock(l2.getBlock())) { + if (!l2.getBlock().getType().equals(Material.BARRIER)) { + grappled = true; + } + reverting = true; + break; + } + + new TempBlock(l2.getBlock(), Material.STATIONARY_WATER, + (byte) 0); + WaterArms.revert.put(l2.getBlock(), 0L); + + if (i == activeLength) { + Location l3 = null; + if (arm.equals(Arm.Left)) { + l3 = GeneralMethods.getRightSide(l2, 1); + } else { + l3 = GeneralMethods.getLeftSide(l2, 1); + } + end = l3.clone(); + if (canPlaceBlock(l3.getBlock())) { + new TempBlock(l3.getBlock(), Material.STATIONARY_WATER, + (byte) 3); + WaterArms.revert.put(l3.getBlock(), 0L); + performAction(l3); + } else { + if (!l3.getBlock().getType().equals(Material.BARRIER)) { + grappled = true; + } + reverting = true; + } + } + } + } + } + + private void performAction(Location location) { + Location endOfArm = waterArms.getLeftArmEnd().clone(); + switch (ability) { + case Pull: + for (Entity entity : GeneralMethods.getEntitiesAroundPoint( + location, 2)) { + if (entity instanceof Player + && Commands.invincible.contains(((Player) entity) + .getName())) { + continue; + } + Vector vector = endOfArm.toVector().subtract( + entity.getLocation().toVector()); + entity.setVelocity(vector.multiply(0.15)); + } + break; + case Punch: + for (Entity entity : GeneralMethods.getEntitiesAroundPoint( + location, 2)) { + if (entity instanceof Player + && Commands.invincible.contains(((Player) entity) + .getName())) { + continue; + } + Vector vector = entity.getLocation().toVector() + .subtract(endOfArm.toVector()); + entity.setVelocity(vector.multiply(0.15)); + if (entity instanceof LivingEntity) { + if (entity.getEntityId() != player.getEntityId()) { + hasDamaged = true; + GeneralMethods + .damageEntity(player, entity, punchDamage); + } + } + } + break; + case Grapple: + grapplePlayer(end); + break; + case Grab: + if (grabbedEntity == null) { + for (Entity entity : GeneralMethods.getEntitiesAroundPoint( + location, 2)) { + if (entity instanceof LivingEntity + && entity.getEntityId() != player.getEntityId() + && !grabbedEntities.containsKey(entity)) { + grabbedEntities.put((LivingEntity) entity, id); + grabbedEntity = (LivingEntity) entity; + grabbed = true; + reverting = true; + waterArms.setActiveArmCooldown(true); + break; + } + } + } + break; + default: + break; + } + } + + private void dragEntity(Location location) { + if (grabbedEntity != null && grabbed) { + if (!waterArms.canDisplayActiveArm() || grabbedEntity.isDead()) { + grabbed = false; + grabbedEntities.remove(grabbedEntity); + return; + } + Location newlocation = grabbedEntity.getLocation(); + double distance = location.distance(newlocation); + double dx, dy, dz; + dx = location.getX() - newlocation.getX(); + dy = location.getY() - newlocation.getY(); + dz = location.getZ() - newlocation.getZ(); + Vector vector = new Vector(dx, dy, dz); + if (distance > .5) { + grabbedEntity.setVelocity(vector.normalize().multiply(1)); + } else { + grabbedEntity.setVelocity(new Vector(0, 0, 0)); + } + grabbedEntity.setFallDistance(0); + if (grabbedEntity instanceof Creature) { + ((Creature) grabbedEntity).setTarget(null); + } + } + } + + private void grapplePlayer(Location location) { + if (reverting && grappled && player != null && end != null + && ability.equals(Whip.Grapple)) { + if (GeneralMethods.isRegionProtectedFromBuild(player, "WaterArms", + location) && grappleRespectRegions) { + return; + } + Vector vector = player.getLocation().toVector() + .subtract(location.toVector()); + player.setVelocity(vector.multiply(-0.25)); + player.setFallDistance(0); + } + } + + public static Integer getId(Player player) { + for (int id : instances.keySet()) { + if (instances.get(id).player.equals(player)) { + return id; + } + } + return 0; + } + + public static void checkValidEntities() { + for (LivingEntity e : grabbedEntities.keySet()) { + if (instances.containsKey(grabbedEntities.get(e))) { + if (instances.get(grabbedEntities.get(e)).grabbedEntity == null) { + grabbedEntities.remove(e); + } + } else { + grabbedEntities.remove(e); + } + } + } + + private void remove() { + if (WaterArms.instances.containsKey(player)) { + if (arm.equals(Arm.Left)) { + waterArms.setLeftArmCooldown(false); + } else { + waterArms.setRightArmCooldown(false); + } + if (hasDamaged) { + waterArms.setMaxPunches(waterArms.getMaxPunches() - 1); + } + waterArms.setMaxUses(waterArms.getMaxUses() - 1); + } + instances.remove(id); + } + + public static void progressAll() { + checkValidEntities(); + for (int ID : instances.keySet()) + instances.get(ID).progress(); + } + + public static void removeAll() { + grabbedEntities.clear(); + instances.clear(); + } + + public Player getPlayer() { + return player; + } + + public Integer getWhipLength() { + return whipLength; + } + + public void setArmLength(int armLength) { + this.whipLength = armLength; + } + + public Double getPunchDamage() { + return punchDamage; + } + + public void setPunchDamage(double damage) { + this.punchDamage = damage; + } + + public long getHoldTime() { + return holdTime; + } + + public void setHoldTime(long holdTime) { + this.holdTime = holdTime; + } + + public boolean getReverting() { + return reverting; + } + + public void setReverting(boolean reverting) { + this.reverting = reverting; + } + + public boolean getGrappled() { + return grappled; + } + + public void setGrappled(boolean grappled) { + this.grappled = grappled; + } + + public boolean getGrabbed() { + return grabbed; + } + + public void setGrabbed(boolean grabbed) { + this.grabbed = grabbed; + } + + public LivingEntity getHeldEntity() { + return grabbedEntity; + } +} \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/waterbending/WaterMethods.java b/src/com/projectkorra/ProjectKorra/waterbending/WaterMethods.java index 58b70192..cf188c92 100644 --- a/src/com/projectkorra/ProjectKorra/waterbending/WaterMethods.java +++ b/src/com/projectkorra/ProjectKorra/waterbending/WaterMethods.java @@ -368,5 +368,6 @@ public class WaterMethods { WaterWave.removeAll(); WaterCombo.removeAll(); WaterReturn.removeAll(); + WaterArms.removeAll(); } } \ No newline at end of file diff --git a/src/com/projectkorra/ProjectKorra/waterbending/WaterbendingManager.java b/src/com/projectkorra/ProjectKorra/waterbending/WaterbendingManager.java index 0b7ed080..d85fa7d0 100644 --- a/src/com/projectkorra/ProjectKorra/waterbending/WaterbendingManager.java +++ b/src/com/projectkorra/ProjectKorra/waterbending/WaterbendingManager.java @@ -34,6 +34,7 @@ public class WaterbendingManager implements Runnable { IceBlast.progressAll(); WaterWave.progressAll(); WaterCombo.progressAll(); + WaterArms.progressAll(); } catch (Exception e) { GeneralMethods.logError(e, false); } diff --git a/src/config.yml b/src/config.yml index 0f2b15a4..b261cebb 100644 --- a/src/config.yml +++ b/src/config.yml @@ -1,613 +1,673 @@ -Properties: - ImportEnabled: true - GlobalCooldown: 500 - SeaLevel: 62 - CustomItems: - GrapplingHook: - Enable: true - IronUses: 25 - GoldUses: 50 - Chat: - Format: ": " - Enable: true - Prefixes: - Air: "[Airbender]" - Water: "[Waterbender]" - Earth: "[Earthbender]" - Fire: "[Firebender]" - Chi: "[Chiblocker]" - Avatar: "[Avatar]" - Colors: - Avatar: DARK_PURPLE - Air: GRAY - Fire: RED - Water: AQUA - Earth: GREEN - Metalbending: DARK_GREEN - Chi: GOLD - RegionProtection: - AllowHarmlessAbilities: true - RespectWorldGuard: true - RespectGriefPrevention: true - RespectFactions: true - RespectTowny: true - RespectPreciousStones: true - RespectLWC: true - CacheBlockTime: 5000 - Air: - CanBendWithWeapons: false - Particles: smoke - PlaySound: true - Water: - CanBendWithWeapons: false - NightFactor: 1.5 - FullMoonFactor: 3.0 - CanBendPackedIce: true - PlaySound: true - Earth: - RevertEarthbending: true - SafeRevert: true - RevertCheckTime: 300000 - CanBendWithWeapons: true - EarthbendableBlocks: - - STONE - - COAL_ORE - - DIAMOND_ORE - - DIRT - - GOLD_ORE - - GRASS - - GRAVEL - - IRON_ORE - - LAPIS_ORE - - NETHERRACK - - REDSTONE_ORE - - SAND - - SANDSTONE - - MYCEL - MetalBlocks: - - IRON_BLOCK - - GOLD_BLOCK - - QUARTZ_BLOCK - MetalPowerFactor: 1.5 - PlaySound: true - Fire: - CanBendWithWeapons: true - DayFactor: 1.5 - PlaySound: true - Chi: - CanBendWithWeapons: false - DisabledWorlds: - - TestWorld - - TestWorld2 -Abilities: - AvatarState: - Enabled: true - 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 all sources, regenreates health rapidly, and is granted extreme speed. Nearly all abilities are incredibly amplified in this state. Additionally, AirShield and FireJet become toggle-able abilities and last until you deactivate them or the Avatar State. Click again with the Avatar State selected to deactivate it." - Cooldown: 720000 - Duration: 480000 - PowerMultiplier: 5 - PotionEffects: - Regeneration: - Enabled: true - Power: 3 - Speed: - Enabled: true - Power: 3 - DamageResistance: - Enabled: true - Power: 3 - FireResistance: - Enabled: true - Power: 3 - Air: - Passive: - Factor: 0.3 - Speed: 2 - Jump: 3 - AirBlast: - Enabled: true - Description: "AirBlast is the most fundamental bending technique of an airbender. To use, simply left-click in a direction. A gust of wind will be created at your fingertips, launching anything in its path harmlessly back. A gust of air can extinguish fires on the ground or on a player, can cool lava, and can flip levers and activate buttons. Additionally, tapping sneak will change the original of your next AirBlast to your targeted location." - Speed: 25 - Range: 20 - Radius: 2 - Push: 3.5 - AirBubble: - Enabled: true - Description: "To use, the bender must merely have the ability selected. All water around the user in a small bubble will vanish, replacing itself once the user either gets too far away or selects a different ability." - Radius: 7 - AirBurst: - Enabled: true - Description: "AirBurst is one of the most powerful abilities in an airbender's arsenal. To use, press and hold sneak to charge your burst. Once charged, you can either release sneak to launch a cone-shaped burst of air in front of you, or click to release theb urst in a sphere around you. Additionally, having this ability selected when you land on the ground from a large enough fall will create a burst of air around you." - FallThreshold: 10 - PushFactor: 1.5 - ChargeTime: 1750 - Damage: 0 - AirScooter: - Enabled: true - Description: "AirScooter is a fast means of transportation. To use, sprint, jump then click with this ability selected. YOu will hop on a scooter of air and be propelled forward in the direction you're looking (you don't need to press anything). This ability can be used to levitate above liquids, but it cannot go up steep slopes. Any other actions will deactivate this ability." - Speed: 0.675 - AirShield: - Enabled: true - Description: "Air Shield is one of the most powerful defensive techniques in existence. To use, simply sneak (default: shift). This will create a whirlwind of air around the user, with a small pocket of safe space in the center. This wind will deflect all projectiles and will prevent any creature from entering it for as long as its maintained." - Radius: 7 - IsAvatarStateToggle: true - AirSpout: - Enabled: true - Description: "This ability gives the airbender limited sustained levitation. It is a toggle - click to activate and form a whirling spout of air beneath you, lifting you up. You can bend other abilities while using AirSpout. Click again to deactivate this ability." - Height: 20 - AirSuction: - Enabled: true - Description: "To use, simply left-click in a direction. A gust of wind will originate as far as it can in that direction and flow towards you, sucking anything in its path harmlessly with it. Skilled benders can use this technique to pull items from precarious locations. Additionally, tapping sneak will change the origin of your next AirSuction to your targeted location." - Speed: 25 - Range: 20 - Radius: 2 - Push: 3.5 - AirSwipe: - Enabled: true - Description: "To use, simply left-click in a direction. An arc of air will flow from you towards that direction, cutting and pushing back anything in its path. Its damage is minimal, but it still sends the message. This ability will extinguish fires, cool lava, and cut things like grass, mushrooms, and flowers. Additionally, you can charge it by holding sneak. Charging before attacking will increase damage and knockback, up to a maximum." - Damage: 2 - Range: 16 - Radius: 2 - Push: 1 - Arc: 20 - Speed: 25 - Cooldown: 1500 - ChargeFactor: 3 - MaxChargeTime: 3000 - Flight: - Enabled: true - Description: "Jump in the air, crouch (default: shift) and hold with this ability bound and you will glide around in the direction you look. While flying, click to Hover. Click again to disable Hovering." - HoverEnabled: true - Suffocate: - Enabled: true - Description: "This ability is one of the most dangerous abilities an Airbender possesses. To use, simply look at an entity and hold shift. The entity will begin taking damage as you extract the air from their lungs. Any bender caught in this sphere will only be able to use basic moves, such as AirSwipe, WaterManipulation, FireBlast, or EarthBlast. An entity can be knocked out of the sphere by certain bending arts, and your attention will be disrupted if you are hit by bending." - Range: 15 - Damage: 2 - ChargeTime: 1000 - Cooldown: 0 - DamageInitialDelay: 2 - DamageInterval: 1 - SlowPotency: 1 - SlowDelay: 0.5 - SlowInterval: 1.25 - BlindPotentcy: 30 - BlindDelay: 2 - BlindInterval: 1.5 - CanBeUsedOnUndeadMobs: true - RequireConstantAim: true - RequireConstantAimRadius: 5 - AnimationRadius: 2.0 - AnimationParticleAmount: 2 - AnimationSpeed: 1.0 - Tornado: - Enabled: true - Description: "To use, simply sneak (default: shift). This will create a swirling vortex at the targeted location. Any creature or object caught in the vortex will be launched up and out in some random direction. If another player gets caught in the vortex, the launching effect is minimal. Tornado can also be used to transport the user. If the user gets caught in his/her own tornado, his/her movements are much more manageable. Provided the user doesn't fall out of the vortex, it will take him to a maximum height and move him in the general direction he/she is looking. Skilled airbenders can scale anything with this ability." - Radius: 10 - Height: 25 - Range: 25 - MobPushFactor: 1 - PlayerPushFactor: 1 - AirCombo: - Enabled: true - Twister: - Speed: 0.35 - Range: 16 - Height: 8 - Radius: 3.5 - RemoveDelay: 1500 - Cooldown: 10000 - DegreesPerParticle: 9 - HeightPerParticle: 2.0 - AirStream: - Speed: 0.5 - Range: 40 - EntityDuration: 4000 - EntityHeight: 14 - Cooldown: 6000 - AirSweep: - Speed: 1.4 - Range: 14 - Damage: 4 - Knockback: 3.5 - Cooldown: 5000 - Water: - Passive: - SwimSpeedFactor: 0.7 - Bloodbending: - Enabled: true - Description: "This ability was made illegal for a reason. With this ability selected, sneak while targeting something and you will bloodbend that target. Bloodbent targets cannot move, bend, or attack. You are free to control their actions by looking elsewhere - they will be forced to move in that direction. Additionally, clicking while bloodbending will launch that target off in the direction you're looking. People who are capable of bloodbending are immune to technique, and you are immune to theirs." - CanOnlyBeUsedAtNight: false - CanBeUsedOnUndeadMobs: true - CanOnlyBeUsedDuringFullMoon: false - ThrowFactor: 2 - Range: 10 - HoldTime: 2000 - Cooldown: 4000 - HealingWaters: - Enabled: true - 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 - Power: 1 - 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." - Cooldown: 2000 - Damage: 2 - Range: 20 - ThrowingMult: 0.7 - Height: 6 - Projectile: - Range: 20 - Damage: 1 - OctopusForm: - Enabled: true - Description: "This ability allows the waterbender to manipulate a large quantity of water into a form resembling that of an octopus. To use, click to select a water source. Then, hold sneak to channel this ability. While channleing, the water will form itself around you and has a chance to block incoming attacks. Additionally, you can click while channeling to attack things near you, dealing damage and knocking the target back. Releasing shift at any time will dissipate the form." - Range: 10 - AttackRange: 2.5 - Damage: 3 - Radius: 3 - FormDelay: 50 - Knockback: 1.75 - PhaseChange: - Enabled: true - Description: "To use, simply left-click. Any water you are looking at within range will instantly freeze over into solid ice. Provided you stay within range of the ice and do not unbind FreezeMelt, that ice will not thaw. If, however, you do either of those things the ice will instantly thaw. If you sneak (default: shift), anything around where you are looking at will instantly melt. Since this is a more favorable state for these things, they will never re-freeze unless they would otherwise by nature or some other bending ability. Additionally, if you tap sneak while targeting water with FreezeMelt, it will evaporate water around that block that is above sea level." - Range: 20 - Radius: 5 - Plantbending: - RegrowTime: 180000 - Surge: - Enabled: true - Description: "This ability has two distinct features. If you sneak to select a source block, you can then click in a direction and a large wave will be launched in that direction. If you sneak again while the wave is en route, the wave will freeze the next target it hits. If, instead, you click to select a source block, you can hold sneak to form a wall of water at your cursor location. Click to shift between a water wall and an ice wall. Release sneak to dissipate it." - Wave: - Radius: 3 - HorizontalPush: 1 - VerticalPush: 0.2 - Range: 20 - Wall: - Range: 5 - Radius: 2 - VerticalPush: 0.2 - Torrent: - Enabled: true - Description: "Torrent is one of the strongest moves in a waterbender's arsenal. To use, first click a source block to select it; then hold shift to begin streaming the water around you. Water flowing around you this way will damage and knock back nearby enemies and projectiles. If you release shift during this, you will create a large wave that expands outwards from you, launching anything in its path back. Instead, if you click you release the water and channel it to flow towards your cursor. Anything caught in the blast will be tossed about violently and take damage. Finally, if you click again when the water is torrenting, it will freeze the area around it when it is obstructed." - Damage: 2 - DeflectDamage: 1 - Range: 25 - Wave: - Radius: 15 - Knockback: 1.5 - Height: 1 - WaterBubble: - Enabled: true - Description: "To use, the bender must merely have the ability selected. All water around the user in a small bubble will vanish, replacing itself once the user either gets too far away or selects a different ability." - Radius: 7 - WaterManipulation: - Enabled: true - Description: "To use, place your cursor over a waterbendable object and tap sneak (default: shift). Smoke will appear where you've selected, indicating the origin of your ability. After you have selected an origin, simply left-click in any direction and you will see your water spout off in that direction, slicing any creature in its path. If you look towards a creature when you use this ability, it will target that creature. A collision from Water Manipulation both knocks the target back and deals some damage. Alternatively, if you have the source selected and tap shift again, you will be able to control the water more directly." - Damage: 3.0 - Range: 20 - Speed: 35 - Push: .3 - Cooldown: 1000 - WaterSpout: - Enabled: true - Description: "This ability provides a Waterbender with a new means of transportation. To use, simply left click while in or over water to spout water up beneath you, experiencing controlled levitation. Left clicking again while the spout is active will cause it to disappear. Alternatively, tapping a Waterbendable block while not in Water will select a water block as a source, from there, you can tap sneak (Default:Shift) to channel the Water around you. Releasing the sneak will create a wave allowing you a quick burst of controlled transportation. While riding the wave you may press sneak to cause the wave to disappear." - Height: 20 - Wave: - Enabled: true - Range: 6 - ChargeTime: 1000 - FlightTime: 2000 - Speed: 1.2 - WaterCombo: - Enabled: true - IceWave: - Damage: 3 - Cooldown: 6000 - IceBullet: - Damage: 1.5 - Radius: 2.5 - Range: 12 - MaxShots: 30 - AnimationSpeed: 1 - ShootTime: 5000 - Cooldown: 10000 - Earth: - Passive: - Duration: 2500 - Catapult: - Enabled: true - Description: "To use, left-click while looking in the direction you want to be launched. A pillar of earth will jut up from under you and launch you in that direction - if and only if there is enough earth behind where you're looking to launch you. Skillful use of this ability takes much time and work, and it does result in the death of certain gung-ho earthbenders. if you plan to use this ability, be sure you've read about your passive ability you innately have as an earthbender." - Length: 7 - Speed: 12 - Push: 5 - Collapse: - Enabled: true - Description: "To use, simply left-click an earthbendable block. That block and the earthbendable blocks above it will be shoved back into the earth below, if they can. This ability does have the capacity to trap something inside of it, although it is incredibly difficult to do so. Additionally, press sneak with this ability to affect an area around your targeted location - all earth that can be moved downwards will be moved downwards. This ability is especially risky or deadly in caves, depending on the earthbender's goal and technique." - Range: 20 - Radius: 7 - Speed: 8 - EarthArmor: - Enabled: true - Description: "This ability encases the earthbender in temporary armor. To use, click on a block that is earthbendable. If there is another block under it that is earthbendable, the block will fly to you and grant you temporary armor and damage reduction. This ability has a long cooldown." - Duration: 10000 - Strength: 2 - Cooldown: 17500 - EarthBlast: - Enabled: true - Description: "To use, place your cursor over an earthbendable object and tap sneak (default: shift). The object will temporarily turn to stone, indicating that you have it focused as the source for your ability. After you have selected an origin (you no longer need to be sneaking), simply left-click in any direction and you will see your object launch off in that direction, smashing into any creature in its path. If you look towards a creature when you use this ability, it will target that creature. A collision from Earth Blast both knocks the target back and deals some damage. You cannot have multiple of these abilities flying at the same time." - CanHitSelf: false - PrepareRange: 7 - Range: 20 - Speed: 35 - Revert: true - Damage: 4 - Push: 0.3 - EarthGrab: - Enabled: true - Description: "To use, simply left-click while targeting a creature within range. This ability will erect a circle of earth to trap the creature in." - Range: 15 - EarthTunnel: - Enabled: true - Description: "Earth Tunnel is a completely utility ability for earthbenders. To use, simply sneak (default: shift) in the direction you want to tunnel. You will slowly begin tunneling in the direction you're facing for as long as you sneak or if the tunnel has been dug long enough. This ability will be interrupted if it hits a block that cannot be earthbent." - MaxRadius: 1 - Range: 10 - Radius: 0.25 - Revert: true - Interval: 30 - Extraction: - Enabled: true - Description: "This ability allows metalbenders to extract the minerals from ore blocks. To use, simply tap sneak while looking at an ore block with metal in it (iron, gold, etc) and the ore will be extracted and drop in front of you. This ability has a small chance of doubling or tripling the loot. This ability has a short cooldown." - Cooldown: 10000 - TripleLootChance: 15 - DoubleLootChance: 40 - MetalClips: - Enabled: true - LavaFlow: - Enabled: true - Description: 'This ability allows an Earthbender to create lava using the Earth - around them. To use, simply hold sneak (Default: Shift) to create a lava moat - that surrounds you, press sneak again to remove the moat. Left click an Earthbendable - block to create a pool of lava after a small delay. Additionally, you can - left click at any time to turn lava back into its original state -- Earth.' - ShiftCooldown: 16000 - ClickLavaCooldown: 10000 - ClickLandCooldown: 500 - ShiftCleanupDelay: 10000 - ClickLavaCleanupDelay: 7000 - ClickLandCleanupDelay: 20000 - ClickRange: 10.0 - ShiftRadius: 8.0 - ClickRadius: 5.0 - ShiftPlatformRadius: 1.5 - ClickLavaCreateSpeed: 0.05 - ClickLandCreateSpeed: 0.1 - ShiftFlowSpeed: 0.1 - ShiftRemoveSpeed: 3.0 - ClickLavaStartDelay: 1500 - ClickLandStartDelay: 0 - UpwardFlow: 2 - DownwardFlow: 4 - AllowNaturalFlow: false - ParticleDensity: 0.33 - EarthSmash: - Enabled: true - Description: 'To raise an EarthSmash hold sneak (default: shift) for approximately - 1.5 seconds, then release while aiming at dirt. To grab the EarthSmash aim - at the center and hold sneak, the EarthSmash will follow your mouse. You can - shoot the EarthSmash by grabbing onto it and left clicking. To ride the EarthSmash - simply hop ontop of it and hold sneak while aiming in the direction that you - wish to go. Another way to ride an EarthSmash is to grab it with sneak and - then right click it. Use EarthSmash as a defensive shield, a powerful attack, - or an advanced means of transportation.' - AllowGrab: true - AllowShooting: true - AllowFlight: true - GrabRange: 10 - ChargeTime: 1200 - Cooldown: 0 - ShotRange: 30 - Damage: 6 - Knockback: 3.5 - Knockup: 0.15 - FlightSpeed: 0.72 - FlightTimer: 3000 - RemoveTimer: 30000 - 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 - Shockwave: - Enabled: true - Description: "This is one of the most powerful moves in the earthbender's arsenal. To use, you must first charge it by holding sneak (default: shift). Once charged, you can release sneak to create an enormous shockwave of earth, disturbing all earth around you and expanding radially outwards. Anything caught in the shockwave will be blasted back and dealt damage. If you instead click while charged, the disruption is focused in a cone in front of you. Lastly, if you fall from a great enough height with this ability selected, you will automatically create a shockwave." - ChargeTime: 2500 - FallThreshold: 10 - Damage: 5 - Knockback: 1.1 - Range: 15 - Tremorsense: - Enabled: true - Description: "This is a pure utility ability for earthbenders. If you are in an area of low-light and are standing on top of an earthbendable block, this ability will automatically turn that block into glowstone, visible *only by you*. If you lose contact with a bendable block, the light will go out as you have lost contact with the earth and cannot 'see' until you can touch earth again. Additionally, if you click with this ability selected, smoke will appear above nearby earth with pockets of air beneath them." - MaxDepth: 10 - Radius: 5 - LightThreshold: 7 - Cooldown: 1000 - Fire: - Blaze: - Enabled: true - Description: "To use, simply click in any direction. An arc of fire will flow from your location, igniting anything in its path. Additionally, tap sneak to engulf the area around you in roaring flames." - ArcOfFire: - Arc: 20 - Range: 9 - RingOfFire: - Range: 7 - Combustion: - Enabled: true - Description: "Combustion is a powerful ability only known by a few skilled Firebenders. It allows the bender to Firebend with their mind, concentrating energy to create a powerful blast. To use, simply tap sneak (Default: Shift) to launch the blast. This technique is highly destructive and very effective, it also comes with a long cooldown." - Cooldown: 15000 - BreakBlocks: false - Power: 1.0 - Damage: 5 - Radius: 4 - Range: 20 - Speed: 25 - FireBlast: - Enabled: true - Description: "FireBlast is the most fundamental technique of a firebender. To use, simply left-click in a direction. A blast of fire will be created at your fingertips. If this blast contacts an enemy, it will dissipate and engulf them in flames, doing additional damage and knocking them back slightly. If the blast hits terrain, it will ignite the nearby area. Additionally, if you hold sneak, you will charge up the fireblast. If you release it when it's charged, it will instead launch a powerful fireball that explodes on contact." - Speed: 15 - Range: 15 - Radius: 2 - Push: 0.3 - Damage: 2 - Cooldown: 1500 - Dissipate: false - Charged: - ChargeTime: 2000 - Damage: 4 - DamageRadius: 6 - Power: 1 - Range: 20 - FireBurst: - Enabled: true - Description: "FireBurst is a very powerful firebending ability. To use, press and hold sneak to charge your burst. Once charged, you can either release sneak to launch a cone-shaped burst of flames in front of you, or click to release the burst in a sphere around you." - ChargeTime: 2500 - Damage: 3 - Range: 15 - FireJet: - Enabled: true - 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 controlled flight for a short time. This ability can be used mid-air to prevent falling to your death, but on the ground it can only be used if standing on a block that's ignitable (e.g. not snow or water)." - Speed: 0.7 - Duration: 1500 - Cooldown: 6000 - IsAvatarStateToggle: true - FireShield: - Enabled: true - Description: "FireShield is a basic defensive ability. Clicking with this ability selected will create a small disc of fire in front of you, which will block most attacks and bending. Alternatively, pressing and holding sneak creates a very small shield of fire, blocking most attacks. Creatures that contact this fire are ignited." - Radius: 3 - DiscRadius: 1.5 - Duration: 1000 - 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 - Illumination: - Enabled: true - Description: "This ability gives firebenders a means of illuminating the area. It is a toggle - clicking will create a torch that follows you around. The torch will only appear on objects that are ignitable and can hold a torch (e.g. not leaves or ice). If you get too far away from the torch, it will disappear, but will reappear when you get on another ignitable block. Clicking again dismisses this torch." - Range: 5 - Lightning: - Enabled: true - Description: "Hold sneak while selecting this ability to charge up a lightning strike. once charged, release sneak to discharge the lightning to the targeted location." - Damage: 6 - Range: 13.0 - ChargeTime: 3500 - Cooldown: 0 - StunChance: 0.2 - StunDuration: 30.0 - MaxArcAngle: 30 - SubArcChance: 0.025 - ChainArcRange: 6.0 - ChainArcChance: 0.5 - MaxChainArcs: 2 - WaterArcs: 4 - WaterArcRange: 12.0 - SelfHitWater: true - SelfHitClose: true - ArcOnIce: false - WallOfFire: - Enabled: true - Description: "To use this ability, click at a location. A wall of fire will appear at this location, igniting enemies caught in it and blocking projectiles." - Range: 4 - Height: 4 - Width: 4 - Duration: 5000 - Damage: 2 - Cooldown: 7500 - Interval: 500 - FireCombo: - Enabled: true - FireKick: - Range: 7.0 - Damage: 3.0 - Cooldown: 2000 - FireSpin: - Range: 7 - Damage: 3.0 - Knockback: 3.2 - Cooldown: 2000 - FireWheel: - Range: 20.0 - Damage: 4.0 - Speed: 0.55 - Cooldown: 200 - JetBlast: - Speed: 1.2 - Cooldown: 6000 - JetBlaze: - Speed: 1.1 - Damage: 3 - Cooldown: 6000 - Chi: - Passive: - FallReductionFactor: 0.5 - Speed: 1 - Jump: 2 - BlockChi: - Duration: 2500 - DodgeChance: 25 - AcrobatStance: - Enabled: true - Description: "AcrobatStance gives a Chiblocker a higher probability of blocking a Bender's Chi while granting them a Speed and Jump boost. It also increases the rate at which the hunger bar depletes. To use, simply left click. Left clicking again will de-activate the stance." - ChiBlockBoost: 0.1 - HighJump: - Enabled: true - Description: "To use this ability, simply click. You will jump quite high. This ability has a short cooldown." - Cooldown: 10000 - Height: 1 - Paralyze: - Enabled: true - Description: "Paralyzes the target, making them unable to do anything for a short period of time. This ability has a long cooldown." - Cooldown: 15000 - Duration: 2000 - RapidPunch: - Enabled: true - Description: "This ability allows the chiblocker to punch rapidly in a short period. To use, simply punch. This has a short cooldown." - Damage: 1 - Distance: 4 - Cooldown: 15000 - Punches: 4 - Smokescreen: - Enabled: true - Description: "Smokescren, if used correctly, can serve as a defensive and offensive ability for Chiblockers. To use, simply left click and you will toss out a Smoke Bomb. When the bomb hits the ground, it will explode and give all players within a small radius of the explosion temporary blindness, allowing you to either get away, or move in for the kill. This ability has a long cooldown." - Cooldown: 50000 - Radius: 4 - Duration: 15 - WarriorStance: - Enabled: true - Description: "WarriorStance gives a Chiblocker increased damage but makes them a tad more vulnerable. To activate, simply left click." - Strength: 1 - Resistance: -1 -Storage: - engine: sqlite - MySQL: - host: localhost - port: 3306 - pass: '' - db: minecraft - user: root +Properties: + ImportEnabled: true + GlobalCooldown: 500 + SeaLevel: 62 + CustomItems: + GrapplingHook: + Enable: true + IronUses: 25 + GoldUses: 50 + Chat: + Format: ": " + Enable: true + Prefixes: + Air: "[Airbender]" + Water: "[Waterbender]" + Earth: "[Earthbender]" + Fire: "[Firebender]" + Chi: "[Chiblocker]" + Avatar: "[Avatar]" + Colors: + Avatar: DARK_PURPLE + Air: GRAY + Fire: RED + Water: AQUA + Earth: GREEN + Metalbending: DARK_GREEN + Chi: GOLD + RegionProtection: + AllowHarmlessAbilities: true + RespectWorldGuard: true + RespectGriefPrevention: true + RespectFactions: true + RespectTowny: true + RespectPreciousStones: true + RespectLWC: true + CacheBlockTime: 5000 + Air: + CanBendWithWeapons: false + Particles: smoke + PlaySound: true + Water: + CanBendWithWeapons: false + NightFactor: 1.5 + FullMoonFactor: 3.0 + CanBendPackedIce: true + PlaySound: true + Earth: + RevertEarthbending: true + SafeRevert: true + RevertCheckTime: 300000 + CanBendWithWeapons: true + EarthbendableBlocks: + - STONE + - COAL_ORE + - DIAMOND_ORE + - DIRT + - GOLD_ORE + - GRASS + - GRAVEL + - IRON_ORE + - LAPIS_ORE + - NETHERRACK + - REDSTONE_ORE + - SAND + - SANDSTONE + - MYCEL + MetalBlocks: + - IRON_BLOCK + - GOLD_BLOCK + - QUARTZ_BLOCK + MetalPowerFactor: 1.5 + PlaySound: true + Fire: + CanBendWithWeapons: true + DayFactor: 1.5 + PlaySound: true + Chi: + CanBendWithWeapons: false + DisabledWorlds: + - TestWorld + - TestWorld2 +Abilities: + AvatarState: + Enabled: true + 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 all sources, regenreates health rapidly, and is granted extreme speed. Nearly all abilities are incredibly amplified in this state. Additionally, AirShield and FireJet become toggle-able abilities and last until you deactivate them or the Avatar State. Click again with the Avatar State selected to deactivate it." + Cooldown: 720000 + Duration: 480000 + PowerMultiplier: 5 + PotionEffects: + Regeneration: + Enabled: true + Power: 3 + Speed: + Enabled: true + Power: 3 + DamageResistance: + Enabled: true + Power: 3 + FireResistance: + Enabled: true + Power: 3 + Air: + Passive: + Factor: 0.3 + Speed: 2 + Jump: 3 + AirBlast: + Enabled: true + Description: "AirBlast is the most fundamental bending technique of an airbender. To use, simply left-click in a direction. A gust of wind will be created at your fingertips, launching anything in its path harmlessly back. A gust of air can extinguish fires on the ground or on a player, can cool lava, and can flip levers and activate buttons. Additionally, tapping sneak will change the original of your next AirBlast to your targeted location." + Speed: 25 + Range: 20 + Radius: 2 + Push: 3.5 + AirBubble: + Enabled: true + Description: "To use, the bender must merely have the ability selected. All water around the user in a small bubble will vanish, replacing itself once the user either gets too far away or selects a different ability." + Radius: 7 + AirBurst: + Enabled: true + Description: "AirBurst is one of the most powerful abilities in an airbender's arsenal. To use, press and hold sneak to charge your burst. Once charged, you can either release sneak to launch a cone-shaped burst of air in front of you, or click to release theb urst in a sphere around you. Additionally, having this ability selected when you land on the ground from a large enough fall will create a burst of air around you." + FallThreshold: 10 + PushFactor: 1.5 + ChargeTime: 1750 + Damage: 0 + AirScooter: + Enabled: true + Description: "AirScooter is a fast means of transportation. To use, sprint, jump then click with this ability selected. YOu will hop on a scooter of air and be propelled forward in the direction you're looking (you don't need to press anything). This ability can be used to levitate above liquids, but it cannot go up steep slopes. Any other actions will deactivate this ability." + Speed: 0.675 + AirShield: + Enabled: true + Description: "Air Shield is one of the most powerful defensive techniques in existence. To use, simply sneak (default: shift). This will create a whirlwind of air around the user, with a small pocket of safe space in the center. This wind will deflect all projectiles and will prevent any creature from entering it for as long as its maintained." + Radius: 7 + IsAvatarStateToggle: true + AirSpout: + Enabled: true + Description: "This ability gives the airbender limited sustained levitation. It is a toggle - click to activate and form a whirling spout of air beneath you, lifting you up. You can bend other abilities while using AirSpout. Click again to deactivate this ability." + Height: 20 + AirSuction: + Enabled: true + Description: "To use, simply left-click in a direction. A gust of wind will originate as far as it can in that direction and flow towards you, sucking anything in its path harmlessly with it. Skilled benders can use this technique to pull items from precarious locations. Additionally, tapping sneak will change the origin of your next AirSuction to your targeted location." + Speed: 25 + Range: 20 + Radius: 2 + Push: 3.5 + AirSwipe: + Enabled: true + Description: "To use, simply left-click in a direction. An arc of air will flow from you towards that direction, cutting and pushing back anything in its path. Its damage is minimal, but it still sends the message. This ability will extinguish fires, cool lava, and cut things like grass, mushrooms, and flowers. Additionally, you can charge it by holding sneak. Charging before attacking will increase damage and knockback, up to a maximum." + Damage: 2 + Range: 16 + Radius: 2 + Push: 1 + Arc: 20 + Speed: 25 + Cooldown: 1500 + ChargeFactor: 3 + MaxChargeTime: 3000 + Flight: + Enabled: true + Description: "Jump in the air, crouch (default: shift) and hold with this ability bound and you will glide around in the direction you look. While flying, click to Hover. Click again to disable Hovering." + HoverEnabled: true + Suffocate: + Enabled: true + Description: "This ability is one of the most dangerous abilities an Airbender possesses. To use, simply look at an entity and hold shift. The entity will begin taking damage as you extract the air from their lungs. Any bender caught in this sphere will only be able to use basic moves, such as AirSwipe, WaterManipulation, FireBlast, or EarthBlast. An entity can be knocked out of the sphere by certain bending arts, and your attention will be disrupted if you are hit by bending." + Range: 15 + Damage: 2 + ChargeTime: 1000 + Cooldown: 0 + DamageInitialDelay: 2 + DamageInterval: 1 + SlowPotency: 1 + SlowDelay: 0.5 + SlowInterval: 1.25 + BlindPotentcy: 30 + BlindDelay: 2 + BlindInterval: 1.5 + CanBeUsedOnUndeadMobs: true + RequireConstantAim: true + RequireConstantAimRadius: 5 + AnimationRadius: 2.0 + AnimationParticleAmount: 2 + AnimationSpeed: 1.0 + Tornado: + Enabled: true + Description: "To use, simply sneak (default: shift). This will create a swirling vortex at the targeted location. Any creature or object caught in the vortex will be launched up and out in some random direction. If another player gets caught in the vortex, the launching effect is minimal. Tornado can also be used to transport the user. If the user gets caught in his/her own tornado, his/her movements are much more manageable. Provided the user doesn't fall out of the vortex, it will take him to a maximum height and move him in the general direction he/she is looking. Skilled airbenders can scale anything with this ability." + Radius: 10 + Height: 25 + Range: 25 + MobPushFactor: 1 + PlayerPushFactor: 1 + AirCombo: + Enabled: true + Twister: + Speed: 0.35 + Range: 16 + Height: 8 + Radius: 3.5 + RemoveDelay: 1500 + Cooldown: 10000 + DegreesPerParticle: 9 + HeightPerParticle: 2.0 + AirStream: + Speed: 0.5 + Range: 40 + EntityDuration: 4000 + EntityHeight: 14 + Cooldown: 6000 + AirSweep: + Speed: 1.4 + Range: 14 + Damage: 4 + Knockback: 3.5 + Cooldown: 5000 + Water: + Passive: + SwimSpeedFactor: 0.7 + Bloodbending: + Enabled: true + Description: "This ability was made illegal for a reason. With this ability selected, sneak while targeting something and you will bloodbend that target. Bloodbent targets cannot move, bend, or attack. You are free to control their actions by looking elsewhere - they will be forced to move in that direction. Additionally, clicking while bloodbending will launch that target off in the direction you're looking. People who are capable of bloodbending are immune to technique, and you are immune to theirs." + CanOnlyBeUsedAtNight: false + CanBeUsedOnUndeadMobs: true + CanOnlyBeUsedDuringFullMoon: false + ThrowFactor: 2 + Range: 10 + HoldTime: 2000 + Cooldown: 4000 + HealingWaters: + Enabled: true + 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 + Power: 1 + 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." + Cooldown: 2000 + Damage: 2 + Range: 20 + ThrowingMult: 0.7 + Height: 6 + Projectile: + Range: 20 + Damage: 1 + OctopusForm: + Enabled: true + Description: "This ability allows the waterbender to manipulate a large quantity of water into a form resembling that of an octopus. To use, click to select a water source. Then, hold sneak to channel this ability. While channleing, the water will form itself around you and has a chance to block incoming attacks. Additionally, you can click while channeling to attack things near you, dealing damage and knocking the target back. Releasing shift at any time will dissipate the form." + Range: 10 + AttackRange: 2.5 + Damage: 3 + Radius: 3 + FormDelay: 50 + Knockback: 1.75 + PhaseChange: + Enabled: true + Description: "To use, simply left-click. Any water you are looking at within range will instantly freeze over into solid ice. Provided you stay within range of the ice and do not unbind FreezeMelt, that ice will not thaw. If, however, you do either of those things the ice will instantly thaw. If you sneak (default: shift), anything around where you are looking at will instantly melt. Since this is a more favorable state for these things, they will never re-freeze unless they would otherwise by nature or some other bending ability. Additionally, if you tap sneak while targeting water with FreezeMelt, it will evaporate water around that block that is above sea level." + Range: 20 + Radius: 5 + Plantbending: + RegrowTime: 180000 + Surge: + Enabled: true + Description: "This ability has two distinct features. If you sneak to select a source block, you can then click in a direction and a large wave will be launched in that direction. If you sneak again while the wave is en route, the wave will freeze the next target it hits. If, instead, you click to select a source block, you can hold sneak to form a wall of water at your cursor location. Click to shift between a water wall and an ice wall. Release sneak to dissipate it." + Wave: + Radius: 3 + HorizontalPush: 1 + VerticalPush: 0.2 + Range: 20 + Wall: + Range: 5 + Radius: 2 + VerticalPush: 0.2 + Torrent: + Enabled: true + Description: "Torrent is one of the strongest moves in a waterbender's arsenal. To use, first click a source block to select it; then hold shift to begin streaming the water around you. Water flowing around you this way will damage and knock back nearby enemies and projectiles. If you release shift during this, you will create a large wave that expands outwards from you, launching anything in its path back. Instead, if you click you release the water and channel it to flow towards your cursor. Anything caught in the blast will be tossed about violently and take damage. Finally, if you click again when the water is torrenting, it will freeze the area around it when it is obstructed." + Damage: 2 + DeflectDamage: 1 + Range: 25 + Wave: + Radius: 15 + Knockback: 1.5 + Height: 1 + WaterBubble: + Enabled: true + Description: "To use, the bender must merely have the ability selected. All water around the user in a small bubble will vanish, replacing itself once the user either gets too far away or selects a different ability." + Radius: 7 + WaterManipulation: + Enabled: true + Description: "To use, place your cursor over a waterbendable object and tap sneak (default: shift). Smoke will appear where you've selected, indicating the origin of your ability. After you have selected an origin, simply left-click in any direction and you will see your water spout off in that direction, slicing any creature in its path. If you look towards a creature when you use this ability, it will target that creature. A collision from Water Manipulation both knocks the target back and deals some damage. Alternatively, if you have the source selected and tap shift again, you will be able to control the water more directly." + Damage: 3.0 + Range: 20 + Speed: 35 + Push: .3 + Cooldown: 1000 + WaterSpout: + Enabled: true + Description: "This ability provides a Waterbender with a new means of transportation. To use, simply left click while in or over water to spout water up beneath you, experiencing controlled levitation. Left clicking again while the spout is active will cause it to disappear. Alternatively, tapping a Waterbendable block while not in Water will select a water block as a source, from there, you can tap sneak (Default:Shift) to channel the Water around you. Releasing the sneak will create a wave allowing you a quick burst of controlled transportation. While riding the wave you may press sneak to cause the wave to disappear." + Height: 20 + Wave: + Enabled: true + Range: 6 + ChargeTime: 1000 + FlightTime: 2000 + Speed: 1.2 + WaterCombo: + Enabled: true + IceWave: + Damage: 3 + Cooldown: 6000 + IceBullet: + Damage: 1.5 + Radius: 2.5 + Range: 12 + MaxShots: 30 + AnimationSpeed: 1 + ShootTime: 5000 + Cooldown: 10000 + WaterArms: + Enabled: true + Description: |- + One of the most diverse moves in a Waterbender's arsenal, this move creates tendrils of water from the players arms to emulate their actual arms. Each water arms mode will be binded to a slot, switch slots to change mode. To deactive the arms, hold Sneak and Double Left-Click. + Pull - Use your Arms to pull blocks, items, mobs or even players towards you! + Punch - An offensive attack, harming players or mobs! + Grapple - Scale walls and speed across battlefields, using your Arms as a grappling hook! + Grab - Grab an entity with your arm, and swing them about! + Freeze - Use your Arms to fire small blasts of ice in any direction! + Spear - Throw your Arms in any direction, freezing whatever it hits! + SneakMessage: 'Active Ability:' + Arms: + InitialLength: 4 + SourceGrabRange: 4 + MaxAttacks: 10 + MaxAlternateUsage: 50 + MaxIceShots: 5 + Cooldown: 20000 + AllowPlantSource: true + Lightning: + Enabled: true + Damage: 10.0 + KillUser: false + Cooldowns: + UsageCooldownEnabled: false + UsageCooldown: 200 + AllowSpectatorUse: false + Whip: + MaxLength: 20 + MaxLengthWeak: 12 + NightAugments: + MaxLength: + Normal: 24 + FullMoon: 30 + Punch: + PunchDamage: 3.0 + Grapple: + RespectRegions: false + Grab: + HoldTime: 10000 + Freeze: + Range: 20 + Damage: 2.0 + Spear: + Range: 40 + Damage: 4.0 + DamageEnabled: true + Sphere: 2 + Duration: 6000 + Length: 18 + NightAugments: + Range: + Normal: 45 + FullMoon: 60 + Sphere: + Normal: 3 + FullMoon: 6 + Duration: + Normal: 7000 + FullMoon: 12000 + Earth: + Passive: + Duration: 2500 + Catapult: + Enabled: true + Description: "To use, left-click while looking in the direction you want to be launched. A pillar of earth will jut up from under you and launch you in that direction - if and only if there is enough earth behind where you're looking to launch you. Skillful use of this ability takes much time and work, and it does result in the death of certain gung-ho earthbenders. if you plan to use this ability, be sure you've read about your passive ability you innately have as an earthbender." + Length: 7 + Speed: 12 + Push: 5 + Collapse: + Enabled: true + Description: "To use, simply left-click an earthbendable block. That block and the earthbendable blocks above it will be shoved back into the earth below, if they can. This ability does have the capacity to trap something inside of it, although it is incredibly difficult to do so. Additionally, press sneak with this ability to affect an area around your targeted location - all earth that can be moved downwards will be moved downwards. This ability is especially risky or deadly in caves, depending on the earthbender's goal and technique." + Range: 20 + Radius: 7 + Speed: 8 + EarthArmor: + Enabled: true + Description: "This ability encases the earthbender in temporary armor. To use, click on a block that is earthbendable. If there is another block under it that is earthbendable, the block will fly to you and grant you temporary armor and damage reduction. This ability has a long cooldown." + Duration: 10000 + Strength: 2 + Cooldown: 17500 + EarthBlast: + Enabled: true + Description: "To use, place your cursor over an earthbendable object and tap sneak (default: shift). The object will temporarily turn to stone, indicating that you have it focused as the source for your ability. After you have selected an origin (you no longer need to be sneaking), simply left-click in any direction and you will see your object launch off in that direction, smashing into any creature in its path. If you look towards a creature when you use this ability, it will target that creature. A collision from Earth Blast both knocks the target back and deals some damage. You cannot have multiple of these abilities flying at the same time." + CanHitSelf: false + PrepareRange: 7 + Range: 20 + Speed: 35 + Revert: true + Damage: 4 + Push: 0.3 + EarthGrab: + Enabled: true + Description: "To use, simply left-click while targeting a creature within range. This ability will erect a circle of earth to trap the creature in." + Range: 15 + EarthTunnel: + Enabled: true + Description: "Earth Tunnel is a completely utility ability for earthbenders. To use, simply sneak (default: shift) in the direction you want to tunnel. You will slowly begin tunneling in the direction you're facing for as long as you sneak or if the tunnel has been dug long enough. This ability will be interrupted if it hits a block that cannot be earthbent." + MaxRadius: 1 + Range: 10 + Radius: 0.25 + Revert: true + Interval: 30 + Extraction: + Enabled: true + Description: "This ability allows metalbenders to extract the minerals from ore blocks. To use, simply tap sneak while looking at an ore block with metal in it (iron, gold, etc) and the ore will be extracted and drop in front of you. This ability has a small chance of doubling or tripling the loot. This ability has a short cooldown." + Cooldown: 10000 + TripleLootChance: 15 + DoubleLootChance: 40 + MetalClips: + Enabled: true + LavaFlow: + Enabled: true + Description: 'This ability allows an Earthbender to create lava using the Earth + around them. To use, simply hold sneak (Default: Shift) to create a lava moat + that surrounds you, press sneak again to remove the moat. Left click an Earthbendable + block to create a pool of lava after a small delay. Additionally, you can + left click at any time to turn lava back into its original state -- Earth.' + ShiftCooldown: 16000 + ClickLavaCooldown: 10000 + ClickLandCooldown: 500 + ShiftCleanupDelay: 10000 + ClickLavaCleanupDelay: 7000 + ClickLandCleanupDelay: 20000 + ClickRange: 10.0 + ShiftRadius: 8.0 + ClickRadius: 5.0 + ShiftPlatformRadius: 1.5 + ClickLavaCreateSpeed: 0.05 + ClickLandCreateSpeed: 0.1 + ShiftFlowSpeed: 0.1 + ShiftRemoveSpeed: 3.0 + ClickLavaStartDelay: 1500 + ClickLandStartDelay: 0 + UpwardFlow: 2 + DownwardFlow: 4 + AllowNaturalFlow: false + ParticleDensity: 0.33 + EarthSmash: + Enabled: true + Description: 'To raise an EarthSmash hold sneak (default: shift) for approximately + 1.5 seconds, then release while aiming at dirt. To grab the EarthSmash aim + at the center and hold sneak, the EarthSmash will follow your mouse. You can + shoot the EarthSmash by grabbing onto it and left clicking. To ride the EarthSmash + simply hop ontop of it and hold sneak while aiming in the direction that you + wish to go. Another way to ride an EarthSmash is to grab it with sneak and + then right click it. Use EarthSmash as a defensive shield, a powerful attack, + or an advanced means of transportation.' + AllowGrab: true + AllowShooting: true + AllowFlight: true + GrabRange: 10 + ChargeTime: 1200 + Cooldown: 0 + ShotRange: 30 + Damage: 6 + Knockback: 3.5 + Knockup: 0.15 + FlightSpeed: 0.72 + FlightTimer: 3000 + RemoveTimer: 30000 + 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 + Shockwave: + Enabled: true + Description: "This is one of the most powerful moves in the earthbender's arsenal. To use, you must first charge it by holding sneak (default: shift). Once charged, you can release sneak to create an enormous shockwave of earth, disturbing all earth around you and expanding radially outwards. Anything caught in the shockwave will be blasted back and dealt damage. If you instead click while charged, the disruption is focused in a cone in front of you. Lastly, if you fall from a great enough height with this ability selected, you will automatically create a shockwave." + ChargeTime: 2500 + FallThreshold: 10 + Damage: 5 + Knockback: 1.1 + Range: 15 + Tremorsense: + Enabled: true + Description: "This is a pure utility ability for earthbenders. If you are in an area of low-light and are standing on top of an earthbendable block, this ability will automatically turn that block into glowstone, visible *only by you*. If you lose contact with a bendable block, the light will go out as you have lost contact with the earth and cannot 'see' until you can touch earth again. Additionally, if you click with this ability selected, smoke will appear above nearby earth with pockets of air beneath them." + MaxDepth: 10 + Radius: 5 + LightThreshold: 7 + Cooldown: 1000 + Fire: + Blaze: + Enabled: true + Description: "To use, simply click in any direction. An arc of fire will flow from your location, igniting anything in its path. Additionally, tap sneak to engulf the area around you in roaring flames." + ArcOfFire: + Arc: 20 + Range: 9 + RingOfFire: + Range: 7 + Combustion: + Enabled: true + Description: "Combustion is a powerful ability only known by a few skilled Firebenders. It allows the bender to Firebend with their mind, concentrating energy to create a powerful blast. To use, simply tap sneak (Default: Shift) to launch the blast. This technique is highly destructive and very effective, it also comes with a long cooldown." + Cooldown: 15000 + BreakBlocks: false + Power: 1.0 + Damage: 5 + Radius: 4 + Range: 20 + Speed: 25 + FireBlast: + Enabled: true + Description: "FireBlast is the most fundamental technique of a firebender. To use, simply left-click in a direction. A blast of fire will be created at your fingertips. If this blast contacts an enemy, it will dissipate and engulf them in flames, doing additional damage and knocking them back slightly. If the blast hits terrain, it will ignite the nearby area. Additionally, if you hold sneak, you will charge up the fireblast. If you release it when it's charged, it will instead launch a powerful fireball that explodes on contact." + Speed: 15 + Range: 15 + Radius: 2 + Push: 0.3 + Damage: 2 + Cooldown: 1500 + Dissipate: false + Charged: + ChargeTime: 2000 + Damage: 4 + DamageRadius: 6 + Power: 1 + Range: 20 + FireBurst: + Enabled: true + Description: "FireBurst is a very powerful firebending ability. To use, press and hold sneak to charge your burst. Once charged, you can either release sneak to launch a cone-shaped burst of flames in front of you, or click to release the burst in a sphere around you." + ChargeTime: 2500 + Damage: 3 + Range: 15 + FireJet: + Enabled: true + 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 controlled flight for a short time. This ability can be used mid-air to prevent falling to your death, but on the ground it can only be used if standing on a block that's ignitable (e.g. not snow or water)." + Speed: 0.7 + Duration: 1500 + Cooldown: 6000 + IsAvatarStateToggle: true + FireShield: + Enabled: true + Description: "FireShield is a basic defensive ability. Clicking with this ability selected will create a small disc of fire in front of you, which will block most attacks and bending. Alternatively, pressing and holding sneak creates a very small shield of fire, blocking most attacks. Creatures that contact this fire are ignited." + Radius: 3 + DiscRadius: 1.5 + Duration: 1000 + 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 + Illumination: + Enabled: true + Description: "This ability gives firebenders a means of illuminating the area. It is a toggle - clicking will create a torch that follows you around. The torch will only appear on objects that are ignitable and can hold a torch (e.g. not leaves or ice). If you get too far away from the torch, it will disappear, but will reappear when you get on another ignitable block. Clicking again dismisses this torch." + Range: 5 + Lightning: + Enabled: true + Description: "Hold sneak while selecting this ability to charge up a lightning strike. once charged, release sneak to discharge the lightning to the targeted location." + Damage: 6 + Range: 13.0 + ChargeTime: 3500 + Cooldown: 0 + StunChance: 0.2 + StunDuration: 30.0 + MaxArcAngle: 30 + SubArcChance: 0.025 + ChainArcRange: 6.0 + ChainArcChance: 0.5 + MaxChainArcs: 2 + WaterArcs: 4 + WaterArcRange: 12.0 + SelfHitWater: true + SelfHitClose: true + ArcOnIce: false + WallOfFire: + Enabled: true + Description: "To use this ability, click at a location. A wall of fire will appear at this location, igniting enemies caught in it and blocking projectiles." + Range: 4 + Height: 4 + Width: 4 + Duration: 5000 + Damage: 2 + Cooldown: 7500 + Interval: 500 + FireCombo: + Enabled: true + FireKick: + Range: 7.0 + Damage: 3.0 + Cooldown: 2000 + FireSpin: + Range: 7 + Damage: 3.0 + Knockback: 3.2 + Cooldown: 2000 + FireWheel: + Range: 20.0 + Damage: 4.0 + Speed: 0.55 + Cooldown: 200 + JetBlast: + Speed: 1.2 + Cooldown: 6000 + JetBlaze: + Speed: 1.1 + Damage: 3 + Cooldown: 6000 + Chi: + Passive: + FallReductionFactor: 0.5 + Speed: 1 + Jump: 2 + BlockChi: + Duration: 2500 + DodgeChance: 25 + AcrobatStance: + Enabled: true + Description: "AcrobatStance gives a Chiblocker a higher probability of blocking a Bender's Chi while granting them a Speed and Jump boost. It also increases the rate at which the hunger bar depletes. To use, simply left click. Left clicking again will de-activate the stance." + ChiBlockBoost: 0.1 + HighJump: + Enabled: true + Description: "To use this ability, simply click. You will jump quite high. This ability has a short cooldown." + Cooldown: 10000 + Height: 1 + Paralyze: + Enabled: true + Description: "Paralyzes the target, making them unable to do anything for a short period of time. This ability has a long cooldown." + Cooldown: 15000 + Duration: 2000 + RapidPunch: + Enabled: true + Description: "This ability allows the chiblocker to punch rapidly in a short period. To use, simply punch. This has a short cooldown." + Damage: 1 + Distance: 4 + Cooldown: 15000 + Punches: 4 + Smokescreen: + Enabled: true + Description: "Smokescren, if used correctly, can serve as a defensive and offensive ability for Chiblockers. To use, simply left click and you will toss out a Smoke Bomb. When the bomb hits the ground, it will explode and give all players within a small radius of the explosion temporary blindness, allowing you to either get away, or move in for the kill. This ability has a long cooldown." + Cooldown: 50000 + Radius: 4 + Duration: 15 + WarriorStance: + Enabled: true + Description: "WarriorStance gives a Chiblocker increased damage but makes them a tad more vulnerable. To activate, simply left click." + Strength: 1 + Resistance: -1 +Storage: + engine: sqlite + MySQL: + host: localhost + port: 3306 + pass: '' + db: minecraft + user: root debug: false \ No newline at end of file diff --git a/src/plugin.yml b/src/plugin.yml index 6dc752da..ea31c1bb 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -31,6 +31,9 @@ permissions: bending.command.invincible: true bending.admin.debug: true bending.admin.remove: true + bending.ability.WaterArms.Grab: true + bending.ability.WaterArms.Freeze: true + bending.ability.WaterArms.Spear: true bending.player: default: true description: Grants access to most abilities and basic commands. @@ -95,6 +98,10 @@ permissions: bending.water.passive: true bending.water.icebending: true bending.water.healing: true + bending.ability.WaterArms: true + bending.ability.WaterArms.Pull: true + bending.ability.WaterArms.Punch: true + bending.ability.WaterArms.Grapple: true bending.earth: default: true description: Grants access to all Earthbending abilities.