diff --git a/Dev Builds/Korra.jar b/Dev Builds/Korra.jar index b8d9018f..8bd745cf 100644 Binary files a/Dev Builds/Korra.jar and b/Dev Builds/Korra.jar differ diff --git a/src/com/projectkorra/ProjectKorra/ConfigManager.java b/src/com/projectkorra/ProjectKorra/ConfigManager.java index 166606f0..54bec172 100644 --- a/src/com/projectkorra/ProjectKorra/ConfigManager.java +++ b/src/com/projectkorra/ProjectKorra/ConfigManager.java @@ -51,6 +51,10 @@ public class ConfigManager { plugin.getConfig().addDefault("Properties.GlobalCooldown", 500); plugin.getConfig().addDefault("Properties.SeaLevel", 62); + 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); diff --git a/src/com/projectkorra/ProjectKorra/CustomEvents/PlayerGrappleEvent.java b/src/com/projectkorra/ProjectKorra/CustomEvents/PlayerGrappleEvent.java new file mode 100644 index 00000000..358891f6 --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/CustomEvents/PlayerGrappleEvent.java @@ -0,0 +1,62 @@ +package com.projectkorra.ProjectKorra.CustomEvents; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; + +public class PlayerGrappleEvent extends Event implements Cancellable { + + + public static final HandlerList handlers = new HandlerList(); + private Player player; + private Entity entity; + private Location pullLocation; + private ItemStack hookItem; + private boolean cancelled = false; + + public PlayerGrappleEvent(Player p, Entity e, Location l) { + player = p; + entity = e; + pullLocation = l; + hookItem = p.getItemInHand(); + } + + public Player getPlayer() { + return player; + } + + public Entity getPulledEntity() { + return entity; + } + + public Location getPullLocation() { + return pullLocation; + } + + public ItemStack getHookItem() { + return hookItem; + } + + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean set) { + cancelled = set; + } + +} diff --git a/src/com/projectkorra/ProjectKorra/PKListener.java b/src/com/projectkorra/ProjectKorra/PKListener.java index 353e3a1e..10725f4d 100644 --- a/src/com/projectkorra/ProjectKorra/PKListener.java +++ b/src/com/projectkorra/ProjectKorra/PKListener.java @@ -1,6 +1,7 @@ package com.projectkorra.ProjectKorra; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import org.bukkit.ChatColor; @@ -9,6 +10,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Entity; +import org.bukkit.entity.Item; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -40,6 +42,7 @@ import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryType.SlotType; import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.PlayerAnimationEvent; +import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerMoveEvent; @@ -51,6 +54,8 @@ import org.bukkit.potion.PotionEffectType; import org.bukkit.util.Vector; import com.projectkorra.ProjectKorra.Ability.AvatarState; +import com.projectkorra.ProjectKorra.CustomEvents.PlayerGrappleEvent; +import com.projectkorra.ProjectKorra.Utilities.GrapplingHookAPI; import com.projectkorra.ProjectKorra.airbending.AirBlast; import com.projectkorra.ProjectKorra.airbending.AirBubble; import com.projectkorra.ProjectKorra.airbending.AirBurst; @@ -110,7 +115,65 @@ public class PKListener implements Listener { public PKListener(ProjectKorra plugin) { this.plugin = plugin; } + + public static HashMap noFallEntities = new HashMap(); // Grappling Hooks + public static HashMap noGrapplePlayers = new HashMap(); // Grappling Hooks + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onPlayerGrapple(PlayerGrappleEvent event) { + if (event.isCancelled()) return; + if (!plugin.getConfig().getBoolean("Properties.CustomItems.GrapplingHook.Enable")) return; + + Player player = event.getPlayer(); + if (!Methods.isBender(player.getName(), Element.Chi) && (!Methods.isBender(player.getName(), Element.Earth) || !Methods.canMetalbend(player))) { + event.setCancelled(true); + return; + } + if (Paralyze.isParalyzed(player) || Bloodbending.isBloodbended(player)) { + event.setCancelled(true); + } + + event.getHookItem().setDurability((short) - 10); + if (noGrapplePlayers.containsKey(player.getName())) { + return; + } + + Entity e = event.getPulledEntity(); + Location loc = event.getPullLocation(); + + if (player.equals(e)) { + if (player.getLocation().distance(loc) < 3) { // Too close + GrapplingHookAPI.pullPlayerSlightly(player, loc); + } else { + GrapplingHookAPI.pullEntityToLocation(player, loc); + } + + if (GrapplingHookAPI.addUse(player, event.getHookItem())) { + GrapplingHookAPI.playGrappleSound(player.getLocation()); + } + GrapplingHookAPI.addPlayerCooldown(player, 100); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void fishEvent(PlayerFishEvent event) { + Player player = event.getPlayer(); + if (GrapplingHookAPI.isGrapplingHook(player.getItemInHand())) { + if (event.getState() == PlayerFishEvent.State.IN_GROUND) { + Location loc = event.getHook().getLocation(); + for (Entity ent: event.getHook().getNearbyEntities(1.5, 1, 1.5)) { + if (ent instanceof Item) { + PlayerGrappleEvent e = new PlayerGrappleEvent(player, ent, player.getLocation()); + plugin.getServer().getPluginManager().callEvent(e); + return; + } + } + + PlayerGrappleEvent e = new PlayerGrappleEvent(player, player, loc); + plugin.getServer().getPluginManager().callEvent(e); + } + } + } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onPlayerInteraction(PlayerInteractEvent event) { Player player = event.getPlayer(); diff --git a/src/com/projectkorra/ProjectKorra/ProjectKorra.java b/src/com/projectkorra/ProjectKorra/ProjectKorra.java index 1bd003dc..b9d1a4e0 100644 --- a/src/com/projectkorra/ProjectKorra/ProjectKorra.java +++ b/src/com/projectkorra/ProjectKorra/ProjectKorra.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import com.projectkorra.ProjectKorra.Ability.AbilityModuleManager; +import com.projectkorra.ProjectKorra.Utilities.CraftingRecipes; public class ProjectKorra extends JavaPlugin { @@ -51,6 +52,8 @@ public class ProjectKorra extends JavaPlugin { } Methods.deserializeFile(); + + new CraftingRecipes(this); } @Override diff --git a/src/com/projectkorra/ProjectKorra/Utilities/CraftingRecipes.java b/src/com/projectkorra/ProjectKorra/Utilities/CraftingRecipes.java new file mode 100644 index 00000000..2602366b --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/Utilities/CraftingRecipes.java @@ -0,0 +1,37 @@ +package com.projectkorra.ProjectKorra.Utilities; + +import org.bukkit.Material; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.inventory.ShapedRecipe; + +import com.projectkorra.ProjectKorra.ProjectKorra; + +public class CraftingRecipes { + + static ProjectKorra plugin; + + public CraftingRecipes(ProjectKorra plugin) { + CraftingRecipes.plugin = plugin; + registerRecipes(); + } + + static FileConfiguration config = ProjectKorra.plugin.getConfig(); + + public static void registerRecipes() { + if (config.getBoolean("Properties.CustomItems.GrapplingHook.Enable")) { + plugin.getServer().addRecipe(ironHookRecipe); + plugin.getServer().addRecipe(goldHookRecipe); + } + } + + static ShapedRecipe ironHookRecipe = new ShapedRecipe(GrapplingHookAPI.createHook(config.getInt("Properties.CustomItems.GrapplingHook.IronUses"))) + .shape(" **", " &*", " ") + .setIngredient('*', Material.IRON_INGOT) + .setIngredient('&', Material.FISHING_ROD); + + static ShapedRecipe goldHookRecipe = new ShapedRecipe(GrapplingHookAPI.createHook(config.getInt("Properties.CustomItems.GrapplingHook.GoldUses"))) + .shape(" **", " &*", " ") + .setIngredient('*', Material.GOLD_INGOT) + .setIngredient('&', Material.FISHING_ROD); + +} diff --git a/src/com/projectkorra/ProjectKorra/Utilities/GrapplingHookAPI.java b/src/com/projectkorra/ProjectKorra/Utilities/GrapplingHookAPI.java new file mode 100644 index 00000000..ff6175d1 --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/Utilities/GrapplingHookAPI.java @@ -0,0 +1,162 @@ +package com.projectkorra.ProjectKorra.Utilities; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.PKListener; +import com.projectkorra.ProjectKorra.ProjectKorra; + +public class GrapplingHookAPI { + + public static ItemStack createHook(int uses) { + ItemStack is = new ItemStack(Material.FISHING_ROD); + ItemMeta im = is.getItemMeta(); + im.setDisplayName(ChatColor.GOLD + "Grappling Hook"); + ArrayList lore = new ArrayList(); + lore.add(ChatColor.GRAY + "Uses Left: " + ChatColor.GREEN + uses); + im.setLore(lore); + is.setItemMeta(im); + return is; + } + + public static boolean isGrapplingHook(ItemStack is) { + ItemMeta im = is.getItemMeta(); + if (is.getType() == Material.FISHING_ROD && im.getDisplayName() != null && im.getDisplayName().equals(ChatColor.GOLD + "Grappling Hook")) { + return true; + } + return false; + } + + public static int getUses(ItemStack is) { + ItemMeta im = is.getItemMeta(); + String usesLine = im.getLore().get(0); + String uses = usesLine.substring(usesLine.indexOf("a") + 1, usesLine.length()); + + if (isInteger(uses)) { + return Integer.parseInt(uses); + } + else + return 0; + } + + public static boolean playerOnCooldown(Player player) { + if (PKListener.noGrapplePlayers.containsKey(player.getName())) return true; + return false; + } + + public static void removePlayerCooldown(Player player) { + if (PKListener.noGrapplePlayers.containsKey(player.getName())) { + PKListener.noGrapplePlayers.remove(player.getName()); + } + } + public static void addPlayerCooldown(final Player player, int seconds) { + if (PKListener.noGrapplePlayers.containsKey(player.getName())) { + Bukkit.getServer().getScheduler().cancelTask(PKListener.noGrapplePlayers.get(player.getName())); + } + + int taskId = ProjectKorra.plugin.getServer().getScheduler().scheduleSyncDelayedTask(ProjectKorra.plugin, new Runnable() { + public void run() { + removePlayerCooldown(player); + } + }, (100)); + + PKListener.noGrapplePlayers.put(player.getName(), taskId); + } + + public static void setUses(ItemStack is, int uses) { + ItemMeta im = is.getItemMeta(); + List lore = new ArrayList(); + + lore.add(ChatColor.GRAY+"Uses Left: " + ChatColor.GREEN + uses); + im.setLore(lore); + is.setItemMeta(im); + } + + public static boolean addUse(Player player, ItemStack hook) { + if (player.getGameMode() == GameMode.CREATIVE) return true; + + ItemMeta im = hook.getItemMeta(); + String usesLine = im.getLore().get(0); + String uses = usesLine.substring(usesLine.indexOf("a")+1, usesLine.length()); + + if (isInteger(uses) == false) { + player.setItemInHand(new ItemStack(Material.AIR)); + player.getWorld().playSound(player.getLocation(), Sound.ITEM_BREAK, 10f, 1f); + return false; + } else { + int currentUses = Integer.parseInt(uses); + currentUses--; + + if (currentUses == 0) { + player.setItemInHand(new ItemStack(Material.AIR)); + player.getWorld().playSound(player.getLocation(), Sound.ITEM_BREAK, 10f, 1f); + return false; + } else { + ArrayList lore = new ArrayList(); + lore.add(ChatColor.GRAY + "Uses Left: " + ChatColor.GREEN + currentUses); + im.setLore(lore); + hook.setItemMeta(im); + } + } + return true; + } + + public static void playGrappleSound(Location loc) { + loc.getWorld().playSound(loc, Sound.MAGMACUBE_JUMP, 10f, 1f); + } + + private static boolean isInteger(String s) { + try { + Integer.parseInt(s); + } catch (NumberFormatException e) { + return false; + } + return true; + } + + public static void pullPlayerSlightly(Player p, Location loc) { + if (loc.getY() > p.getLocation().getY()) { + p.setVelocity(new Vector(0, 0.25, 0)); + return; + } + + Location playerLoc = p.getLocation(); + + Vector vector = loc.toVector().subtract(playerLoc.toVector()); + p.setVelocity(vector); + } + + public static void pullEntityToLocation(final Entity e, Location loc) { + Location entityLoc = e.getLocation(); + + entityLoc.setY(entityLoc.getY() + 0.5); + e.teleport(entityLoc); + + double g = -0.08; + double d = loc.distance(entityLoc); + double t = d; + double v_x = (1.0+0.07*t) * (loc.getX()-entityLoc.getX())/t; + double v_y = (1.0+0.03*t) * (loc.getY()-entityLoc.getY())/t -0.5*g*t; + double v_z = (1.0+0.07*t) * (loc.getZ()-entityLoc.getZ())/t; + + Vector v = e.getVelocity(); + v.setX(v_x); + v.setY(v_y); + v.setZ(v_z); + e.setVelocity(v); + } + + +} \ No newline at end of file diff --git a/src/config.yml b/src/config.yml index 824172b6..bed886f2 100644 --- a/src/config.yml +++ b/src/config.yml @@ -1,6 +1,11 @@ Properties: GlobalCooldown: 500 SeaLevel: 62 + CustomItems: + GrapplingHook: + Enable: true + IronUses: 25 + GoldUses: 50 Chat: Format: ": " Enable: true diff --git a/src/plugin.yml b/src/plugin.yml index 977deb8d..3b40903f 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -1,6 +1,6 @@ name: ProjectKorra author: ProjectKorra -version: 1.2.0 BETA 8 +version: 1.2.0 BETA 9 main: com.projectkorra.ProjectKorra.ProjectKorra commands: projectkorra: