diff --git a/src/com/projectkorra/ProjectKorra/ComboManager.java b/src/com/projectkorra/ProjectKorra/ComboManager.java new file mode 100644 index 00000000..cd9517a5 --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/ComboManager.java @@ -0,0 +1,242 @@ +package com.projectkorra.ProjectKorra; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import com.projectkorra.ProjectKorra.firebending.FireCombo; + +public class ComboManager +{ + public static enum ClickType{ + SHIFTDOWN, SHIFTUP, LEFTCLICK, RIGHTCLICK + } + private static final long CLEANUP_DELAY = 10000; + public static ConcurrentHashMap> recentlyUsedAbilities = new ConcurrentHashMap>(); + public static ArrayList comboAbilityList = new ArrayList(); + + public ComboManager() + { + ArrayList fireKick = new ArrayList(); + fireKick.add(new AbilityInformation("FireBlast",ClickType.LEFTCLICK)); + fireKick.add(new AbilityInformation("FireBlast",ClickType.LEFTCLICK)); + fireKick.add(new AbilityInformation("FireBlast",ClickType.SHIFTDOWN)); + fireKick.add(new AbilityInformation("FireBlast",ClickType.LEFTCLICK)); + comboAbilityList.add(new ComboAbility("FireKick",fireKick,FireCombo.class)); + + ArrayList fireSpin = new ArrayList(); + fireSpin.add(new AbilityInformation("FireBlast",ClickType.LEFTCLICK)); + fireSpin.add(new AbilityInformation("FireBlast",ClickType.LEFTCLICK)); + fireSpin.add(new AbilityInformation("FireShield",ClickType.LEFTCLICK)); + fireSpin.add(new AbilityInformation("FireShield",ClickType.SHIFTDOWN)); + fireSpin.add(new AbilityInformation("FireShield",ClickType.SHIFTUP)); + comboAbilityList.add(new ComboAbility("FireSpin",fireSpin,FireCombo.class)); + + ArrayList jetBlast = new ArrayList(); + jetBlast.add(new AbilityInformation("FireJet",ClickType.SHIFTDOWN)); + jetBlast.add(new AbilityInformation("FireJet",ClickType.SHIFTUP)); + jetBlast.add(new AbilityInformation("FireJet",ClickType.SHIFTDOWN)); + jetBlast.add(new AbilityInformation("FireJet",ClickType.SHIFTUP)); + jetBlast.add(new AbilityInformation("FireShield",ClickType.SHIFTDOWN)); + jetBlast.add(new AbilityInformation("FireShield",ClickType.SHIFTUP)); + jetBlast.add(new AbilityInformation("FireJet",ClickType.LEFTCLICK)); + comboAbilityList.add(new ComboAbility("JetBlast",jetBlast,FireCombo.class)); + + ArrayList jetBlaze = new ArrayList(); + jetBlaze.add(new AbilityInformation("FireJet",ClickType.SHIFTDOWN)); + jetBlaze.add(new AbilityInformation("FireJet",ClickType.SHIFTUP)); + jetBlaze.add(new AbilityInformation("FireJet",ClickType.SHIFTDOWN)); + jetBlaze.add(new AbilityInformation("FireJet",ClickType.SHIFTUP)); + jetBlaze.add(new AbilityInformation("Blaze",ClickType.SHIFTDOWN)); + jetBlaze.add(new AbilityInformation("Blaze",ClickType.SHIFTUP)); + jetBlaze.add(new AbilityInformation("FireJet",ClickType.LEFTCLICK)); + comboAbilityList.add(new ComboAbility("JetBlaze",jetBlaze,FireCombo.class)); + + ArrayList fireWheel = new ArrayList(); + fireWheel.add(new AbilityInformation("FireShield",ClickType.SHIFTDOWN)); + fireWheel.add(new AbilityInformation("FireShield",ClickType.RIGHTCLICK)); + fireWheel.add(new AbilityInformation("FireShield",ClickType.RIGHTCLICK)); + fireWheel.add(new AbilityInformation("Blaze",ClickType.SHIFTUP)); + comboAbilityList.add(new ComboAbility("FireWheel",fireWheel,FireCombo.class)); + + startCleanupTask(); + } + public static void addComboAbility(Player player, ClickType type) + { + String abilityName = Methods.getBoundAbility(player); + if(abilityName == null) + return; + + AbilityInformation info = new AbilityInformation(abilityName,type,System.currentTimeMillis()); + addRecentAbility(player,info); + + ComboAbility comboAbil = checkForValidCombo(player); + if(comboAbil == null) + return; + + if(comboAbil.getComboType().equals(FireCombo.class)) + new FireCombo(player, comboAbil.getName()); + } + + public static class AbilityInformation + { + private String abilityName; + private ClickType clickType; + private long time; + public AbilityInformation(String name, ClickType type, long time){ + this.abilityName = name; + this.clickType = type; + this.time = time; + } + public AbilityInformation(String name, ClickType type){ + this(name,type,0); + } + public String getAbilityName() { + return abilityName; + } + public void setAbilityName(String abilityName) { + this.abilityName = abilityName; + } + public ClickType getClickType() { + return clickType; + } + public void setClickType(ClickType clickType) { + this.clickType = clickType; + } + public long getTime() { + return time; + } + public void setTime(long time) { + this.time = time; + } + public String toString() + { + return abilityName + " " + clickType + " " + time; + } + public boolean equalsWithoutTime(AbilityInformation info) + { + return this.getAbilityName().equals(info.getAbilityName()) + && this.getClickType().equals(info.getClickType()); + } + } + public static class ComboAbility + { + private String name; + private ArrayList abilities; + private Object comboType; + public ComboAbility(String name, ArrayList abilities, Object comboType){ + this.name = name; + this.abilities = abilities; + this.comboType = comboType; + } + 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 Object getComboType() { + return comboType; + } + public void setComboType(Object comboType) { + this.comboType = comboType; + } + public String toString(){ + return name; + } + } + + public static void addRecentAbility(Player player, AbilityInformation info) + { + ArrayList list; + String name = player.getName(); + if(recentlyUsedAbilities.containsKey(name)){ + list = recentlyUsedAbilities.get(name); + recentlyUsedAbilities.remove(player); + } + else + list = new ArrayList(); + list.add(info); + recentlyUsedAbilities.put(name, list); + } + public static ArrayList getRecentlyUsedAbilities(Player player, int amount) + { + String name = player.getName(); + if(!recentlyUsedAbilities.containsKey(name)) + return new ArrayList(); + + ArrayList list = recentlyUsedAbilities.get(name); + if(list.size() < amount) + return new ArrayList(list); + + ArrayList tempList = new ArrayList(); + for(int i = 0; i < amount; i++) + tempList.add(0,list.get(list.size() - 1 - i)); + return tempList; + } + public static ComboAbility checkForValidCombo(Player player) + { + ArrayList playerCombo = getRecentlyUsedAbilities(player,8); + for(ComboAbility customAbility : comboAbilityList) + { + ArrayList abilityCombo = customAbility.getAbilities(); + int size = abilityCombo.size(); + + if(playerCombo.size() < size) + continue; + + boolean isValid = true; + for(int i = 1; i <= size; i++) + { + if(!playerCombo.get(playerCombo.size() - i) + .equalsWithoutTime(abilityCombo.get(abilityCombo.size() - i))) + { + isValid = false; + break; + } + } + if(isValid) + return customAbility; + } + return null; + } + public static void startCleanupTask(){ + new BukkitRunnable(){ + public void run(){ + cleanupOldCombos(); + } + }.runTaskTimer(ProjectKorra.plugin, 0, CLEANUP_DELAY); + } + public static void cleanupOldCombos() + { + Enumeration keys = recentlyUsedAbilities.keys(); + while(keys.hasMoreElements()) + { + String name = keys.nextElement(); + ArrayList combos = recentlyUsedAbilities.get(name); + recentlyUsedAbilities.remove(name); + for(int i = 0; i < combos.size(); i++) + { + AbilityInformation info = combos.get(i); + if(System.currentTimeMillis() - info.getTime() > CLEANUP_DELAY){ + combos.remove(i); + i--; + } + } + + if(combos.size() > 0) + recentlyUsedAbilities.put(name, combos); + } + } +} + diff --git a/src/com/projectkorra/ProjectKorra/Commands.java b/src/com/projectkorra/ProjectKorra/Commands.java index 6b922522..cc557efe 100644 --- a/src/com/projectkorra/ProjectKorra/Commands.java +++ b/src/com/projectkorra/ProjectKorra/Commands.java @@ -797,7 +797,7 @@ public class Commands { if (p.getName().equalsIgnoreCase("runefist") // codiaz || p.getName().equalsIgnoreCase("Jacklin213") // Jacklin213 || p.getName().equalsIgnoreCase("kingbirdy") // kingbirdy - || p.getName().equalsIgnoreCase("creepermcaliens") // Coolade + || p.getName().equalsIgnoreCase("CherryCoolade") // Coolade || p.getName().equalsIgnoreCase("sampepere")) { // AlexTheCoder s.sendMessage(ChatColor.YELLOW + "ProjectKorra (Core) Developer"); } @@ -1199,6 +1199,8 @@ public class Commands { + "of utility however, being able to make themselves un-ignitable, extinguish large areas, cook food " + "in their hands, extinguish large areas, small bursts of flight, and then comes the abilities to shoot " + "fire from your hands."); + s.sendMessage(ChatColor.YELLOW + "Firebenders can chain their abilities into combos, type " + + Methods.getFireColor() + "/b help FireCombo" + ChatColor.YELLOW + " for more information."); s.sendMessage(ChatColor.YELLOW + "Learn More: " + ChatColor.DARK_AQUA + "http://tinyurl.com/k4fkjhb"); } if (Arrays.asList(chialiases).contains(args[1].toLowerCase())) { @@ -1296,6 +1298,16 @@ public class Commands { s.sendMessage(ChatColor.YELLOW + "This command will bind an ability to the slot you specify (if you specify one), or the slot currently" + " selected in your hotbar (If you do not specify a Slot #)."); } + if (args[1].equalsIgnoreCase("FireCombo")) + { + s.sendMessage(ChatColor.GOLD + "Fire Combos allow you to chain multiple abilities together to create stronger abilities." + + " Fire Combos are meant to be advanced Firebending techniques, they take practice! "); + s.sendMessage(Methods.getFireColor() + "FireKick" + ChatColor.WHITE + ": FireBlast > FireBlast > (Hold Shift) > FireBlast. "); + s.sendMessage(Methods.getFireColor() + "FireSpin" + ChatColor.WHITE + ": FireBlast > FireBlast > FireShield > (Tap Shift). "); + s.sendMessage(Methods.getFireColor() + "FireWheel" + ChatColor.WHITE + ": FireShield (Hold Shift) > Right Click a block in front of you twice > Switch to Blaze > Release Shift. "); + s.sendMessage(Methods.getFireColor() + "JetBlast" + ChatColor.WHITE + ": FireJet (Tap Shift) > FireJet (Tap Shift) > FireShield (Tap Shift) > FireJet. "); + s.sendMessage(Methods.getFireColor() + "JetBlaze" + ChatColor.WHITE + ": FireJet (Tap Shift) > FireJet (Tap Shift) > Blaze (Tap Shift) > FireJet. "); + } if (Methods.abilityExists(args[1])) { String ability = Methods.getAbility(args[1]); diff --git a/src/com/projectkorra/ProjectKorra/ConfigManager.java b/src/com/projectkorra/ProjectKorra/ConfigManager.java index de4e4a59..7ad958b8 100644 --- a/src/com/projectkorra/ProjectKorra/ConfigManager.java +++ b/src/com/projectkorra/ProjectKorra/ConfigManager.java @@ -534,6 +534,24 @@ public class ConfigManager { 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", 8.0); + config.addDefault("Abilities.Fire.FireCombo.FireKick.Damage", 3.0); + config.addDefault("Abilities.Fire.FireCombo.FireKick.Cooldown", 1000); + config.addDefault("Abilities.Fire.FireCombo.FireSpin.Range", 5.0); + config.addDefault("Abilities.Fire.FireCombo.FireSpin.Damage", 3.0); + config.addDefault("Abilities.Fire.FireCombo.FireSpin.Knockback", 2.0); + 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.5); + 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); diff --git a/src/com/projectkorra/ProjectKorra/PKListener.java b/src/com/projectkorra/ProjectKorra/PKListener.java index 5b94b349..d44f74b7 100644 --- a/src/com/projectkorra/ProjectKorra/PKListener.java +++ b/src/com/projectkorra/ProjectKorra/PKListener.java @@ -59,6 +59,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffectType; import org.bukkit.util.Vector; +import com.projectkorra.ProjectKorra.ComboManager.ClickType; import com.projectkorra.ProjectKorra.Ability.AvatarState; import com.projectkorra.ProjectKorra.CustomEvents.PlayerGrappleEvent; import com.projectkorra.ProjectKorra.Objects.Preset; @@ -245,6 +246,7 @@ public class PKListener implements Listener { if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { Methods.cooldowns.put(player.getName(), System.currentTimeMillis()); + ComboManager.addComboAbility(player, ClickType.RIGHTCLICK); } if (Paralyze.isParalyzed(player) || Bloodbending.isBloodbended(player) || Suffocate.isBreathbent(player)) { event.setCancelled(true); @@ -326,7 +328,12 @@ public class PKListener implements Listener { Player player = event.getPlayer(); if (event.isCancelled()) return; - + + if(player.isSneaking()) + ComboManager.addComboAbility(player, ComboManager.ClickType.SHIFTUP); + else + ComboManager.addComboAbility(player, ComboManager.ClickType.SHIFTDOWN); + if(Suffocate.isBreathbent(player)) { if(!Methods.getBoundAbility(player).equalsIgnoreCase("AirSwipe") || !Methods.getBoundAbility(player).equalsIgnoreCase("FireBlast") || !Methods.getBoundAbility(player).equalsIgnoreCase("EarthBlast") || !Methods.getBoundAbility(player).equalsIgnoreCase("WaterManipulation")) { event.setCancelled(true); @@ -665,7 +672,8 @@ public class PKListener implements Listener { if (event.isCancelled()) return; Player player = event.getPlayer(); - + ComboManager.addComboAbility(player, ComboManager.ClickType.LEFTCLICK); + if(Suffocate.isBreathbent(player)) { if(!Methods.getBoundAbility(player).equalsIgnoreCase("AirSwipe") || !Methods.getBoundAbility(player).equalsIgnoreCase("FireBlast") || !Methods.getBoundAbility(player).equalsIgnoreCase("EarthBlast") || !Methods.getBoundAbility(player).equalsIgnoreCase("WaterManipulation")) { event.setCancelled(true); diff --git a/src/com/projectkorra/ProjectKorra/ProjectKorra.java b/src/com/projectkorra/ProjectKorra/ProjectKorra.java index 84fe93a5..c294df2b 100644 --- a/src/com/projectkorra/ProjectKorra/ProjectKorra.java +++ b/src/com/projectkorra/ProjectKorra/ProjectKorra.java @@ -31,6 +31,7 @@ public class ProjectKorra extends JavaPlugin { new Methods(this); new Commands(this); new AbilityModuleManager(this); + new ComboManager(); ConfigManager.configCheck(); diff --git a/src/com/projectkorra/ProjectKorra/firebending/FireCombo.java b/src/com/projectkorra/ProjectKorra/firebending/FireCombo.java new file mode 100644 index 00000000..38262f69 --- /dev/null +++ b/src/com/projectkorra/ProjectKorra/firebending/FireCombo.java @@ -0,0 +1,545 @@ +package com.projectkorra.ProjectKorra.firebending; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.util.Vector; + +import com.projectkorra.ProjectKorra.BendingPlayer; +import com.projectkorra.ProjectKorra.ComboManager.ClickType; +import com.projectkorra.ProjectKorra.Methods; +import com.projectkorra.ProjectKorra.ProjectKorra; +import com.projectkorra.ProjectKorra.Ability.AvatarState; +import com.projectkorra.ProjectKorra.Utilities.ParticleEffect; +import com.projectkorra.ProjectKorra.chiblocking.Paralyze; +import com.projectkorra.ProjectKorra.waterbending.Bloodbending; + +public class FireCombo +{ + private static final List abilitiesToBlock = new ArrayList(){ + private static final long serialVersionUID = 5395690551860441647L; + { + add("AirShield"); + add("FireShield"); + add("AirSwipe"); + add("FireBlast"); + add("EarthManipulation"); + add("WaterManipulation"); + add("Combustion"); + }}; + private static boolean enabled = ProjectKorra.plugin.getConfig().getBoolean("Abilities.Fire.FireCombo.Enabled"); + private static final double FIRE_WHEEL_STARTING_HEIGHT = 2; + private static final double FIRE_WHEEL_RADIUS = 1; + public static double BURN_TIME = 2.5; + public static double FIRE_KICK_RANGE = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.FireCombo.FireKick.Range"); + public static double FIRE_KICK_DAMAGE = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.FireCombo.FireKick.Damage"); + public static double FIRE_SPIN_RANGE = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.FireCombo.FireSpin.Range"); + public static double FIRE_SPIN_DAMAGE = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.FireCombo.FireSpin.Damage"); + public static double FIRE_SPIN_KNOCKBACK = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.FireCombo.FireSpin.Knockback"); + public static double FIRE_WHEEL_DAMAGE = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.FireCombo.FireWheel.Damage"); + public static double FIRE_WHEEL_RANGE = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.FireCombo.FireWheel.Range"); + public static double FIRE_WHEEL_SPEED = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.FireCombo.FireWheel.Speed"); + public static double JET_BLAST_SPEED = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.FireCombo.JetBlast.Speed"); + public static double JET_BLAZE_SPEED = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.FireCombo.JetBlaze.Speed"); + public static double JET_BLAZE_DAMAGE = ProjectKorra.plugin.getConfig().getDouble("Abilities.Fire.FireCombo.JetBlaze.Damage"); + + public static long FIRE_KICK_COOLDOWN = ProjectKorra.plugin.getConfig().getLong("Abilities.Fire.FireCombo.FireKick.Cooldown"); + public static long FIRE_SPIN_COOLDOWN = ProjectKorra.plugin.getConfig().getLong("Abilities.Fire.FireCombo.FireSpin.Cooldown"); + public static long FIRE_WHEEL_COOLDOWN = ProjectKorra.plugin.getConfig().getLong("Abilities.Fire.FireCombo.FireWheel.Cooldown"); + public static long JET_BLAST_COOLDOWN = ProjectKorra.plugin.getConfig().getLong("Abilities.Fire.FireCombo.JetBlast.Cooldown"); + public static long JET_BLAZE_COOLDOWN = ProjectKorra.plugin.getConfig().getLong("Abilities.Fire.FireCombo.JetBlaze.Cooldown"); + + + public static ArrayList instances = new ArrayList(); + + private Player player; + private BendingPlayer bplayer; + private ClickType type; + private String ability; + + private long time; + private Location origin; + private Location currentLoc; + private Location destination; + private Vector direction; + private boolean firstTime = true; + private ArrayList affectedEntities = new ArrayList(); + private ArrayList tasks = new ArrayList(); + private int progressCounter = 0; + private double damage = 0, speed = 0, range = 0; + private long cooldown = 0; + + public FireCombo(Player player, String ability) + { + if(!enabled || !player.hasPermission("bending.ability.FireCombo")) + return; + if(Methods.isRegionProtectedFromBuild(player, "Blaze", player.getLocation())) + return; + time = System.currentTimeMillis(); + this.player = player; + this.ability = ability; + this.bplayer = Methods.getBendingPlayer(player.getName()); + + if(Methods.isChiBlocked(player.getName()) + || Bloodbending.isBloodbended(player) + || Paralyze.isParalyzed(player)){ + return; + } + + if(ability.equalsIgnoreCase("FireKick")){ + damage = FIRE_KICK_DAMAGE; + range = FIRE_KICK_RANGE; + speed = 1; + cooldown = FIRE_KICK_COOLDOWN; + } + else if(ability.equalsIgnoreCase("FireSpin")){ + damage = FIRE_SPIN_DAMAGE; + range = FIRE_SPIN_RANGE; + speed = 0.3; + cooldown = FIRE_SPIN_COOLDOWN; + } + else if(ability.equalsIgnoreCase("FireWheel")){ + damage = FIRE_WHEEL_DAMAGE; + range = FIRE_WHEEL_RANGE; + speed = FIRE_WHEEL_SPEED; + cooldown = FIRE_WHEEL_COOLDOWN; + } + else if(ability.equalsIgnoreCase("JetBlast")){ + speed = JET_BLAST_SPEED; + cooldown = JET_BLAST_COOLDOWN; + } + else if(ability.equalsIgnoreCase("JetBlaze")){ + damage = JET_BLAZE_DAMAGE; + speed = JET_BLAZE_SPEED; + cooldown = JET_BLAZE_COOLDOWN; + } + if(AvatarState.isAvatarState(player)){ + cooldown = 0; + damage = AvatarState.getValue(damage); + range = AvatarState.getValue(range); + } + instances.add(this); + } + public void progress() + { + progressCounter++; + for(int i = 0; i < tasks.size(); i++){ + BukkitRunnable br = tasks.get(i); + if(br instanceof FireComboStream) + { + FireComboStream fs = (FireComboStream)br; + if(fs.isCancelled()) + tasks.remove(fs); + } + } + if (player.isDead() || !player.isOnline()) { + remove(); + return; + } + + if(ability.equalsIgnoreCase("FireKick")) + { + if(destination == null) + { + if(bplayer.isOnCooldown("FireKick") && !AvatarState.isAvatarState(player)){ + remove(); + return; + } + bplayer.addCooldown("FireKick", cooldown); + Vector eyeDir = player.getEyeLocation().getDirection().normalize().multiply(range); + destination = player.getEyeLocation().add(eyeDir); + + player.getWorld().playSound(player.getLocation(), Sound.HORSE_JUMP, 0.5f, 0f); + player.getWorld().playSound(player.getLocation(), Sound.FIZZ, 0.5f, 1f); + for(int i = -30; i <= 30; i+=5) + { + Vector vec = Methods.getDirection(player.getLocation(),destination.clone()); + vec = Methods.rotateXZ(vec,i); + + FireComboStream fs = new FireComboStream(this, vec, player.getLocation(),range, speed); + fs.setSpread(0.2F); + fs.setDensity(5); + fs.setUseNewParticles(true); + if(tasks.size() % 3 != 0) + fs.setCollides(false); + fs.runTaskTimer(ProjectKorra.plugin, 0, 1L); + tasks.add(fs);player.getWorld().playSound(player.getLocation(), Sound.FIRE_IGNITE, 0.5f, 1f); + } + currentLoc = ((FireComboStream)tasks.get(0)).getLocation(); + for(FireComboStream stream : tasks) + if(Methods.blockAbilities(player, abilitiesToBlock, currentLoc, 2)) + stream.remove(); + } + else if(tasks.size() == 0){ + remove(); + return; + } + } + else if(ability.equalsIgnoreCase("FireSpin")) + { + if(destination == null) + { + if(bplayer.isOnCooldown("FireSpin") && !AvatarState.isAvatarState(player)){ + remove(); + return; + } + bplayer.addCooldown("FireSpin", cooldown); + destination = player.getEyeLocation().add(range,0,range); + player.getWorld().playSound(player.getLocation(), Sound.FIZZ, 0.5f, 0.5f); + + for(int i = 0; i <= 360; i+=5) + { + Vector vec = Methods.getDirection(player.getLocation(),destination.clone()); + vec = Methods.rotateXZ(vec, i - 180); + vec.setY(0); + + FireComboStream fs = new FireComboStream(this, vec, player.getLocation().clone().add(0,1,0), range, speed); + fs.setSpread(0.0F); + fs.setDensity(1); + fs.setUseNewParticles(true); + if(tasks.size() % 10 != 0) + fs.setCollides(false); + fs.runTaskTimer(ProjectKorra.plugin, 0, 1L); + tasks.add(fs); + } + } + if(tasks.size() == 0){ + remove(); + return; + } + for(FireComboStream stream : tasks) + if(Methods.isWithinShields(stream.getLocation())) + stream.remove(); + } + else if(ability.equalsIgnoreCase("JetBlast")) + { + if(System.currentTimeMillis() - time > 5000) + { + remove(); + return; + } + else if(FireJet.instances.containsKey(player)) + { + if(firstTime){ + if(bplayer.isOnCooldown("JetBlast") && !AvatarState.isAvatarState(player)){ + remove(); + return; + } + bplayer.addCooldown("JetBlast", cooldown); + firstTime = false; + float spread = 0F; + ParticleEffect.LARGE_EXPLODE.display(player.getLocation(), spread, spread, spread, 0, 1); + player.getWorld().playSound(player.getLocation(), Sound.EXPLODE, 15, 0F); + } + player.setVelocity(player.getVelocity().normalize().multiply(speed)); + + FireComboStream fs = new FireComboStream(this,player.getVelocity().clone().multiply(-1),player.getLocation(), 3, 0.5); + fs.setDensity(1); + fs.setSpread(0.9F); + fs.setUseNewParticles(true); + fs.setCollides(false); + fs.runTaskTimer(ProjectKorra.plugin, 0, 1L); + tasks.add(fs); + } + } + + else if(ability.equalsIgnoreCase("JetBlaze")) + { + if(firstTime) + { + if(bplayer.isOnCooldown("JetBlaze") && !AvatarState.isAvatarState(player)) + { + remove(); + return; + } + bplayer.addCooldown("JetBlaze", cooldown); + firstTime = false; + } + else if(System.currentTimeMillis() - time > 5000) + { + remove(); + return; + } + else if(FireJet.instances.containsKey(player)) + { + direction = player.getVelocity().clone().multiply(-1); + player.setVelocity(player.getVelocity().normalize().multiply(speed)); + + FireComboStream fs = new FireComboStream(this,direction,player.getLocation(), 5, 1); + fs.setDensity(8); + fs.setSpread(1.0F); + fs.setUseNewParticles(true); + fs.setCollisionRadius(3); + fs.setParticleEffect(ParticleEffect.LARGE_SMOKE); + if(progressCounter % 5 != 0) + fs.setCollides(false); + fs.runTaskTimer(ProjectKorra.plugin, 0, 1L); + tasks.add(fs); + if(progressCounter % 5 == 0) + player.getWorld().playSound(player.getLocation(), Sound.WITHER_SHOOT, 3, 1F); + } + } + else if(ability.equalsIgnoreCase("FireWheel")) + { + if(currentLoc == null) + { + if(bplayer.isOnCooldown("FireWheel") && !AvatarState.isAvatarState(player)){ + remove(); + return; + } + bplayer.addCooldown("FireWheel", cooldown); + origin = player.getLocation(); + currentLoc = Methods.getTopBlock(player.getLocation(), 3, 3).getLocation(); + + if(currentLoc == null){ + remove(); + return; + } + currentLoc = player.getLocation(); + direction = player.getEyeLocation().getDirection().clone().normalize(); + direction.setY(0); + } + else if(currentLoc.distance(origin) > range){ + remove(); + return; + } + + Block topBlock = Methods.getTopBlock(currentLoc, 2, -4); + if(topBlock == null || + (Methods.isWaterbendable(topBlock, player) && !Methods.isPlant(topBlock))){ + remove(); + return; + } + if(topBlock.getType() == Material.FIRE || Methods.isPlant(topBlock)) + topBlock = topBlock.getLocation().add(0,-1,0).getBlock(); + currentLoc.setY(topBlock.getY() + FIRE_WHEEL_STARTING_HEIGHT); + + FireComboStream fs = new FireComboStream(this, direction, currentLoc.clone().add(0,-1,0), 5, 1); + fs.setDensity(0); + fs.setSinglePoint(true); + fs.setCollisionRadius(1.5); + fs.setCollides(true); + fs.runTaskTimer(ProjectKorra.plugin, 0, 1L); + tasks.add(fs); + + for(double i = -180; i <= 180; i+=3) + { + Location tempLoc = currentLoc.clone(); + Vector newDir = direction.clone().multiply(FIRE_WHEEL_RADIUS * Math.cos(Math.toRadians(i))); + tempLoc.add(newDir); + tempLoc.setY(tempLoc.getY() + (FIRE_WHEEL_RADIUS * Math.sin(Math.toRadians(i)))); + ParticleEffect.FLAME.display(tempLoc, 0, 0, 0, 0, 1); + } + + currentLoc = currentLoc.add(direction.clone().multiply(speed)); + currentLoc.getWorld().playSound(currentLoc, Sound.FIRE, 1, 1); + if(Methods.blockAbilities(player, abilitiesToBlock, currentLoc, 2)){ + remove(); + return; + }; + } + + if(progressCounter % 3 == 0) + checkSafeZone(); + } + public void checkSafeZone(){ + if(currentLoc != null && Methods.isRegionProtectedFromBuild(player, "Blaze", currentLoc)) + remove(); + } + public void collision(LivingEntity entity, Vector direction, FireComboStream fstream) + { + if(Methods.isRegionProtectedFromBuild(player, "Blaze", entity.getLocation())) + return; + entity.getLocation().getWorld().playSound(entity.getLocation(), Sound.VILLAGER_HIT, 0.3f, 0.3f); + + if(ability.equalsIgnoreCase("FireKick")) + { + Methods.damageEntity(player, entity, damage); + fstream.remove(); + } + else if(ability.equalsIgnoreCase("FireSpin")) + { + double knockback = AvatarState.isAvatarState(player) ? + FIRE_SPIN_KNOCKBACK + 0.5 : FIRE_SPIN_KNOCKBACK; + Methods.damageEntity(player, entity, damage); + entity.setVelocity(direction.normalize().multiply(knockback)); + fstream.remove(); + } + else if(ability.equalsIgnoreCase("JetBlaze")) + { + if(!affectedEntities.contains(entity)) + { + affectedEntities.add(entity); + Methods.damageEntity(player, entity, damage); + entity.setFireTicks((int) (BURN_TIME * 20)); + } + } + else if(ability.equalsIgnoreCase("FireWheel")) + { + if(!affectedEntities.contains(entity)) + { + affectedEntities.add(entity); + Methods.damageEntity(player, entity, damage); + entity.setFireTicks((int) (BURN_TIME * 20)); + this.remove(); + } + } + } + public void remove() + { + /** + * Removes this instance of FireCombo, cleans up + * any blocks that are remaining in totalBlocks, + * and cancels any remaining tasks. + */ + instances.remove(this); + for(BukkitRunnable task : tasks) + task.cancel(); + } + + public static void progressAll() + { + for(int i = instances.size() - 1; i >= 0; i--) + instances.get(i).progress(); + } + public static void removeAll() + { + for(int i = instances.size() - 1; i >= 0; i--) + { + instances.get(i).remove(); + } + } + public Player getPlayer(){ + return player; + } + public static ArrayList getFireCombo(Player player) + { + /** + * Returns all the FireCombos created by a specific player. + */ + ArrayList list = new ArrayList(); + for(FireCombo lf : instances) + if(lf.player != null && lf.player == player) + list.add(lf); + return list; + } + public static ArrayList getFireCombo(Player player, ClickType type) + { + /** + * Returns all of the FireCombos created by a specific player but + * filters the abilities based on shift or click. + */ + ArrayList list = new ArrayList(); + for(FireCombo lf : instances) + if(lf.player != null && lf.player == player && lf.type != null && lf.type == type) + list.add(lf); + return list; + } + public class FireComboStream extends BukkitRunnable + { + private Vector direction; + private double speed; + private Location initialLoc, currentLoc; + private double distance; + + ParticleEffect particleEffect = ParticleEffect.FLAME; + private FireCombo fireCombo; + private float spread = 0; + private int density = 1; + private boolean useNewParticles = false; + private boolean cancelled = false; + private boolean collides = true; + private boolean singlePoint = false; + private double collisionRadius = 2; + private int checkCollisionDelay = 1; + private int checkCollisionCounter = 0; + + public FireComboStream(FireCombo fireCombo, Vector direction, Location loc, double distance, double speed) + { + this.fireCombo = fireCombo; + this.direction = direction; + this.speed = speed; + this.initialLoc = loc.clone(); + this.currentLoc = loc.clone(); + this.distance = distance; + } + public void run() + { + Block block = currentLoc.getBlock(); + if(block.getType() != Material.AIR && !Methods.isPlant(block)){ + remove(); + return; + } + for(int i = 0; i < density; i++) + { + if(useNewParticles) + particleEffect.display(currentLoc, spread, spread, spread, 0, 1); + else + currentLoc.getWorld().playEffect(currentLoc, Effect.MOBSPAWNER_FLAMES, 0, 15); + } + + currentLoc.add(direction.normalize().multiply(speed)); + if(initialLoc.distance(currentLoc) > distance) + { + remove(); + return; + } + else if(collides && checkCollisionCounter % checkCollisionDelay == 0) + { + for(Entity entity : Methods.getEntitiesAroundPoint(currentLoc, collisionRadius)) + { + if(entity instanceof LivingEntity && !entity.equals(fireCombo.getPlayer())) + fireCombo.collision((LivingEntity) entity, direction, this); + } + } + checkCollisionCounter++; + if(singlePoint) + remove(); + } + public void remove() + { + this.cancel(); + this.cancelled = true; + } + public Location getLocation(){ + return this.currentLoc; + } + public void setSpread(float spread){ + this.spread = spread; + } + public void setUseNewParticles(boolean b){ + useNewParticles = b; + } + public void setDensity(int density){ + this.density = density; + } + public boolean isCancelled(){ + return cancelled; + } + public void setParticleEffect(ParticleEffect effect){ + this.particleEffect = effect; + } + public void setCollides(boolean b){ + this.collides = b; + } + public void setCollisionRadius(double radius){ + this.collisionRadius = radius; + } + public void setSinglePoint(boolean b){ + this.singlePoint = b; + } + public void setCheckCollisionDelay(int delay){ + this.checkCollisionDelay = delay; + } + } + +} diff --git a/src/com/projectkorra/ProjectKorra/firebending/FirebendingManager.java b/src/com/projectkorra/ProjectKorra/firebending/FirebendingManager.java index 5390cd3c..656d114b 100644 --- a/src/com/projectkorra/ProjectKorra/firebending/FirebendingManager.java +++ b/src/com/projectkorra/ProjectKorra/firebending/FirebendingManager.java @@ -33,5 +33,6 @@ public class FirebendingManager implements Runnable { } FireStream.dissipateAll(); FireStream.progressAll(); + FireCombo.progressAll(); } }