diff --git a/src/com/projectkorra/projectkorra/GeneralMethods.java b/src/com/projectkorra/projectkorra/GeneralMethods.java
index f92c3115..556e2ad4 100644
--- a/src/com/projectkorra/projectkorra/GeneralMethods.java
+++ b/src/com/projectkorra/projectkorra/GeneralMethods.java
@@ -211,11 +211,15 @@ public class GeneralMethods {
}
/**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ *
* Cycles through a list of ability names to check if any instances of the
* abilities exist at a specific location. If an instance of the ability is
* found then it will be removed, with the exception FireShield, and
* AirShield.
*/
+ @Deprecated
public static boolean blockAbilities(Player player, List abilitiesToBlock, Location loc, double radius) {
boolean hasBlocked = false;
for (String ability : abilitiesToBlock) {
diff --git a/src/com/projectkorra/projectkorra/ProjectKorra.java b/src/com/projectkorra/projectkorra/ProjectKorra.java
index 789a78ac..4953a641 100644
--- a/src/com/projectkorra/projectkorra/ProjectKorra.java
+++ b/src/com/projectkorra/projectkorra/ProjectKorra.java
@@ -11,6 +11,8 @@ import org.bukkit.plugin.java.JavaPlugin;
import com.bekvon.bukkit.residence.protection.FlagPermissions;
import com.projectkorra.projectkorra.ability.CoreAbility;
+import com.projectkorra.projectkorra.ability.util.CollisionInitializer;
+import com.projectkorra.projectkorra.ability.util.CollisionManager;
import com.projectkorra.projectkorra.ability.util.ComboManager;
import com.projectkorra.projectkorra.ability.util.MultiAbilityManager;
import com.projectkorra.projectkorra.airbending.AirbendingManager;
@@ -33,6 +35,7 @@ public class ProjectKorra extends JavaPlugin {
public static ProjectKorra plugin;
public static Logger log;
public static PKLogHandler handler;
+ public static CollisionManager collisionManager;
public static long time_step = 1;
public Updater updater;
@@ -59,6 +62,9 @@ public class ProjectKorra extends JavaPlugin {
new MultiAbilityManager();
new ComboManager();
CoreAbility.registerAbilities();
+ collisionManager = new CollisionManager();
+ new CollisionInitializer(collisionManager).initializeCollisions();
+ collisionManager.startCollisionDetection();
Preset.loadExternalPresets();
diff --git a/src/com/projectkorra/projectkorra/ability/AirAbility.java b/src/com/projectkorra/projectkorra/ability/AirAbility.java
index 132037fb..675b02b4 100644
--- a/src/com/projectkorra/projectkorra/ability/AirAbility.java
+++ b/src/com/projectkorra/projectkorra/ability/AirAbility.java
@@ -2,11 +2,14 @@ package com.projectkorra.projectkorra.ability;
import com.projectkorra.projectkorra.Element;
import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.airbending.AirSpout;
import com.projectkorra.projectkorra.airbending.Suffocate;
import com.projectkorra.projectkorra.util.ParticleEffect;
+import com.projectkorra.projectkorra.util.ParticleEffect.ParticleData;
import org.bukkit.Location;
+import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
@@ -34,6 +37,16 @@ public abstract class AirAbility extends ElementalAbility {
public Element getElement() {
return Element.AIR;
}
+
+ @Override
+ public void handleCollision(Collision collision) {
+ super.handleCollision(collision);
+ if (collision.isRemovingFirst()) {
+ ParticleData particleData = (ParticleEffect.ParticleData) new ParticleEffect.BlockData(Material.WOOL, (byte) 0);
+ ParticleEffect.BLOCK_CRACK.display(particleData, 1F, 1F, 1F, 0.1F, 10, collision.getLocationFirst(), 50);
+ }
+ }
+
/**
* Breaks a breathbendng hold on an entity or one a player is inflicting on an entity.
@@ -77,11 +90,15 @@ public abstract class AirAbility extends ElementalAbility {
}
/**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ *
* Checks whether a location is within an AirShield.
*
* @param loc The location to check
* @return true If the location is inside an AirShield.
*/
+ @Deprecated
public static boolean isWithinAirShield(Location loc) {
List list = new ArrayList();
list.add("AirShield");
@@ -124,22 +141,30 @@ public abstract class AirAbility extends ElementalAbility {
}
/**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ *
* Removes all air spouts in a location within a certain radius.
*
* @param loc The location to use
* @param radius The radius around the location to remove spouts in
* @param source The player causing the removal
*/
+ @Deprecated
public static void removeAirSpouts(Location loc, double radius, Player source) {
AirSpout.removeSpouts(loc, radius, source);
}
/**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ *
* Removes all air spouts in a location with a radius of 1.5.
*
* @param loc The location to use
* @param source The player causing the removal
*/
+ @Deprecated
public static void removeAirSpouts(Location loc, Player source) {
removeAirSpouts(loc, 1.5, source);
}
diff --git a/src/com/projectkorra/projectkorra/ability/CoreAbility.java b/src/com/projectkorra/projectkorra/ability/CoreAbility.java
index 3efde921..1536c899 100644
--- a/src/com/projectkorra/projectkorra/ability/CoreAbility.java
+++ b/src/com/projectkorra/projectkorra/ability/CoreAbility.java
@@ -18,6 +18,7 @@ import java.util.concurrent.ConcurrentSkipListMap;
import java.util.jar.JarFile;
import org.bukkit.Bukkit;
+import org.bukkit.Location;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
@@ -29,6 +30,8 @@ import com.projectkorra.projectkorra.Element;
import com.projectkorra.projectkorra.Element.SubElement;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.util.AbilityLoader;
+import com.projectkorra.projectkorra.ability.util.Collision;
+import com.projectkorra.projectkorra.ability.util.CollisionManager;
import com.projectkorra.projectkorra.ability.util.ComboManager;
import com.projectkorra.projectkorra.ability.util.MultiAbilityManager;
import com.projectkorra.projectkorra.ability.util.MultiAbilityManager.MultiAbilityInfo;
@@ -40,9 +43,14 @@ import com.projectkorra.projectkorra.event.AbilityStartEvent;
import sun.reflect.ReflectionFactory;
/**
- * CoreAbility provides default implementation of an Ability, including methods to control
- * the life cycle of a specific instance. CoreAbility also provides a system to load CoreAbilities
- * within a {@link JavaPlugin}, or located in an external {@link JarFile}.
+ * CoreAbility provides default implementation of an Ability, including methods
+ * to control the life cycle of a specific instance. CoreAbility also provides a
+ * system to load CoreAbilities within a {@link JavaPlugin}, or located in an
+ * external {@link JarFile}.
+ *
+ * For {@link CollisionManager} and {@link Collision}, a CoreAbility may need to
+ * override {@link #isCollidable()}, {@link #getCollisionRadius()},
+ * {@link #handleCollision(Collision)}, and {@link #getLocations()}.
*
* @see #start()
* @see #progress()
@@ -51,35 +59,41 @@ import sun.reflect.ReflectionFactory;
* @see #registerPluginAbilities(JavaPlugin, String)
*/
public abstract class CoreAbility implements Ability {
-
+
private static final Map, Map>> INSTANCES = new ConcurrentHashMap<>();
private static final Map, Set> INSTANCES_BY_CLASS = new ConcurrentHashMap<>();
- private static final Map ABILITIES_BY_NAME = new ConcurrentSkipListMap<>();
-
+ private static final Map ABILITIES_BY_NAME = new ConcurrentSkipListMap<>(); // preserves ordering
+ private static final Map, CoreAbility> ABILITIES_BY_CLASS = new ConcurrentHashMap<>();
+ private static final double DEFAULT_COLLISION_RADIUS = 0.3;
+
private static int idCounter;
- protected long startTime;
protected Player player;
protected BendingPlayer bPlayer;
-
+
private boolean started;
private boolean removed;
private int id;
+ private long startTime;
+ private long startTick;
static {
idCounter = Integer.MIN_VALUE;
}
-
+
/**
- * The default constructor is needed to create a fake instance of each CoreAbility via reflection
- * in {@link #registerAbilities()}. More specifically, {@link #registerPluginAbilities} calls
- * getDeclaredConstructor which is only usable with a public default constructor. Reflection lets us
- * create a list of all of the plugin's abilities when the plugin first loads.
+ * The default constructor is needed to create a fake instance of each
+ * CoreAbility via reflection in {@link #registerAbilities()}. More
+ * specifically, {@link #registerPluginAbilities} calls
+ * getDeclaredConstructor which is only usable with a public default
+ * constructor. Reflection lets us create a list of all of the plugin's
+ * abilities when the plugin first loads.
*
* @see #ABILITIES_BY_NAME
* @see #getAbility(String)
*/
- public CoreAbility() {}
+ public CoreAbility() {
+ }
/**
* Creates a new CoreAbility instance but does not start it.
@@ -91,13 +105,14 @@ public abstract class CoreAbility implements Ability {
if (player == null) {
return;
}
-
+
this.player = player;
this.bPlayer = BendingPlayer.getBendingPlayer(player);
this.startTime = System.currentTimeMillis();
this.started = false;
this.id = CoreAbility.idCounter;
-
+ this.startTick = getCurrentTick();
+
if (idCounter == Integer.MAX_VALUE) {
idCounter = Integer.MIN_VALUE;
} else {
@@ -106,9 +121,10 @@ public abstract class CoreAbility implements Ability {
}
/**
- * Causes the ability to begin updating every tick by calling {@link #progress()}
- * until {@link #remove()} is called. This method cannot be overridden, and any code
- * that needs to be performed before start should be handled in the constructor.
+ * Causes the ability to begin updating every tick by calling
+ * {@link #progress()} until {@link #remove()} is called. This method cannot
+ * be overridden, and any code that needs to be performed before start
+ * should be handled in the constructor.
*
* @see #getStartTime()
* @see #isStarted()
@@ -120,7 +136,7 @@ public abstract class CoreAbility implements Ability {
}
AbilityStartEvent event = new AbilityStartEvent(this);
Bukkit.getServer().getPluginManager().callEvent(event);
- if(event.isCancelled()) {
+ if (event.isCancelled()) {
remove();
return;
}
@@ -144,11 +160,12 @@ public abstract class CoreAbility implements Ability {
}
/**
- * Causes this CoreAbility instance to be removed, and {@link #progress} will no longer
- * be called every tick. If this method is overridden then the new method must call
- * super.remove().
+ * Causes this CoreAbility instance to be removed, and {@link #progress}
+ * will no longer be called every tick. If this method is overridden then
+ * the new method must call super.remove().
*
* {@inheritDoc}
+ *
* @see #isRemoved()
*/
@Override
@@ -156,10 +173,10 @@ public abstract class CoreAbility implements Ability {
if (player == null) {
return;
}
-
+
Bukkit.getServer().getPluginManager().callEvent(new AbilityEndEvent(this));
removed = true;
-
+
Map> classMap = INSTANCES.get(getClass());
if (classMap != null) {
Map playerMap = classMap.get(player.getUniqueId());
@@ -169,7 +186,7 @@ public abstract class CoreAbility implements Ability {
classMap.remove(player.getUniqueId());
}
}
-
+
if (classMap.size() == 0) {
INSTANCES.remove(getClass());
}
@@ -194,7 +211,8 @@ public abstract class CoreAbility implements Ability {
}
/**
- * Removes every CoreAbility instance that has been started but not yet removed.
+ * Removes every CoreAbility instance that has been started but not yet
+ * removed.
*/
public static void removeAll() {
for (Set setAbils : INSTANCES_BY_CLASS.values()) {
@@ -202,7 +220,7 @@ public abstract class CoreAbility implements Ability {
abil.remove();
}
}
-
+
for (CoreAbility coreAbility : ABILITIES_BY_NAME.values()) {
if (coreAbility instanceof AddonAbility) {
AddonAbility addon = (AddonAbility) coreAbility;
@@ -212,8 +230,8 @@ public abstract class CoreAbility implements Ability {
}
/**
- * Returns any T CoreAbility that has been started and not yet removed. May return null if
- * no such ability exists.
+ * Returns any T CoreAbility that has been started and not yet removed. May
+ * return null if no such ability exists.
*
* @param player the player that created the CoreAbility instance
* @param clazz the class of the type of CoreAbility
@@ -226,16 +244,18 @@ public abstract class CoreAbility implements Ability {
}
return null;
}
-
+
/**
- * Returns a "fake" instance for the CoreAbility represented by abilityName. This method
- * does not look into CoreAbility instances that were created by Players, instead this
- * method looks at the CoreAbilities that were created via Reflection by {@link #registerAbilities()}
- * when the plugin was first loaded.
+ * Returns a "fake" instance for the CoreAbility represented by abilityName.
+ * This method does not look into CoreAbility instances that were created by
+ * Players, instead this method looks at the CoreAbilities that were created
+ * via Reflection by {@link #registerAbilities()} when the plugin was first
+ * loaded.
*
- * These "fake" instances have a null player, but methods such as
- * {@link Ability#getName()}, and {@link Ability#getElement()} will still work, as will checking
- * the type of the ability with instanceof.
+ *
+ * These "fake" instances have a null player, but methods such as
+ * {@link Ability#getName()}, and {@link Ability#getElement()} will still
+ * work, as will checking the type of the ability with instanceof.
*
*
* CoreAbility coreAbil = getAbility(someString);
@@ -247,16 +267,28 @@ public abstract class CoreAbility implements Ability {
public static CoreAbility getAbility(String abilityName) {
return abilityName != null ? ABILITIES_BY_NAME.get(abilityName.toLowerCase()) : null;
}
-
+
/**
- * Returns a list of "fake" instances for each ability that was loaded by {@link #registerAbilities()}
+ * Returns a "fake" instance for a CoreAbility with the specific class.
+ *
+ * @param clazz the class for the type of CoreAbility to be returned
+ * @return a "fake" CoreAbility instance or null
+ */
+ public static CoreAbility getAbility(Class extends CoreAbility> clazz) {
+ return clazz != null ? ABILITIES_BY_CLASS.get(clazz) : null;
+ }
+
+ /**
+ * @return a list of "fake" instances for each ability that was loaded by
+ * {@link #registerAbilities()}
*/
public static ArrayList getAbilities() {
return new ArrayList(ABILITIES_BY_NAME.values());
}
/**
- * Returns a Collection of all of the player created instances for a specific type of CoreAbility.
+ * Returns a Collection of all of the player created instances for a
+ * specific type of CoreAbility.
*
* @param clazz the class for the type of CoreAbilities
* @return a Collection of real instances
@@ -270,7 +302,8 @@ public abstract class CoreAbility implements Ability {
}
/**
- * Returns a Collection of specific CoreAbility instances that were created by the specified player.
+ * Returns a Collection of specific CoreAbility instances that were created
+ * by the specified player.
*
* @param player the player that created the instances
* @param clazz the class for the type of CoreAbilities
@@ -283,9 +316,10 @@ public abstract class CoreAbility implements Ability {
}
return (Collection) INSTANCES.get(clazz).get(player.getUniqueId()).values();
}
-
+
/**
- * Returns an List of fake instances that were loaded by {@link #registerAbilities()} filtered by Element.
+ * Returns an List of fake instances that were loaded by
+ * {@link #registerAbilities()} filtered by Element.
*
* @param element the Element of the loaded abilities
* @return a list of fake CoreAbility instances
@@ -306,7 +340,7 @@ public abstract class CoreAbility implements Ability {
}
return abilities;
}
-
+
/**
* Returns true if the player has an active CoreAbility instance of type T.
*
@@ -316,9 +350,10 @@ public abstract class CoreAbility implements Ability {
public static boolean hasAbility(Player player, Class clazz) {
return getAbility(player, clazz) != null;
}
-
+
/**
- * Returns a Set of all of the players that currently have an active instance of clazz.
+ * Returns a Set of all of the players that currently have an active
+ * instance of clazz.
*
* @param clazz the clazz for the type of CoreAbility
*/
@@ -337,10 +372,10 @@ public abstract class CoreAbility implements Ability {
}
return players;
}
-
+
/**
- * Scans and loads plugin CoreAbilities, and Addon CoreAbilities that are located
- * in a Jar file inside of the /ProjectKorra/Abilities/ folder.
+ * Scans and loads plugin CoreAbilities, and Addon CoreAbilities that are
+ * located in a Jar file inside of the /ProjectKorra/Abilities/ folder.
*/
public static void registerAbilities() {
ABILITIES_BY_NAME.clear();
@@ -350,9 +385,10 @@ public abstract class CoreAbility implements Ability {
/**
* Scans a JavaPlugin and registers CoreAbility class files.
- *
+ *
* @param plugin a JavaPlugin containing CoreAbility class files
- * @param packagePrefix a prefix of the package name, used to increase performance
+ * @param packagePrefix a prefix of the package name, used to increase
+ * performance
* @see #getAbilities()
* @see #getAbility(String)
*/
@@ -361,26 +397,26 @@ public abstract class CoreAbility implements Ability {
if (plugin == null) {
return;
}
-
+
Class> pluginClass = plugin.getClass();
ClassLoader loader = pluginClass.getClassLoader();
ReflectionFactory rf = ReflectionFactory.getReflectionFactory();
-
+
try {
for (final ClassInfo info : ClassPath.from(loader).getAllClasses()) {
if (!info.getPackageName().startsWith(packagePrefix)) {
continue;
}
-
+
Class> clazz = null;
try {
clazz = info.load();
if (!CoreAbility.class.isAssignableFrom(clazz) || clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) {
continue;
}
-
+
Constructor> objDef = CoreAbility.class.getDeclaredConstructor();
- Constructor> intConstr = rf.newConstructorForSerialization(clazz, objDef);;
+ Constructor> intConstr = rf.newConstructorForSerialization(clazz, objDef);
CoreAbility ability = (CoreAbility) clazz.cast(intConstr.newInstance());
if (ability == null || ability.getName() == null) {
@@ -393,6 +429,7 @@ public abstract class CoreAbility implements Ability {
String name = ability.getName();
ABILITIES_BY_NAME.put(ability.getName().toLowerCase(), ability);
+ ABILITIES_BY_CLASS.put(ability.getClass(), ability);
if (ability instanceof ComboAbility) {
ComboAbility combo = (ComboAbility) ability;
@@ -407,25 +444,28 @@ public abstract class CoreAbility implements Ability {
ComboManager.getAuthors().put(name, author);
}
}
-
+
if (ability instanceof MultiAbility) {
MultiAbility multiAbil = (MultiAbility) ability;
MultiAbilityManager.multiAbilityList.add(new MultiAbilityInfo(name, multiAbil.getMultiAbilities()));
}
-
+
if (ability instanceof AddonAbility) {
AddonAbility addon = (AddonAbility) ability;
addon.load();
}
- } catch (Exception e) {
- } catch (Error e) {
+ }
+ catch (Exception e) {
+ }
+ catch (Error e) {
}
}
- } catch (IOException e) {
+ }
+ catch (IOException e) {
e.printStackTrace();
}
}
-
+
/**
* Scans all of the Jar files inside of /ProjectKorra/folder and registers
* all of the CoreAbility class files that were found.
@@ -441,10 +481,10 @@ public abstract class CoreAbility implements Ability {
path.mkdir();
return;
}
-
+
AbilityLoader abilityLoader = new AbilityLoader(plugin, path);
List loadedAbilities = abilityLoader.load(CoreAbility.class, CoreAbility.class);
-
+
for (CoreAbility coreAbil : loadedAbilities) {
if (!(coreAbil instanceof AddonAbility)) {
plugin.getLogger().warning(coreAbil.getName() + " is an addon ability and must implement the AddonAbility interface");
@@ -453,14 +493,14 @@ public abstract class CoreAbility implements Ability {
plugin.getLogger().info(coreAbil.getName() + " is disabled");
continue;
}
-
+
AddonAbility addon = (AddonAbility) coreAbil;
String name = coreAbil.getName();
-
+
try {
addon.load();
ABILITIES_BY_NAME.put(name.toLowerCase(), coreAbil);
-
+
if (coreAbil instanceof ComboAbility) {
ComboAbility combo = (ComboAbility) coreAbil;
if (combo.getCombination() != null) {
@@ -470,28 +510,37 @@ public abstract class CoreAbility implements Ability {
ComboManager.getAuthors().put(name, addon.getAuthor());
}
}
-
+
if (coreAbil instanceof MultiAbility) {
MultiAbility multiAbil = (MultiAbility) coreAbil;
MultiAbilityManager.multiAbilityList.add(new MultiAbilityInfo(name, multiAbil.getMultiAbilities()));
}
- } catch (Exception | Error e) {
+ }
+ catch (Exception | Error e) {
plugin.getLogger().warning("The ability " + coreAbil.getName() + " was not able to load, if this message shows again please remove it!");
e.printStackTrace();
addon.stop();
- ABILITIES_BY_NAME.remove(name.toLowerCase());
+ ABILITIES_BY_NAME.remove(name.toLowerCase());
}
}
}
-
+
public long getStartTime() {
return startTime;
}
+ public long getStartTick() {
+ return startTick;
+ }
+
+ public long getCurrentTick() {
+ return player.getWorld().getFullTime();
+ }
+
public boolean isStarted() {
return started;
}
-
+
public boolean isRemoved() {
return removed;
}
@@ -503,37 +552,37 @@ public abstract class CoreAbility implements Ability {
public int getId() {
return id;
}
-
+
@Override
public boolean isHiddenAbility() {
return false;
}
-
+
@Override
public boolean isEnabled() {
if (this instanceof AddonAbility) {
return true;
}
-
+
String elementName = getElement().getName();
if (getElement() instanceof SubElement) {
elementName = ((SubElement) getElement()).getParentElement().getName();
}
-
+
String tag = null;
if (this instanceof ComboAbility) {
- tag = "Abilities." + elementName + "." + elementName + "Combo." + getName() + ".Enabled";
+ tag = "Abilities." + elementName + "." + elementName + "Combo." + getName() + ".Enabled";
} else {
tag = "Abilities." + elementName + "." + getName() + ".Enabled";
}
-
+
if (getConfig().isBoolean(tag)) {
return getConfig().getBoolean(tag);
} else {
return true;
}
}
-
+
@Override
public String getDescription() {
String elementName = getElement().getName();
@@ -547,36 +596,98 @@ public abstract class CoreAbility implements Ability {
public Player getPlayer() {
return player;
}
-
+
+ /**
+ * Used by the CollisionManager to check if two instances can collide with
+ * each other. For example, an EarthBlast is not collidable right when the
+ * person selects a source block, but it is collidable once the block begins
+ * traveling.
+ *
+ * @return true if the instance is currently collidable
+ * @see CollisionManager
+ */
+ public boolean isCollidable() {
+ return true;
+ }
+
+ /**
+ * The radius for collision of the ability instance. Some circular abilities
+ * are better represented with 1 single Location with a small or large
+ * radius, such as AirShield, FireShield, EarthSmash, WaterManipulation,
+ * EarthBlast, etc. Some abilities consist of multiple Locations with small
+ * radiuses, such as AirSpout, WaterSpout, Torrent, RaiseEarth, AirSwipe,
+ * FireKick, etc.
+ *
+ * @return the radius for a location returned by {@link #getLocations()}
+ * @see CollisionManager
+ */
+ public double getCollisionRadius() {
+ return DEFAULT_COLLISION_RADIUS;
+ }
+
+ /**
+ * Called when this ability instance collides with another. Some abilities
+ * may want advanced behavior on a Collision; e.g. FireCombos only remove
+ * the stream that was hit rather than the entire ability.
+ *
+ * collision.getAbilitySecond() - the ability that we are colliding with
+ * collision.isRemovingFirst() - if this ability should be removed
+ *
+ * This ability should only worry about itself because handleCollision will
+ * be called for the other ability instance as well.
+ *
+ * @param collision with data about the other ability instance
+ * @see CollisionManager
+ */
+ public void handleCollision(Collision collision) {
+ if (collision.isRemovingFirst()) {
+ remove();
+ }
+ }
+
+ /**
+ * A List of Locations used to represent the ability. Some abilities might
+ * just be 1 Location with a radius, while some might be multiple Locations
+ * with small radiuses.
+ *
+ * @return a List of the ability's locations
+ * @see CollisionManager
+ */
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ locations.add(getLocation());
+ return locations;
+ }
+
/**
* @return the current FileConfiguration for the plugin
*/
public static FileConfiguration getConfig() {
return ConfigManager.getConfig();
}
-
+
/**
* @return the language.yml for the plugin
*/
public static FileConfiguration getLanguageConfig() {
return ConfigManager.languageConfig.get();
}
-
+
/**
- * Returns a String used to debug potential CoreAbility memory that can be caused
- * by a developer forgetting to call {@link #remove()}
+ * Returns a String used to debug potential CoreAbility memory that can be
+ * caused by a developer forgetting to call {@link #remove()}
*/
public static String getDebugString() {
StringBuilder sb = new StringBuilder();
int playerCounter = 0;
HashMap classCounter = new HashMap<>();
-
+
for (Map> map1 : INSTANCES.values()) {
playerCounter++;
for (Map map2 : map1.values()) {
for (CoreAbility coreAbil : map2.values()) {
String simpleName = coreAbil.getClass().getSimpleName();
-
+
if (classCounter.containsKey(simpleName)) {
classCounter.put(simpleName, classCounter.get(simpleName) + 1);
} else {
@@ -585,7 +696,7 @@ public abstract class CoreAbility implements Ability {
}
}
}
-
+
for (Set set : INSTANCES_BY_CLASS.values()) {
for (CoreAbility coreAbil : set) {
String simpleName = coreAbil.getClass().getSimpleName();
@@ -596,7 +707,7 @@ public abstract class CoreAbility implements Ability {
}
}
}
-
+
sb.append("Class->UUID's in memory: " + playerCounter + "\n");
sb.append("Abilities in memory:\n");
for (String className : classCounter.keySet()) {
@@ -604,4 +715,9 @@ public abstract class CoreAbility implements Ability {
}
return sb.toString();
}
+
+ public static double getDefaultCollisionRadius() {
+ return DEFAULT_COLLISION_RADIUS;
+ }
+
}
diff --git a/src/com/projectkorra/projectkorra/ability/EarthAbility.java b/src/com/projectkorra/projectkorra/ability/EarthAbility.java
index e3f7a0e0..c62bd0f6 100644
--- a/src/com/projectkorra/projectkorra/ability/EarthAbility.java
+++ b/src/com/projectkorra/projectkorra/ability/EarthAbility.java
@@ -21,6 +21,7 @@ import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.BendingPlayer;
import com.projectkorra.projectkorra.Element;
import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.configuration.ConfigManager;
import com.projectkorra.projectkorra.earthbending.EarthPassive;
import com.projectkorra.projectkorra.earthbending.LavaFlow;
@@ -30,6 +31,7 @@ import com.projectkorra.projectkorra.firebending.Illumination;
import com.projectkorra.projectkorra.util.BlockSource;
import com.projectkorra.projectkorra.util.Information;
import com.projectkorra.projectkorra.util.ParticleEffect;
+import com.projectkorra.projectkorra.util.ParticleEffect.ParticleData;
import com.projectkorra.projectkorra.util.TempBlock;
public abstract class EarthAbility extends ElementalAbility {
@@ -82,6 +84,15 @@ public abstract class EarthAbility extends ElementalAbility {
return false;
}
+ @Override
+ public void handleCollision(Collision collision) {
+ super.handleCollision(collision);
+ if (collision.isRemovingFirst()) {
+ ParticleData particleData = (ParticleEffect.ParticleData) new ParticleEffect.BlockData(Material.DIRT, (byte) 0);
+ ParticleEffect.BLOCK_CRACK.display(particleData, 1F, 1F, 1F, 0.1F, 10, collision.getLocationFirst(), 50);
+ }
+ }
+
public static boolean isEarthbendable(Material material) {
return isEarth(material) || isMetal(material) || isSand(material) || isLava(material);
}
diff --git a/src/com/projectkorra/projectkorra/ability/FireAbility.java b/src/com/projectkorra/projectkorra/ability/FireAbility.java
index b5d2af58..dbfcdfde 100644
--- a/src/com/projectkorra/projectkorra/ability/FireAbility.java
+++ b/src/com/projectkorra/projectkorra/ability/FireAbility.java
@@ -19,11 +19,13 @@ import org.bukkit.inventory.ItemStack;
import com.projectkorra.projectkorra.Element;
import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.configuration.ConfigManager;
import com.projectkorra.projectkorra.firebending.BlazeArc;
import com.projectkorra.projectkorra.firebending.HeatControl;
import com.projectkorra.projectkorra.util.Information;
import com.projectkorra.projectkorra.util.ParticleEffect;
+import com.projectkorra.projectkorra.util.ParticleEffect.ParticleData;
import com.projectkorra.rpg.RPGMethods;
public abstract class FireAbility extends ElementalAbility {
@@ -60,6 +62,15 @@ public abstract class FireAbility extends ElementalAbility {
public Element getElement() {
return Element.FIRE;
}
+
+ @Override
+ public void handleCollision(Collision collision) {
+ super.handleCollision(collision);
+ if (collision.isRemovingFirst()) {
+ ParticleData particleData = (ParticleEffect.ParticleData) new ParticleEffect.BlockData(Material.FIRE, (byte) 0);
+ ParticleEffect.BLOCK_CRACK.display(particleData, 1F, 1F, 1F, 0.1F, 10, collision.getLocationFirst(), 50);
+ }
+ }
public double getDayFactor(double value) {
return player != null ? getDayFactor(value, player.getWorld()) : 1;
@@ -140,11 +151,15 @@ public abstract class FireAbility extends ElementalAbility {
}
/**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ *
* Checks whether a location is within a FireShield.
*
* @param loc The location to check
* @return true If the location is inside a FireShield.
*/
+ @Deprecated
public static boolean isWithinFireShield(Location loc) {
List list = new ArrayList();
list.add("FireShield");
diff --git a/src/com/projectkorra/projectkorra/ability/WaterAbility.java b/src/com/projectkorra/projectkorra/ability/WaterAbility.java
index ff5fe1cc..740518f5 100644
--- a/src/com/projectkorra/projectkorra/ability/WaterAbility.java
+++ b/src/com/projectkorra/projectkorra/ability/WaterAbility.java
@@ -3,8 +3,11 @@ package com.projectkorra.projectkorra.ability;
import com.projectkorra.projectkorra.BendingPlayer;
import com.projectkorra.projectkorra.Element;
import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.util.BlockSource;
+import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
+import com.projectkorra.projectkorra.util.ParticleEffect.ParticleData;
import com.projectkorra.projectkorra.waterbending.PhaseChangeFreeze;
import com.projectkorra.projectkorra.waterbending.PhaseChangeMelt;
import com.projectkorra.projectkorra.waterbending.SurgeWall;
@@ -75,6 +78,15 @@ public abstract class WaterAbility extends ElementalAbility {
return false;
}
+ @Override
+ public void handleCollision(Collision collision) {
+ super.handleCollision(collision);
+ if (collision.isRemovingFirst()) {
+ ParticleData particleData = (ParticleEffect.ParticleData) new ParticleEffect.BlockData(Material.WATER, (byte) 0);
+ ParticleEffect.BLOCK_CRACK.display(particleData, 1F, 1F, 1F, 0.1F, 10, collision.getLocationFirst(), 50);
+ }
+ }
+
public boolean isIcebendable(Block block) {
return isIcebendable(block.getType());
}
@@ -301,22 +313,30 @@ public abstract class WaterAbility extends ElementalAbility {
}
/**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ *
* Removes all water spouts in a location within a certain radius.
*
* @param loc The location to use
* @param radius The radius around the location to remove spouts in
* @param source The player causing the removal
*/
+ @Deprecated
public static void removeWaterSpouts(Location loc, double radius, Player source) {
WaterSpout.removeSpouts(loc, radius, source);
}
/**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ *
* Removes all water spouts in a location with a radius of 1.5.
*
* @param loc The location to use
* @param source The player causing the removal
*/
+ @Deprecated
public static void removeWaterSpouts(Location loc, Player source) {
removeWaterSpouts(loc, 1.5, source);
}
diff --git a/src/com/projectkorra/projectkorra/ability/util/Collision.java b/src/com/projectkorra/projectkorra/ability/util/Collision.java
new file mode 100644
index 00000000..837cfbf1
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/ability/util/Collision.java
@@ -0,0 +1,86 @@
+package com.projectkorra.projectkorra.ability.util;
+
+import org.bukkit.Location;
+
+import com.projectkorra.projectkorra.ability.CoreAbility;
+
+/**
+ * A Collision is used to represent the collision between two CoreAbility
+ * objects.
+ *
+ * @see CollisionManager
+ */
+public class Collision {
+ private CoreAbility abilityFirst;
+ private CoreAbility abilitySecond;
+ private boolean removingFirst;
+ private boolean removingSecond;
+ private Location locationFirst;
+ private Location locationSecond;
+
+ public Collision(CoreAbility abilityFirst, CoreAbility abilitySecond, boolean removingFirst, boolean removingSecond, Location locationFirst, Location locationSecond) {
+ if (abilityFirst == null || abilitySecond == null) {
+ return;
+ }
+
+ this.abilityFirst = abilityFirst;
+ this.abilitySecond = abilitySecond;
+ this.removingFirst = removingFirst;
+ this.removingSecond = removingSecond;
+ this.locationFirst = locationFirst;
+ this.locationSecond = locationSecond;
+ }
+
+ public Collision(CoreAbility abilityFirst, CoreAbility abilitySecond, boolean removingFirst, boolean removingSecond) {
+ this(abilityFirst, abilitySecond, removingFirst, removingSecond, null, null);
+ }
+
+ public CoreAbility getAbilityFirst() {
+ return abilityFirst;
+ }
+
+ public void setAbilityFirst(CoreAbility abilityFirst) {
+ this.abilityFirst = abilityFirst;
+ }
+
+ public CoreAbility getAbilitySecond() {
+ return abilitySecond;
+ }
+
+ public void setAbilitySecond(CoreAbility abilitySecond) {
+ this.abilitySecond = abilitySecond;
+ }
+
+ public boolean isRemovingFirst() {
+ return removingFirst;
+ }
+
+ public void setRemovingFirst(boolean removingFirst) {
+ this.removingFirst = removingFirst;
+ }
+
+ public boolean isRemovingSecond() {
+ return removingSecond;
+ }
+
+ public void setRemovingSecond(boolean removingSecond) {
+ this.removingSecond = removingSecond;
+ }
+
+ public Location getLocationFirst() {
+ return locationFirst;
+ }
+
+ public void setLocationFirst(Location locationFirst) {
+ this.locationFirst = locationFirst;
+ }
+
+ public Location getLocationSecond() {
+ return locationSecond;
+ }
+
+ public void setLocationSecond(Location locationSecond) {
+ this.locationSecond = locationSecond;
+ }
+
+}
diff --git a/src/com/projectkorra/projectkorra/ability/util/CollisionInitializer.java b/src/com/projectkorra/projectkorra/ability/util/CollisionInitializer.java
new file mode 100644
index 00000000..d3057c1f
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/ability/util/CollisionInitializer.java
@@ -0,0 +1,176 @@
+package com.projectkorra.projectkorra.ability.util;
+
+import com.projectkorra.projectkorra.ability.CoreAbility;
+import com.projectkorra.projectkorra.airbending.AirBlast;
+import com.projectkorra.projectkorra.airbending.AirBubble;
+import com.projectkorra.projectkorra.airbending.AirCombo;
+import com.projectkorra.projectkorra.airbending.AirCombo.AirStream;
+import com.projectkorra.projectkorra.airbending.AirCombo.AirSweep;
+import com.projectkorra.projectkorra.airbending.AirFlight;
+import com.projectkorra.projectkorra.airbending.AirScooter;
+import com.projectkorra.projectkorra.airbending.AirShield;
+import com.projectkorra.projectkorra.airbending.AirSpout;
+import com.projectkorra.projectkorra.airbending.AirSuction;
+import com.projectkorra.projectkorra.airbending.AirSwipe;
+import com.projectkorra.projectkorra.airbending.Suffocate;
+import com.projectkorra.projectkorra.airbending.Tornado;
+import com.projectkorra.projectkorra.earthbending.Catapult;
+import com.projectkorra.projectkorra.earthbending.Collapse;
+import com.projectkorra.projectkorra.earthbending.EarthArmor;
+import com.projectkorra.projectkorra.earthbending.EarthBlast;
+import com.projectkorra.projectkorra.earthbending.EarthSmash;
+import com.projectkorra.projectkorra.earthbending.EarthTunnel;
+import com.projectkorra.projectkorra.earthbending.LavaFlow;
+import com.projectkorra.projectkorra.earthbending.RaiseEarth;
+import com.projectkorra.projectkorra.earthbending.Ripple;
+import com.projectkorra.projectkorra.earthbending.SandSpout;
+import com.projectkorra.projectkorra.firebending.BlazeArc;
+import com.projectkorra.projectkorra.firebending.Combustion;
+import com.projectkorra.projectkorra.firebending.FireBlast;
+import com.projectkorra.projectkorra.firebending.FireBlastCharged;
+import com.projectkorra.projectkorra.firebending.FireCombo;
+import com.projectkorra.projectkorra.firebending.FireCombo.FireKick;
+import com.projectkorra.projectkorra.firebending.FireCombo.FireSpin;
+import com.projectkorra.projectkorra.firebending.FireCombo.FireWheel;
+import com.projectkorra.projectkorra.firebending.FireJet;
+import com.projectkorra.projectkorra.firebending.FireShield;
+import com.projectkorra.projectkorra.firebending.Lightning;
+import com.projectkorra.projectkorra.firebending.WallOfFire;
+import com.projectkorra.projectkorra.waterbending.Bloodbending;
+import com.projectkorra.projectkorra.waterbending.HealingWaters;
+import com.projectkorra.projectkorra.waterbending.IceBlast;
+import com.projectkorra.projectkorra.waterbending.IceSpikeBlast;
+import com.projectkorra.projectkorra.waterbending.OctopusForm;
+import com.projectkorra.projectkorra.waterbending.PlantArmor;
+import com.projectkorra.projectkorra.waterbending.SurgeWall;
+import com.projectkorra.projectkorra.waterbending.SurgeWave;
+import com.projectkorra.projectkorra.waterbending.Torrent;
+import com.projectkorra.projectkorra.waterbending.TorrentWave;
+import com.projectkorra.projectkorra.waterbending.WaterBubble;
+import com.projectkorra.projectkorra.waterbending.WaterCombo;
+import com.projectkorra.projectkorra.waterbending.WaterCombo.IceBullet;
+import com.projectkorra.projectkorra.waterbending.WaterCombo.IceWave;
+import com.projectkorra.projectkorra.waterbending.WaterManipulation;
+import com.projectkorra.projectkorra.waterbending.WaterSpout;
+import com.projectkorra.projectkorra.waterbending.WaterSpoutWave;
+
+/**
+ * CollisionInitializer is used to create the default Collisions for a given
+ * CollisionManager.
+ *
+ * @see Collision
+ * @see CollisionManager
+ */
+public class CollisionInitializer {
+
+ private CollisionManager cm;
+
+ public CollisionInitializer(CollisionManager cm) {
+ this.cm = cm;
+ }
+
+ @SuppressWarnings("unused")
+ public void initializeCollisions() {
+ CoreAbility airBlast = CoreAbility.getAbility(AirBlast.class);
+ CoreAbility airBubble = CoreAbility.getAbility(AirBubble.class);
+ CoreAbility airCombo = CoreAbility.getAbility(AirCombo.class);
+ CoreAbility airFlight = CoreAbility.getAbility(AirFlight.class);
+ CoreAbility airScooter = CoreAbility.getAbility(AirScooter.class);
+ CoreAbility airShield = CoreAbility.getAbility(AirShield.class);
+ CoreAbility airSpout = CoreAbility.getAbility(AirSpout.class);
+ CoreAbility airStream = CoreAbility.getAbility(AirStream.class);
+ CoreAbility airSuction = CoreAbility.getAbility(AirSuction.class);
+ CoreAbility airSweep = CoreAbility.getAbility(AirSweep.class);
+ CoreAbility airSwipe = CoreAbility.getAbility(AirSwipe.class);
+ CoreAbility suffocate = CoreAbility.getAbility(Suffocate.class);
+ CoreAbility tornado = CoreAbility.getAbility(Tornado.class);
+
+ CoreAbility catapult = CoreAbility.getAbility(Catapult.class);
+ CoreAbility collapse = CoreAbility.getAbility(Collapse.class);
+ CoreAbility earthArmor = CoreAbility.getAbility(EarthArmor.class);
+ CoreAbility earthBlast = CoreAbility.getAbility(EarthBlast.class);
+ CoreAbility earthSmash = CoreAbility.getAbility(EarthSmash.class);
+ CoreAbility earthTunnel = CoreAbility.getAbility(EarthTunnel.class);
+ CoreAbility lavaFlow = CoreAbility.getAbility(LavaFlow.class);
+ CoreAbility raiseEarth = CoreAbility.getAbility(RaiseEarth.class);
+ CoreAbility ripple = CoreAbility.getAbility(Ripple.class);
+ CoreAbility sandSpout = CoreAbility.getAbility(SandSpout.class);
+
+ CoreAbility blazeArc = CoreAbility.getAbility(BlazeArc.class);
+ CoreAbility combustion = CoreAbility.getAbility(Combustion.class);
+ CoreAbility fireBlast = CoreAbility.getAbility(FireBlast.class);
+ CoreAbility fireBlastCharged = CoreAbility.getAbility(FireBlastCharged.class);
+ CoreAbility fireCombo = CoreAbility.getAbility(FireCombo.class);
+ CoreAbility fireJet = CoreAbility.getAbility(FireJet.class);
+ CoreAbility fireKick = CoreAbility.getAbility(FireKick.class);
+ CoreAbility fireSpin = CoreAbility.getAbility(FireSpin.class);
+ CoreAbility fireWheel = CoreAbility.getAbility(FireWheel.class);
+ CoreAbility fireShield = CoreAbility.getAbility(FireShield.class);
+ CoreAbility lightning = CoreAbility.getAbility(Lightning.class);
+ CoreAbility wallOfFire = CoreAbility.getAbility(WallOfFire.class);
+
+ CoreAbility bloodbending = CoreAbility.getAbility(Bloodbending.class);
+ CoreAbility healingWaters = CoreAbility.getAbility(HealingWaters.class);
+ CoreAbility iceBlast = CoreAbility.getAbility(IceBlast.class);
+ CoreAbility iceBullet = CoreAbility.getAbility(IceBullet.class);
+ CoreAbility iceWave = CoreAbility.getAbility(IceWave.class);
+ CoreAbility iceSpikeBlast = CoreAbility.getAbility(IceSpikeBlast.class);
+ CoreAbility octopusForm = CoreAbility.getAbility(OctopusForm.class);
+ CoreAbility plantArmor = CoreAbility.getAbility(PlantArmor.class);
+ CoreAbility surgeWall = CoreAbility.getAbility(SurgeWall.class);
+ CoreAbility surgeWave = CoreAbility.getAbility(SurgeWave.class);
+ CoreAbility torrent = CoreAbility.getAbility(Torrent.class);
+ CoreAbility torrentWave = CoreAbility.getAbility(TorrentWave.class);
+ CoreAbility waterBubble = CoreAbility.getAbility(WaterBubble.class);
+ CoreAbility waterCombo = CoreAbility.getAbility(WaterCombo.class);
+ CoreAbility waterManipulation = CoreAbility.getAbility(WaterManipulation.class);
+ CoreAbility waterSpout = CoreAbility.getAbility(WaterSpout.class);
+ CoreAbility waterSpoutWave = CoreAbility.getAbility(WaterSpoutWave.class);
+
+ CoreAbility[] smallDamageAbils = { airSwipe, earthBlast, waterManipulation, fireBlast, combustion, blazeArc };
+ CoreAbility[] abilitiesThatRemoveSmall = { earthSmash, airShield, airCombo, fireCombo, waterCombo, fireBlastCharged };
+ CoreAbility[] abilsThatRemoveSpouts = { airSwipe, earthBlast, waterManipulation, fireBlast, fireBlastCharged, earthSmash, fireCombo, airCombo, waterCombo };
+ CoreAbility[] damageComboAbils = { fireKick, fireSpin, fireWheel, airSweep, iceBullet };
+
+ // All small damaging abilities block each other
+ for (int i = 0; i < smallDamageAbils.length; i++) {
+ for (int j = i; j < smallDamageAbils.length; j++) {
+ cm.add(new Collision(smallDamageAbils[i], smallDamageAbils[j], true, true));
+ }
+ }
+
+ // All combos block each other
+ for (int i = 0; i < damageComboAbils.length; i++) {
+ for (int j = i; j < damageComboAbils.length; j++) {
+ cm.add(new Collision(damageComboAbils[i], damageComboAbils[j], true, true));
+ }
+ }
+
+ // These abilities remove all small damaging abilities
+ for (CoreAbility abilThatRemoves : abilitiesThatRemoveSmall) {
+ for (CoreAbility smallDamageAbil : smallDamageAbils) {
+ cm.add(new Collision(abilThatRemoves, smallDamageAbil, false, true));
+ }
+ }
+
+ for (CoreAbility spoutDestroyAbil : abilsThatRemoveSpouts) {
+ cm.add(new Collision(spoutDestroyAbil, airSpout, false, true));
+ cm.add(new Collision(spoutDestroyAbil, waterSpout, false, true));
+ cm.add(new Collision(spoutDestroyAbil, sandSpout, false, true));
+ }
+
+ cm.add(new Collision(airShield, airBlast, false, true));
+ cm.add(new Collision(airShield, airSuction, false, true));
+ cm.add(new Collision(airShield, airStream, false, true));
+ for (CoreAbility comboAbil : damageComboAbils) {
+ cm.add(new Collision(airShield, comboAbil, false, true));
+ }
+
+ cm.add(new Collision(fireShield, fireBlast, false, true));
+ cm.add(new Collision(fireShield, fireBlastCharged, false, true));
+ cm.add(new Collision(fireShield, waterManipulation, false, true));
+ cm.add(new Collision(fireShield, earthBlast, false, true));
+ cm.add(new Collision(fireShield, airSweep, false, true));
+ }
+
+}
diff --git a/src/com/projectkorra/projectkorra/ability/util/CollisionManager.java b/src/com/projectkorra/projectkorra/ability/util/CollisionManager.java
new file mode 100644
index 00000000..5a7d6ba8
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/ability/util/CollisionManager.java
@@ -0,0 +1,245 @@
+package com.projectkorra.projectkorra.ability.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import com.projectkorra.projectkorra.ProjectKorra;
+import com.projectkorra.projectkorra.ability.CoreAbility;
+import com.projectkorra.projectkorra.event.AbilityCollisionEvent;
+
+/**
+ * A CollisionManager is used to monitor possible collisions between all
+ * CoreAbilities. Use {@link #add(Collision)} to begin monitoring for collision
+ * between two abilities, as shown in {@link CollisionInitializer}.
+ *
+ * For a CoreAbility to collide properly, the {@link CoreAbility#isCollidable()}
+ * , {@link CoreAbility#getCollisionRadius()},
+ * {@link CoreAbility#getLocations()}, and {@link CoreAbility#handleCollision()}
+ * should be overridden if necessary.
+ *
+ * During a Collision the {@link AbilityCollisionEvent} is called, then if not
+ * cancelled, abilityFirst.handleCollision, and finally
+ * abilitySecond.handleCollision.
+ */
+public class CollisionManager {
+
+ /*
+ * If true an ability instance can remove multiple other instances on a
+ * single tick. e.g. 3 Colliding WaterManipulations can all be removed
+ * instantly, rather than just 2.
+ */
+ private boolean removeMultipleInstances;
+
+ /*
+ * The amount of ticks in between checking for collisions. Higher values
+ * reduce lag but are less accurate in detection.
+ */
+ private long detectionDelay;
+
+ /*
+ * The amount of ticks that an ability must be alive before considered as
+ * collidable. Some CoreAbilities are started even though they will be
+ * removed on the next tick in progress, in these cases we do not want to
+ * consider those abilities for collision.
+ */
+ private long minAbilityTickAlive;
+
+ /*
+ * Used for efficiency. The distance that we can guarantee that two
+ * abilities will not collide so that we can stop comparing locations early.
+ * For example, two Torrents that are thousands of blocks apart should not
+ * be fully checked.
+ */
+ private double certainNoCollisionDistance;
+
+ private ArrayList collisions;
+ private BukkitRunnable detectionRunnable;
+
+ public CollisionManager() {
+ this.removeMultipleInstances = true;
+ this.detectionDelay = 1;
+ this.minAbilityTickAlive = 3;
+ this.certainNoCollisionDistance = 100;
+ collisions = new ArrayList<>();
+ }
+
+ private void detectCollisions() {
+ HashMap> locationsCache = new HashMap<>();
+
+ for (Collision collision : collisions) {
+ Collection extends CoreAbility> instancesFirst = CoreAbility.getAbilities(collision.getAbilityFirst().getClass());
+ Collection extends CoreAbility> instancesSecond = CoreAbility.getAbilities(collision.getAbilitySecond().getClass());
+ HashSet alreadyCollided = new HashSet();
+ double certainNoCollisionDistSquared = Math.pow(certainNoCollisionDistance, 2);
+
+ for (CoreAbility abilityFirst : instancesFirst) {
+ if (abilityFirst.getPlayer() == null || alreadyCollided.contains(abilityFirst) || !abilityFirst.isCollidable() || abilityFirst.getCurrentTick() - abilityFirst.getStartTick() < minAbilityTickAlive) {
+ continue;
+ }
+
+ if (!locationsCache.containsKey(abilityFirst)) {
+ locationsCache.put(abilityFirst, abilityFirst.getLocations());
+ }
+ List locationsFirst = locationsCache.get(abilityFirst);
+ if (locationsFirst == null) {
+ continue;
+ }
+
+ for (CoreAbility abilitySecond : instancesSecond) {
+ if (abilitySecond.getPlayer() == null || alreadyCollided.contains(abilitySecond) || !abilitySecond.isCollidable() || abilitySecond.getCurrentTick() - abilitySecond.getStartTick() < minAbilityTickAlive) {
+ continue;
+ } else if (abilityFirst.getPlayer().equals(abilitySecond.getPlayer())) {
+ continue;
+ }
+
+ if (!locationsCache.containsKey(abilitySecond)) {
+ locationsCache.put(abilitySecond, abilitySecond.getLocations());
+ }
+ List locationsSecond = locationsCache.get(abilitySecond);
+ if (locationsSecond == null) {
+ continue;
+ }
+
+ boolean collided = false;
+ boolean certainNoCollision = false; // Used for efficiency
+ Location locationFirst = null;
+ Location locationSecond = null;
+ double requiredDist = abilityFirst.getCollisionRadius() + abilitySecond.getCollisionRadius();
+ double requiredDistSquared = Math.pow(requiredDist, 2);
+
+ for (int i = 0; i < locationsFirst.size(); i++) {
+ locationFirst = locationsFirst.get(i);
+ if (locationFirst == null) {
+ continue;
+ }
+ for (int j = 0; j < locationsSecond.size(); j++) {
+ locationSecond = locationsSecond.get(j);
+ if (locationSecond == null) {
+ continue;
+ }
+
+ double distSquared = locationFirst.distanceSquared(locationSecond);
+ if (distSquared <= requiredDistSquared) {
+ collided = true;
+ break;
+ } else if (distSquared >= certainNoCollisionDistSquared) {
+ certainNoCollision = true;
+ break;
+ }
+ }
+ if (collided || certainNoCollision) {
+ break;
+ }
+ }
+
+ if (collided) {
+ Collision forwardCollision = new Collision(abilityFirst, abilitySecond, collision.isRemovingFirst(), collision.isRemovingSecond(), locationFirst, locationSecond);
+ Collision reverseCollision = new Collision(abilitySecond, abilityFirst, collision.isRemovingSecond(), collision.isRemovingFirst(), locationSecond, locationFirst);
+ AbilityCollisionEvent event = new AbilityCollisionEvent(forwardCollision);
+ Bukkit.getServer().getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ continue;
+ }
+ abilityFirst.handleCollision(forwardCollision);
+ abilitySecond.handleCollision(reverseCollision);
+ if (!removeMultipleInstances) {
+ alreadyCollided.add(abilityFirst);
+ alreadyCollided.add(abilitySecond);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds a new Collision to the CollisionManager so that two abilities can be
+ * checked for collisions.
+ *
+ * @param collision a Collision containing two CoreAbility classes
+ */
+ public void add(Collision collision) {
+ collisions.add(collision);
+ }
+
+ /**
+ * Begins a BukkitRunnable to check for Collisions.
+ */
+ public void startCollisionDetection() {
+ stopCollisionDetection();
+ detectionRunnable = new BukkitRunnable() {
+ @Override
+ public void run() {
+ detectCollisions();
+ }
+ };
+ detectionRunnable.runTaskTimer(ProjectKorra.plugin, 0L, detectionDelay);
+ }
+
+ /**
+ * Stops the collision detecting BukkitRunnable.
+ */
+ public void stopCollisionDetection() {
+ if (detectionRunnable != null) {
+ detectionRunnable.cancel();
+ detectionRunnable = null;
+ }
+ }
+
+ public boolean isRemoveMultipleInstances() {
+ return removeMultipleInstances;
+ }
+
+ public void setRemoveMultipleInstances(boolean removeMultipleInstances) {
+ this.removeMultipleInstances = removeMultipleInstances;
+ }
+
+ public long getDetectionDelay() {
+ return detectionDelay;
+ }
+
+ public void setDetectionDelay(long detectionDelay) {
+ this.detectionDelay = detectionDelay;
+ }
+
+ public long getMinAbilityTickAlive() {
+ return minAbilityTickAlive;
+ }
+
+ public void setMinAbilityTickAlive(long minAbilityTickAlive) {
+ this.minAbilityTickAlive = minAbilityTickAlive;
+ }
+
+ public double getCertainNoCollisionDistance() {
+ return certainNoCollisionDistance;
+ }
+
+ public void setCertainNoCollisionDistance(double certainNoCollisionDistance) {
+ this.certainNoCollisionDistance = certainNoCollisionDistance;
+ }
+
+ public ArrayList getCollisions() {
+ return collisions;
+ }
+
+ public void setCollisions(ArrayList collisions) {
+ this.collisions = collisions;
+ }
+
+ public BukkitRunnable getDetectionRunnable() {
+ return detectionRunnable;
+ }
+
+ public void setDetectionRunnable(BukkitRunnable detectionRunnable) {
+ this.detectionRunnable = detectionRunnable;
+ }
+
+}
diff --git a/src/com/projectkorra/projectkorra/ability/util/ComboManager.java b/src/com/projectkorra/projectkorra/ability/util/ComboManager.java
index 613c30c0..874c1f96 100644
--- a/src/com/projectkorra/projectkorra/ability/util/ComboManager.java
+++ b/src/com/projectkorra/projectkorra/ability/util/ComboManager.java
@@ -15,12 +15,22 @@ import com.projectkorra.projectkorra.Element.SubElement;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.ComboAbility;
import com.projectkorra.projectkorra.ability.CoreAbility;
-import com.projectkorra.projectkorra.airbending.AirCombo;
-import com.projectkorra.projectkorra.chiblocking.ChiCombo;
+import com.projectkorra.projectkorra.airbending.AirCombo.AirStream;
+import com.projectkorra.projectkorra.airbending.AirCombo.AirSweep;
+import com.projectkorra.projectkorra.airbending.AirCombo.Twister;
+import com.projectkorra.projectkorra.chiblocking.ChiCombo.Immobilize;
import com.projectkorra.projectkorra.configuration.ConfigManager;
-import com.projectkorra.projectkorra.firebending.FireCombo;
+import com.projectkorra.projectkorra.firebending.FireCombo.FireKick;
+import com.projectkorra.projectkorra.firebending.FireCombo.FireSpin;
+import com.projectkorra.projectkorra.firebending.FireCombo.FireWheel;
+import com.projectkorra.projectkorra.firebending.FireCombo.JetBlast;
+import com.projectkorra.projectkorra.firebending.FireCombo.JetBlaze;
import com.projectkorra.projectkorra.util.ClickType;
-import com.projectkorra.projectkorra.waterbending.WaterCombo;
+import com.projectkorra.projectkorra.util.ReflectionHandler;
+import com.projectkorra.projectkorra.waterbending.WaterCombo.IceBullet;
+import com.projectkorra.projectkorra.waterbending.WaterCombo.IceBulletLeftClick;
+import com.projectkorra.projectkorra.waterbending.WaterCombo.IceBulletRightClick;
+import com.projectkorra.projectkorra.waterbending.WaterCombo.IceWave;
public class ComboManager {
@@ -42,7 +52,7 @@ public class ComboManager {
fireKick.add(new AbilityInformation("FireBlast", ClickType.LEFT_CLICK));
fireKick.add(new AbilityInformation("FireBlast", ClickType.SHIFT_DOWN));
fireKick.add(new AbilityInformation("FireBlast", ClickType.LEFT_CLICK));
- COMBO_ABILITIES.put("FireKick", new ComboAbilityInfo("FireKick", fireKick, FireCombo.class));
+ COMBO_ABILITIES.put("FireKick", new ComboAbilityInfo("FireKick", fireKick, FireKick.class));
DESCRIPTIONS.put("FireKick", ConfigManager.languageConfig.get().getString("Abilities.Fire.Combo.FireKick.Description"));
INSTRUCTIONS.put("FireKick", "FireBlast > FireBlast > (Hold Shift) > FireBlast.");
}
@@ -54,7 +64,7 @@ public class ComboManager {
fireSpin.add(new AbilityInformation("FireShield", ClickType.LEFT_CLICK));
fireSpin.add(new AbilityInformation("FireShield", ClickType.SHIFT_DOWN));
fireSpin.add(new AbilityInformation("FireShield", ClickType.SHIFT_UP));
- COMBO_ABILITIES.put("FireSpin", new ComboAbilityInfo("FireSpin", fireSpin, FireCombo.class));
+ COMBO_ABILITIES.put("FireSpin", new ComboAbilityInfo("FireSpin", fireSpin, FireSpin.class));
DESCRIPTIONS.put("FireSpin", ConfigManager.languageConfig.get().getString("Abilities.Fire.Combo.FireSpin.Description"));
INSTRUCTIONS.put("FireSpin", "FireBlast > FireBlast > FireShield > (Tap Shift).");
}
@@ -68,7 +78,7 @@ public class ComboManager {
jetBlast.add(new AbilityInformation("FireShield", ClickType.SHIFT_DOWN));
jetBlast.add(new AbilityInformation("FireShield", ClickType.SHIFT_UP));
jetBlast.add(new AbilityInformation("FireJet", ClickType.LEFT_CLICK));
- COMBO_ABILITIES.put("JetBlast", new ComboAbilityInfo("JetBlast", jetBlast, FireCombo.class));
+ COMBO_ABILITIES.put("JetBlast", new ComboAbilityInfo("JetBlast", jetBlast, JetBlast.class));
DESCRIPTIONS.put("JetBlast", ConfigManager.languageConfig.get().getString("Abilities.Fire.Combo.JetBlast.Description"));
INSTRUCTIONS.put("JetBlast", "FireJet (Tap Shift) > FireJet (Tap Shift) > FireShield (Tap Shift) > FireJet.");
}
@@ -82,7 +92,7 @@ public class ComboManager {
jetBlaze.add(new AbilityInformation("Blaze", ClickType.SHIFT_DOWN));
jetBlaze.add(new AbilityInformation("Blaze", ClickType.SHIFT_UP));
jetBlaze.add(new AbilityInformation("FireJet", ClickType.LEFT_CLICK));
- COMBO_ABILITIES.put("JetBlaze", new ComboAbilityInfo("JetBlaze", jetBlaze, FireCombo.class));
+ COMBO_ABILITIES.put("JetBlaze", new ComboAbilityInfo("JetBlaze", jetBlaze, JetBlaze.class));
DESCRIPTIONS.put("JetBlaze", ConfigManager.languageConfig.get().getString("Abilities.Fire.Combo.JetBlaze.Description"));
INSTRUCTIONS.put("JetBlaze", "FireJet (Tap Shift) > FireJet (Tap Shift) > Blaze (Tap Shift) > FireJet.");
}
@@ -93,7 +103,7 @@ public class ComboManager {
fireWheel.add(new AbilityInformation("FireShield", ClickType.RIGHT_CLICK_BLOCK));
fireWheel.add(new AbilityInformation("FireShield", ClickType.RIGHT_CLICK_BLOCK));
fireWheel.add(new AbilityInformation("Blaze", ClickType.SHIFT_UP));
- COMBO_ABILITIES.put("FireWheel", new ComboAbilityInfo("FireWheel", fireWheel, FireCombo.class));
+ COMBO_ABILITIES.put("FireWheel", new ComboAbilityInfo("FireWheel", fireWheel, FireWheel.class));
DESCRIPTIONS.put("FireWheel", ConfigManager.languageConfig.get().getString("Abilities.Fire.Combo.FireWheel.Description"));
INSTRUCTIONS.put("FireWheel", "FireShield (Hold Shift) > Right Click a block in front of you twice > Switch to Blaze > Release Shift.");
}
@@ -104,7 +114,7 @@ public class ComboManager {
twister.add(new AbilityInformation("AirShield", ClickType.SHIFT_UP));
twister.add(new AbilityInformation("Tornado", ClickType.SHIFT_DOWN));
twister.add(new AbilityInformation("AirBlast", ClickType.LEFT_CLICK));
- COMBO_ABILITIES.put("Twister", new ComboAbilityInfo("Twister", twister, AirCombo.class));
+ COMBO_ABILITIES.put("Twister", new ComboAbilityInfo("Twister", twister, Twister.class));
DESCRIPTIONS.put("Twister", ConfigManager.languageConfig.get().getString("Abilities.Air.Combo.Twister.Description"));
INSTRUCTIONS.put("Twister", "AirShield (Tap Shift) > Tornado (Hold Shift) > AirBlast (Left Click)");
}
@@ -114,7 +124,7 @@ public class ComboManager {
airStream.add(new AbilityInformation("AirShield", ClickType.SHIFT_DOWN));
airStream.add(new AbilityInformation("AirSuction", ClickType.LEFT_CLICK));
airStream.add(new AbilityInformation("AirBlast", ClickType.LEFT_CLICK));
- COMBO_ABILITIES.put("AirStream", new ComboAbilityInfo("AirStream", airStream, AirCombo.class));
+ COMBO_ABILITIES.put("AirStream", new ComboAbilityInfo("AirStream", airStream, AirStream.class));
DESCRIPTIONS.put("AirStream", ConfigManager.languageConfig.get().getString("Abilities.Air.Combo.AirStream.Description"));
INSTRUCTIONS.put("AirStream", "AirShield (Hold Shift) > AirSuction (Left Click) > AirBlast (Left Click)");
}
@@ -125,7 +135,7 @@ public class ComboManager {
airSweep.add(new AbilityInformation("AirSwipe", ClickType.LEFT_CLICK));
airSweep.add(new AbilityInformation("AirBurst", ClickType.SHIFT_DOWN));
airSweep.add(new AbilityInformation("AirBurst", ClickType.LEFT_CLICK));
- COMBO_ABILITIES.put("AirSweep", new ComboAbilityInfo("AirSweep", airSweep, AirCombo.class));
+ COMBO_ABILITIES.put("AirSweep", new ComboAbilityInfo("AirSweep", airSweep, AirSweep.class));
DESCRIPTIONS.put("AirSweep", ConfigManager.languageConfig.get().getString("Abilities.Air.Combo.AirSweep.Description"));
INSTRUCTIONS.put("AirSweep", "AirSwipe (Left Click) > AirSwipe (Left Click) > AirBurst (Hold Shift) > AirBurst (Left Click)");
}
@@ -134,7 +144,7 @@ public class ComboManager {
ArrayList iceWave = new ArrayList<>();
iceWave.add(new AbilityInformation("WaterSpout", ClickType.SHIFT_UP));
iceWave.add(new AbilityInformation("PhaseChange", ClickType.LEFT_CLICK));
- COMBO_ABILITIES.put("IceWave", new ComboAbilityInfo("IceWave", iceWave, WaterCombo.class));
+ COMBO_ABILITIES.put("IceWave", new ComboAbilityInfo("IceWave", iceWave, IceWave.class));
DESCRIPTIONS.put("IceWave", ConfigManager.languageConfig.get().getString("Abilities.Water.Combo.IceWave.Description"));
INSTRUCTIONS.put("IceWave", "Create a WaterSpout Wave > PhaseChange (Left Click)");
}
@@ -144,16 +154,16 @@ public class ComboManager {
iceBullet.add(new AbilityInformation("WaterBubble", ClickType.SHIFT_DOWN));
iceBullet.add(new AbilityInformation("WaterBubble", ClickType.SHIFT_UP));
iceBullet.add(new AbilityInformation("IceBlast", ClickType.SHIFT_DOWN));
- COMBO_ABILITIES.put("IceBullet", new ComboAbilityInfo("IceBullet", iceBullet, WaterCombo.class));
+ COMBO_ABILITIES.put("IceBullet", new ComboAbilityInfo("IceBullet", iceBullet, IceBullet.class));
DESCRIPTIONS.put("IceBullet", ConfigManager.languageConfig.get().getString("Abilities.Water.Combo.IceBullet.Description"));
INSTRUCTIONS.put("IceBullet", "WaterBubble (Tap Shift) > IceBlast (Hold Shift) > Wait for ice to Form > Then alternate between Left and Right click with IceBlast");
ArrayList iceBulletLeft = new ArrayList<>();
iceBulletLeft.add(new AbilityInformation("IceBlast", ClickType.LEFT_CLICK));
- COMBO_ABILITIES.put("IceBulletLeftClick", new ComboAbilityInfo("IceBulletLeftClick", iceBulletLeft, WaterCombo.class));
+ COMBO_ABILITIES.put("IceBulletLeftClick", new ComboAbilityInfo("IceBulletLeftClick", iceBulletLeft, IceBulletLeftClick.class));
ArrayList iceBulletRight = new ArrayList<>();
iceBulletRight.add(new AbilityInformation("IceBlast", ClickType.RIGHT_CLICK_BLOCK));
- COMBO_ABILITIES.put("IceBulletRightClick", new ComboAbilityInfo("IceBulletRightClick", iceBulletRight, WaterCombo.class));
+ COMBO_ABILITIES.put("IceBulletRightClick", new ComboAbilityInfo("IceBulletRightClick", iceBulletRight, IceBulletRightClick.class));
}
if (ConfigManager.defaultConfig.get().getBoolean("Abilities.Chi.ChiCombo.Immobilize.Enabled")) {
@@ -162,7 +172,7 @@ public class ComboManager {
immobilize.add(new AbilityInformation("SwiftKick", ClickType.LEFT_CLICK_ENTITY));
immobilize.add(new AbilityInformation("QuickStrike", ClickType.LEFT_CLICK_ENTITY));
immobilize.add(new AbilityInformation("QuickStrike", ClickType.LEFT_CLICK_ENTITY));
- COMBO_ABILITIES.put("Immobilize", new ComboAbilityInfo("Immobilize", immobilize, ChiCombo.class));
+ COMBO_ABILITIES.put("Immobilize", new ComboAbilityInfo("Immobilize", immobilize, Immobilize.class));
DESCRIPTIONS.put("Immobilize", ConfigManager.languageConfig.get().getString("Abilities.Chi.Combo.Immobilize.Description"));
INSTRUCTIONS.put("Immobilize", "QuickStrike (Left Click) > SwiftKick (Left Click) > QuickStrike (Left Click) > QuickStrike (Left Click)");
}
@@ -191,17 +201,15 @@ public class ComboManager {
}
new BukkitRunnable() {
-
@Override
public void run() {
- if (comboAbil.getComboType().equals(FireCombo.class)) {
- new FireCombo(player, comboAbil.getName());
- } else if (comboAbil.getComboType().equals(AirCombo.class)) {
- new AirCombo(player, comboAbil.getName());
- } else if (comboAbil.getComboType().equals(WaterCombo.class)) {
- new WaterCombo(player, comboAbil.getName());
- } else if (comboAbil.getComboType().equals(ChiCombo.class)) {
- new ChiCombo(player, comboAbil.getName());
+ if (comboAbil.getComboType() instanceof Class) {
+ Class> clazz = (Class>) comboAbil.getComboType();
+ try {
+ ReflectionHandler.instantiateObject(clazz, player);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
} else {
if (comboAbil.getComboType() instanceof ComboAbility) {
((ComboAbility) comboAbil.getComboType()).createNewComboInstance(player);
@@ -209,10 +217,8 @@ public class ComboManager {
}
}
}
-
+
}.runTaskLater(ProjectKorra.plugin, 1L);
-
-
}
/**
diff --git a/src/com/projectkorra/projectkorra/airbending/AirBlast.java b/src/com/projectkorra/projectkorra/airbending/AirBlast.java
index 7ff6deaa..3210074b 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirBlast.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirBlast.java
@@ -26,6 +26,7 @@ import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.CoreAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
@@ -80,7 +81,7 @@ public class AirBlast extends AirAbility {
if (entity != null) {
this.direction = GeneralMethods.getDirection(origin, entity.getLocation()).normalize();
} else {
- this.direction = GeneralMethods.getDirection(origin, GeneralMethods.getTargetedLocation(player, range)) .normalize();
+ this.direction = GeneralMethods.getDirection(origin, GeneralMethods.getTargetedLocation(player, range)).normalize();
}
} else {
origin = player.getEyeLocation();
@@ -126,7 +127,7 @@ public class AirBlast extends AirAbility {
this.canOpenDoors = getConfig().getBoolean("Abilities.Air.AirBlast.CanOpenDoors");
this.canPressButtons = getConfig().getBoolean("Abilities.Air.AirBlast.CanPressButtons");
this.canCoolLava = getConfig().getBoolean("Abilities.Air.AirBlast.CanCoolLava");
-
+
this.isFromOtherOrigin = false;
this.showParticles = true;
this.random = new Random();
@@ -172,7 +173,7 @@ public class AirBlast extends AirAbility {
}
ORIGINS.put(player, location);
-
+
}
private void advanceLocation() {
@@ -207,7 +208,7 @@ public class AirBlast extends AirAbility {
push.setY(max);
}
}
- if(location.getWorld().equals(origin.getWorld())) {
+ if (location.getWorld().equals(origin.getWorld())) {
factor *= 1 - location.distance(origin) / (2 * range);
}
@@ -291,8 +292,7 @@ public class AirBlast extends AirAbility {
continue;
}
- Material doorTypes[] = { Material.WOODEN_DOOR, Material.SPRUCE_DOOR, Material.BIRCH_DOOR, Material.JUNGLE_DOOR,
- Material.ACACIA_DOOR, Material.DARK_OAK_DOOR };
+ Material doorTypes[] = { Material.WOODEN_DOOR, Material.SPRUCE_DOOR, Material.BIRCH_DOOR, Material.JUNGLE_DOOR, Material.ACACIA_DOOR, Material.DARK_OAK_DOOR };
if (Arrays.asList(doorTypes).contains(block.getType()) && canOpenDoors) {
if (block.getData() >= 8) {
block = block.getRelative(BlockFace.DOWN);
@@ -400,12 +400,13 @@ public class AirBlast extends AirAbility {
}
/*
- * If a player presses shift and AirBlasts straight down then the AirBlast's location gets
- * messed up and reading the distance returns Double.NaN. If we don't remove this instance
- * then the AirBlast will never be removed.
+ * If a player presses shift and AirBlasts straight down then the
+ * AirBlast's location gets messed up and reading the distance returns
+ * Double.NaN. If we don't remove this instance then the AirBlast will
+ * never be removed.
*/
double dist = 0;
- if(location.getWorld().equals(origin.getWorld())) {
+ if (location.getWorld().equals(origin.getWorld())) {
dist = location.distance(origin);
}
if (Double.isNaN(dist) || dist > range) {
@@ -421,6 +422,11 @@ public class AirBlast extends AirAbility {
return;
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean removeAirBlastsAroundPoint(Location location, double radius) {
boolean removed = false;
for (AirBlast airBlast : getAbilities(AirBlast.class)) {
@@ -449,7 +455,7 @@ public class AirBlast extends AirAbility {
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -460,6 +466,11 @@ public class AirBlast extends AirAbility {
return false;
}
+ @Override
+ public double getCollisionRadius() {
+ return getRadius();
+ }
+
public Location getOrigin() {
return origin;
}
@@ -619,13 +630,13 @@ public class AirBlast extends AirAbility {
public void setParticles(int particles) {
this.particles = particles;
}
-
+
public static int getSelectParticles() {
return getConfig().getInt("Abilities.Air.AirBlast.SelectParticles");
}
-
+
public static double getSelectRange() {
return getConfig().getInt("Abilities.Air.AirBlast.SelectRange");
}
-
+
}
diff --git a/src/com/projectkorra/projectkorra/airbending/AirBubble.java b/src/com/projectkorra/projectkorra/airbending/AirBubble.java
index 5c929612..3c600293 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirBubble.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirBubble.java
@@ -1,11 +1,7 @@
package com.projectkorra.projectkorra.airbending;
-import com.projectkorra.projectkorra.BendingPlayer;
-import com.projectkorra.projectkorra.Element;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ability.AirAbility;
-import com.projectkorra.projectkorra.ability.WaterAbility;
-import com.projectkorra.projectkorra.waterbending.WaterManipulation;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -14,8 +10,11 @@ import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import com.projectkorra.projectkorra.BendingPlayer;
+import com.projectkorra.projectkorra.Element;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.AirAbility;
+import com.projectkorra.projectkorra.waterbending.WaterManipulation;
public class AirBubble extends AirAbility {
@@ -27,7 +26,7 @@ public class AirBubble extends AirAbility {
public AirBubble(Player player) {
super(player);
-
+
this.radius = 0;
this.airRadius = getConfig().getDouble("Abilities.Air.AirBubble.Radius");
this.waterRadius = getConfig().getDouble("Abilities.Water.WaterBubble.Radius");
@@ -50,7 +49,7 @@ public class AirBubble extends AirAbility {
if (bPlayer == null) {
continue;
}
-
+
String name = bPlayer.getBoundAbilityName();
if (name.equalsIgnoreCase("AirBubble") | name.equalsIgnoreCase("WaterBubble")) {
if (!hasAbility(player, AirBubble.class) && player.isSneaking()) {
@@ -94,7 +93,7 @@ public class AirBubble extends AirAbility {
} else {
radius = waterRadius;
}
-
+
if (airRadius > radius && bPlayer.hasElement(Element.AIR)) {
radius = airRadius;
}
@@ -129,8 +128,6 @@ public class AirBubble extends AirAbility {
}
}
}
-
- WaterAbility.removeWaterSpouts(location, radius, player);
}
@Override
@@ -157,7 +154,7 @@ public class AirBubble extends AirAbility {
public long getCooldown() {
return 0;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -168,6 +165,11 @@ public class AirBubble extends AirAbility {
return false;
}
+ @Override
+ public double getCollisionRadius() {
+ return getRadius();
+ }
+
public boolean isWaterBubble() {
return waterBubble;
}
diff --git a/src/com/projectkorra/projectkorra/airbending/AirBurst.java b/src/com/projectkorra/projectkorra/airbending/AirBurst.java
index 615fc50e..5fc6c4be 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirBurst.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirBurst.java
@@ -1,8 +1,7 @@
package com.projectkorra.projectkorra.airbending;
-import com.projectkorra.projectkorra.ProjectKorra;
-import com.projectkorra.projectkorra.ability.AirAbility;
-import com.projectkorra.projectkorra.avatar.AvatarState;
+import java.util.ArrayList;
+import java.util.List;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
@@ -10,7 +9,9 @@ import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
-import java.util.ArrayList;
+import com.projectkorra.projectkorra.ProjectKorra;
+import com.projectkorra.projectkorra.ability.AirAbility;
+import com.projectkorra.projectkorra.avatar.AvatarState;
public class AirBurst extends AirAbility {
@@ -27,7 +28,7 @@ public class AirBurst extends AirAbility {
private double particlePercentage;
private ArrayList blasts;
private ArrayList affectedEntities;
-
+
public AirBurst(Player player, boolean isFallBurst) {
super(player);
if (bPlayer.isOnCooldown(this)) {
@@ -76,7 +77,7 @@ public class AirBurst extends AirAbility {
return;
}
- if (System.currentTimeMillis() > startTime + chargeTime && !isCharged) {
+ if (System.currentTimeMillis() > getStartTime() + chargeTime && !isCharged) {
isCharged = true;
}
@@ -99,7 +100,7 @@ public class AirBurst extends AirAbility {
if (bPlayer.isOnCooldown("AirBurst")) {
return;
}
-
+
Location location = player.getLocation();
double x, y, z;
double r = 1;
@@ -109,11 +110,11 @@ public class AirBurst extends AirAbility {
for (double phi = 0; phi < 360; phi += dphi) {
double rphi = Math.toRadians(phi);
double rtheta = Math.toRadians(theta);
-
+
x = r * Math.cos(rphi) * Math.sin(rtheta);
y = r * Math.sin(rphi) * Math.sin(rtheta);
z = r * Math.cos(rtheta);
-
+
Vector direction = new Vector(x, z, y);
AirBlast blast = new AirBlast(player, location, direction.normalize(), pushFactor, this);
blast.setDamage(damage);
@@ -136,17 +137,17 @@ public class AirBurst extends AirAbility {
double angle = Math.toRadians(30);
double x, y, z;
double r = 1;
-
+
for (double theta = 0; theta <= 180; theta += blastAngleTheta) {
double dphi = blastAnglePhi / Math.sin(Math.toRadians(theta));
for (double phi = 0; phi < 360; phi += dphi) {
double rphi = Math.toRadians(phi);
double rtheta = Math.toRadians(theta);
-
+
x = r * Math.cos(rphi) * Math.sin(rtheta);
y = r * Math.sin(rphi) * Math.sin(rtheta);
z = r * Math.cos(rtheta);
-
+
Vector direction = new Vector(x, z, y);
if (direction.angle(vector) <= angle) {
AirBlast blast = new AirBlast(player, location, direction.normalize(), pushFactor, this);
@@ -185,14 +186,14 @@ public class AirBurst extends AirAbility {
for (double phi = 0; phi < 360; phi += dphi) {
double rphi = Math.toRadians(phi);
double rtheta = Math.toRadians(theta);
-
+
x = r * Math.cos(rphi) * Math.sin(rtheta);
y = r * Math.sin(rphi) * Math.sin(rtheta);
z = r * Math.cos(rtheta);
-
+
Vector direction = new Vector(x, z, y);
AirBlast blast = new AirBlast(player, location, direction.normalize(), pushFactor, this);
-
+
blast.setDamage(damage);
blast.setShowParticles(false);
blasts.add(blast);
@@ -216,7 +217,7 @@ public class AirBurst extends AirAbility {
public long getCooldown() {
return 0;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -227,6 +228,14 @@ public class AirBurst extends AirAbility {
return false;
}
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (AirBlast blast : blasts) {
+ locations.add(blast.getLocation());
+ }
+ return locations;
+ }
public void addAffectedEntity(Entity entity) {
affectedEntities.add(entity);
diff --git a/src/com/projectkorra/projectkorra/airbending/AirCombo.java b/src/com/projectkorra/projectkorra/airbending/AirCombo.java
index e36acac2..6f1e91e4 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirCombo.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirCombo.java
@@ -1,19 +1,7 @@
package com.projectkorra.projectkorra.airbending;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ProjectKorra;
-import com.projectkorra.projectkorra.ability.AirAbility;
-import com.projectkorra.projectkorra.ability.ComboAbility;
-import com.projectkorra.projectkorra.ability.EarthAbility;
-import com.projectkorra.projectkorra.ability.FireAbility;
-import com.projectkorra.projectkorra.ability.WaterAbility;
-import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation;
-import com.projectkorra.projectkorra.avatar.AvatarState;
-import com.projectkorra.projectkorra.command.Commands;
-import com.projectkorra.projectkorra.firebending.FireCombo;
-import com.projectkorra.projectkorra.firebending.FireCombo.FireComboStream;
-import com.projectkorra.projectkorra.util.DamageHandler;
-import com.projectkorra.projectkorra.util.Flight;
+import java.util.ArrayList;
+import java.util.List;
import org.bukkit.Location;
import org.bukkit.block.Block;
@@ -23,12 +11,22 @@ import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
-import java.util.ArrayList;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ProjectKorra;
+import com.projectkorra.projectkorra.ability.AirAbility;
+import com.projectkorra.projectkorra.ability.ComboAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
+import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation;
+import com.projectkorra.projectkorra.avatar.AvatarState;
+import com.projectkorra.projectkorra.command.Commands;
+import com.projectkorra.projectkorra.firebending.FireCombo.FireComboStream;
+import com.projectkorra.projectkorra.util.DamageHandler;
+import com.projectkorra.projectkorra.util.Flight;
/*
- * TODO: Combo classes should eventually be rewritten so that each combo is treated
- * as an individual ability. In the mean time, we will just place "fake"
- * classes so that CoreAbility will register each ability.
+ * TODO: Combo classes should eventually be rewritten so that each combo is
+ * treated as an individual ability. In the mean time, we will just place "fake"
+ * classes so that CoreAbility will register each ability.
*/
public class AirCombo extends AirAbility implements ComboAbility {
@@ -62,7 +60,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
public AirCombo(Player player, String ability) {
super(player);
-
+
this.abilityName = ability;
this.affectedEntities = new ArrayList<>();
this.tasks = new ArrayList<>();
@@ -71,7 +69,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
if (!bPlayer.canBendIgnoreBindsCooldowns(this)) {
return;
}
-
+
if (bPlayer.isOnCooldown(ability)) {
return;
}
@@ -98,7 +96,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
this.knockback = getConfig().getDouble("Abilities.Air.AirCombo.AirSweep.Knockback");
this.cooldown = getConfig().getLong("Abilities.Air.AirCombo.AirSweep.Cooldown");
}
-
+
if (bPlayer.isAvatarState()) {
this.cooldown = 0;
this.damage = AvatarState.getValue(damage);
@@ -201,7 +199,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
direction = GeneralMethods.getDirection(currentLoc, destination).normalize();
currentLoc.add(direction.clone().multiply(speed));
-
+
if (player.getWorld() != currentLoc.getWorld()) {
remove();
return;
@@ -223,12 +221,6 @@ public class AirCombo extends AirAbility implements ComboAbility {
} else if (GeneralMethods.isRegionProtectedFromBuild(this, currentLoc)) {
remove();
return;
- } else if (FireAbility.isWithinFireShield(currentLoc)) {
- remove();
- return;
- } else if (isWithinAirShield(currentLoc)) {
- remove();
- return;
} else if (!isTransparent(currentLoc.getBlock())) {
currentLoc.subtract(direction.clone().multiply(speed));
}
@@ -280,8 +272,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
destination = player.getLocation().add(player.getEyeLocation().getDirection().normalize().multiply(10));
Vector origToDest = GeneralMethods.getDirection(origin, destination);
for (double i = 0; i < 30; i++) {
- Vector vec = GeneralMethods.getDirection(player.getLocation(),
- origin.clone().add(origToDest.clone().multiply(i / 30)));
+ Vector vec = GeneralMethods.getDirection(player.getLocation(), origin.clone().add(origToDest.clone().multiply(i / 30)));
FireComboStream fs = new FireComboStream(null, vec, player.getLocation(), range, speed, "AirSweep");
fs.setDensity(1);
@@ -316,7 +307,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
fstream.remove();
return;
}
-
+
if (!isTransparent(loc.getBlock())) {
if (!isTransparent(loc.clone().add(0, 0.2, 0).getBlock())) {
fstream.remove();
@@ -346,12 +337,6 @@ public class AirCombo extends AirAbility implements ComboAbility {
}
}
}
-
- if (GeneralMethods.blockAbilities(player, FireCombo.getBlockableAbilities(), loc, 1)) {
- fstream.remove();
- } else AirAbility.removeAirSpouts(loc, player);
- WaterAbility.removeWaterSpouts(loc, player);
- EarthAbility.removeSandSpouts(loc, player);
}
}
}
@@ -368,6 +353,11 @@ public class AirCombo extends AirAbility implements ComboAbility {
}
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean removeAroundPoint(Player player, String ability, Location loc, double radius) {
boolean removed = false;
for (AirCombo combo : getAbilities(AirCombo.class)) {
@@ -386,8 +376,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
} else if (ability.equalsIgnoreCase("AirSweep") && combo.abilityName.equalsIgnoreCase("AirSweep")) {
for (int j = 0; j < combo.tasks.size(); j++) {
FireComboStream fs = (FireComboStream) combo.tasks.get(j);
- if (fs.getLocation() != null && fs.getLocation().getWorld().equals(loc.getWorld())
- && Math.abs(fs.getLocation().distance(loc)) <= radius) {
+ if (fs.getLocation() != null && fs.getLocation().getWorld().equals(loc.getWorld()) && Math.abs(fs.getLocation().distance(loc)) <= radius) {
fs.remove();
removed = true;
}
@@ -423,7 +412,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
public boolean isHiddenAbility() {
return true;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -433,7 +422,13 @@ public class AirCombo extends AirAbility implements ComboAbility {
public boolean isHarmlessAbility() {
return false;
}
-
+
+ @Override
+ public boolean isCollidable() {
+ // Override in subclasses
+ return false;
+ }
+
@Override
public String getInstructions() {
return null;
@@ -449,7 +444,6 @@ public class AirCombo extends AirAbility implements ComboAbility {
return null;
}
-
public String getAbilityName() {
return abilityName;
}
@@ -609,6 +603,10 @@ public class AirCombo extends AirAbility implements ComboAbility {
public ArrayList getTasks() {
return tasks;
}
+
+ public void setTasks(ArrayList tasks) {
+ this.tasks = tasks;
+ }
public ArrayList getFlights() {
return flights;
@@ -617,44 +615,91 @@ public class AirCombo extends AirAbility implements ComboAbility {
public void setCooldown(long cooldown) {
this.cooldown = cooldown;
}
-
- public class AirStream extends AirCombo {
- public AirStream(Player player, String name) {
+ // Combo subclasses need to be static to be reflectively called in ComboManager
+ public static class AirStream extends AirCombo {
+
+ public AirStream(Player player) {
super(player, "AirStream");
}
-
+
@Override
public String getName() {
return "AirStream";
}
-
- }
-
- public class AirSweep extends AirCombo {
- public AirSweep(Player player, String name) {
+ @Override
+ public boolean isCollidable() {
+ return true;
+ }
+
+ }
+
+ public static class AirSweep extends AirCombo {
+
+ public AirSweep(Player player) {
super(player, "AirSweep");
}
-
+
@Override
public String getName() {
return "AirSweep";
}
-
- }
-
- public class Twister extends AirCombo {
- public Twister(Player player, String name) {
- super(player, "Twister");
+ @Override
+ public boolean isCollidable() {
+ return true;
}
+ @Override
+ public void handleCollision(Collision collision) {
+ if (collision.isRemovingFirst()) {
+ ArrayList newTasks = new ArrayList<>();
+ double collisionDistanceSquared = Math.pow(getCollisionRadius() + collision.getAbilitySecond().getCollisionRadius(), 2);
+ // Remove all of the streams that are by this specific ourLocation.
+ // Don't just do a single stream at a time or this algorithm becomes O(n^2) with
+ // Collision's detection algorithm.
+ for (BukkitRunnable task : getTasks()) {
+ if (task instanceof FireComboStream) {
+ FireComboStream stream = (FireComboStream) task;
+ if (stream.getLocation().distanceSquared(collision.getLocationSecond()) > collisionDistanceSquared) {
+ newTasks.add(stream);
+ } else {
+ stream.cancel();
+ }
+ } else {
+ newTasks.add(task);
+ }
+ }
+ setTasks(newTasks);
+ }
+ }
+
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (BukkitRunnable task : getTasks()) {
+ if (task instanceof FireComboStream) {
+ FireComboStream stream = (FireComboStream) task;
+ locations.add(stream.getLocation());
+ }
+ }
+ return locations;
+ }
+
+ }
+
+ public static class Twister extends AirCombo {
+
+ public Twister(Player player) {
+ super(player, "Twister");
+ }
+
@Override
public String getName() {
return "Twister";
}
-
+
}
-
+
}
diff --git a/src/com/projectkorra/projectkorra/airbending/AirScooter.java b/src/com/projectkorra/projectkorra/airbending/AirScooter.java
index 3748f3fb..719d2e74 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirScooter.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirScooter.java
@@ -25,18 +25,17 @@ public class AirScooter extends AirAbility {
private Block floorblock;
private Random random;
private ArrayList angles;
-
+
private boolean canFly;
private boolean hadFly;
private double phi = 0;
-
+
public AirScooter(Player player) {
super(player);
-
- if (check(player))
+
+ if (check(player))
return;
- else if (!player.isSprinting() || GeneralMethods.isSolid(player.getEyeLocation().getBlock())
- || player.getEyeLocation().getBlock().isLiquid())
+ else if (!player.isSprinting() || GeneralMethods.isSolid(player.getEyeLocation().getBlock()) || player.getEyeLocation().getBlock().isLiquid())
return;
else if (GeneralMethods.isSolid(player.getLocation().add(0, -.5, 0).getBlock()))
return;
@@ -52,7 +51,7 @@ public class AirScooter extends AirAbility {
this.angles = new ArrayList<>();
canFly = player.getAllowFlight();
hadFly = player.isFlying();
-
+
new Flight(player);
player.setAllowFlight(true);
player.setFlying(true);
@@ -82,8 +81,8 @@ public class AirScooter extends AirAbility {
}
/*
- * Looks for a block under the player and sets "floorBlock" to a block
- * under the player if it within the maximum height
+ * Looks for a block under the player and sets "floorBlock" to a block under
+ * the player if it within the maximum height
*/
private void getFloor() {
floorblock = null;
@@ -102,7 +101,7 @@ public class AirScooter extends AirAbility {
remove();
return;
}
-
+
getFloor();
if (floorblock == null) {
remove();
@@ -114,7 +113,7 @@ public class AirScooter extends AirAbility {
/*
* checks the players speed and ends the move if they are going too slow
*/
- if (System.currentTimeMillis() > startTime + interval) {
+ if (System.currentTimeMillis() > getStartTime() + interval) {
if (player.getVelocity().length() < speed * 0.3) {
remove();
return;
@@ -122,8 +121,8 @@ public class AirScooter extends AirAbility {
spinScooter();
}
/*
- * Checks for how far the ground is away from the player
- * it elevates or lowers the player based on their distance from the ground.
+ * Checks for how far the ground is away from the player it elevates or
+ * lowers the player based on their distance from the ground.
*/
double distance = player.getLocation().getY() - (double) floorblock.getY();
double dx = Math.abs(distance - 2.4);
@@ -141,7 +140,7 @@ public class AirScooter extends AirAbility {
} else {
return;
}
-
+
player.setSprinting(false);
player.removePotionEffect(PotionEffectType.SPEED);
player.setVelocity(velocity);
@@ -163,36 +162,33 @@ public class AirScooter extends AirAbility {
}
/*
- * The particles used for AirScooter
- * phi = how many rings of particles the sphere has.
- * theta = how dense the rings are.
- * r = Radius of the sphere
+ * The particles used for AirScooter phi = how many rings of particles the
+ * sphere has. theta = how dense the rings are. r = Radius of the sphere
*/
private void spinScooter() {
Location origin = player.getLocation();
Location origin2 = player.getLocation();
- phi += Math.PI/10*4;
- for(double theta = 0; theta <= 2*Math.PI; theta += Math.PI/10) {
+ phi += Math.PI / 10 * 4;
+ for (double theta = 0; theta <= 2 * Math.PI; theta += Math.PI / 10) {
double r = 0.6;
- double x = r*Math.cos(theta)*Math.sin(phi);
- double y = r*Math.cos(phi);
- double z = r*Math.sin(theta)*Math.sin(phi);
+ double x = r * Math.cos(theta) * Math.sin(phi);
+ double y = r * Math.cos(phi);
+ double z = r * Math.sin(theta) * Math.sin(phi);
origin.add(x, y, z);
playAirbendingParticles(origin, 1, 0F, 0F, 0F);
origin.subtract(x, y, z);
}
- for(double theta = 0; theta <= 2*Math.PI; theta += Math.PI/10) {
+ for (double theta = 0; theta <= 2 * Math.PI; theta += Math.PI / 10) {
double r = 0.6;
- double x = r*Math.cos(theta)*Math.sin(phi);
- double y = r*Math.cos(phi);
- double z = r*Math.sin(theta)*Math.sin(phi);
+ double x = r * Math.cos(theta) * Math.sin(phi);
+ double y = r * Math.cos(phi);
+ double z = r * Math.sin(theta) * Math.sin(phi);
origin2.subtract(x, y, z);
playAirbendingParticles(origin2, 1, 0F, 0F, 0F);
origin2.add(x, y, z);
}
}
-
@Override
public String getName() {
return "AirScooter";
@@ -207,7 +203,7 @@ public class AirScooter extends AirAbility {
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return false;
@@ -218,6 +214,10 @@ public class AirScooter extends AirAbility {
return true;
}
+ @Override
+ public double getCollisionRadius() {
+ return getRadius();
+ }
public double getSpeed() {
return speed;
@@ -258,7 +258,7 @@ public class AirScooter extends AirAbility {
public void setFloorblock(Block floorblock) {
this.floorblock = floorblock;
}
-
+
public void setCooldown(long cooldown) {
this.cooldown = cooldown;
}
diff --git a/src/com/projectkorra/projectkorra/airbending/AirShield.java b/src/com/projectkorra/projectkorra/airbending/AirShield.java
index 16a217fc..c28a4b8a 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirShield.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirShield.java
@@ -1,16 +1,8 @@
package com.projectkorra.projectkorra.airbending;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ability.AirAbility;
-import com.projectkorra.projectkorra.avatar.AvatarState;
-import com.projectkorra.projectkorra.command.Commands;
-import com.projectkorra.projectkorra.earthbending.EarthBlast;
-import com.projectkorra.projectkorra.earthbending.SandSpout;
-import com.projectkorra.projectkorra.firebending.BlazeArc;
-import com.projectkorra.projectkorra.firebending.Combustion;
-import com.projectkorra.projectkorra.firebending.FireBlast;
-import com.projectkorra.projectkorra.waterbending.WaterManipulation;
-import com.projectkorra.projectkorra.waterbending.WaterSpout;
+import java.util.HashMap;
+import java.util.Random;
+import java.util.Set;
import org.bukkit.Effect;
import org.bukkit.Location;
@@ -20,9 +12,11 @@ import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
-import java.util.HashMap;
-import java.util.Random;
-import java.util.Set;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.AirAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
+import com.projectkorra.projectkorra.avatar.AvatarState;
+import com.projectkorra.projectkorra.command.Commands;
public class AirShield extends AirAbility {
@@ -34,16 +28,16 @@ public class AirShield extends AirAbility {
private int particles;
private Random random;
private HashMap angles;
-
+
public AirShield(Player player) {
super(player);
this.maxRadius = getConfig().getDouble("Abilities.Air.AirShield.Radius");
this.isToggledByAvatarState = getConfig().getBoolean("Abilities.Air.AirShield.IsAvatarStateToggle");
this.radius = this.maxRadius;
- this.speed = getConfig().getDouble("Abilities.Air.AirShield.Speed");
+ this.speed = getConfig().getDouble("Abilities.Air.AirShield.Speed");
this.streams = getConfig().getInt("Abilities.Air.AirShield.Streams");
- this.particles = getConfig().getInt("Abilities.Air.AirShield.Particles");
+ this.particles = getConfig().getInt("Abilities.Air.AirShield.Particles");
this.random = new Random();
this.angles = new HashMap<>();
@@ -61,10 +55,15 @@ public class AirShield extends AirAbility {
angle = 0;
}
}
-
+
start();
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean isWithinShield(Location loc) {
for (AirShield ashield : getAbilities(AirShield.class)) {
if (!ashield.player.getWorld().equals(loc.getWorld())) {
@@ -96,16 +95,6 @@ public class AirShield extends AirAbility {
private void rotateShield() {
Location origin = player.getLocation();
- FireBlast.removeFireBlastsAroundPoint(origin, radius);
- Combustion.removeAroundPoint(origin, radius);
- BlazeArc.removeAroundPoint(origin, radius);
- AirBlast.removeAirBlastsAroundPoint(origin, radius);
- AirSuction.removeAirSuctionsAroundPoint(origin, radius);
- EarthBlast.removeAroundPoint(origin, radius);
- SandSpout.removeSpouts(origin, radius, player);
- WaterSpout.removeSpouts(origin, radius, player);
- WaterManipulation.removeAroundPoint(origin, radius);
-
for (Entity entity : GeneralMethods.getEntitiesAroundPoint(origin, radius)) {
if (GeneralMethods.isRegionProtectedFromBuild(player, "AirShield", entity.getLocation())) {
continue;
@@ -181,7 +170,7 @@ public class AirShield extends AirAbility {
radius = maxRadius;
}
}
-
+
@Override
public String getName() {
return "AirShield";
@@ -196,7 +185,7 @@ public class AirShield extends AirAbility {
public long getCooldown() {
return 0;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -207,6 +196,11 @@ public class AirShield extends AirAbility {
return false;
}
+ @Override
+ public double getCollisionRadius() {
+ return getRadius();
+ }
+
public boolean isToggledByAvatarState() {
return isToggledByAvatarState;
}
diff --git a/src/com/projectkorra/projectkorra/airbending/AirSpout.java b/src/com/projectkorra/projectkorra/airbending/AirSpout.java
index 7ce7ad99..45c00acd 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirSpout.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirSpout.java
@@ -1,5 +1,7 @@
package com.projectkorra.projectkorra.airbending;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Random;
import org.bukkit.Location;
@@ -9,26 +11,28 @@ import org.bukkit.entity.Player;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.AirAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.util.Flight;
public class AirSpout extends AirAbility {
- private static final Integer[] DIRECTIONS = {0, 1, 2, 3, 5, 6, 7, 8};
+ private static final Integer[] DIRECTIONS = { 0, 1, 2, 3, 5, 6, 7, 8 };
private int angle;
+ private long animTime;
private long interval;
private long cooldown;
private double height;
public AirSpout(Player player) {
super(player);
-
+
AirSpout spout = getAbility(player, AirSpout.class);
if (spout != null) {
spout.remove();
return;
}
-
+
if (!bPlayer.canBend(this)) {
remove();
return;
@@ -36,6 +40,7 @@ public class AirSpout extends AirAbility {
this.angle = 0;
this.cooldown = 0;
+ this.animTime = System.currentTimeMillis();
this.interval = getConfig().getLong("Abilities.Air.AirSpout.Interval");
this.height = getConfig().getDouble("Abilities.Air.AirSpout.Height");
@@ -43,12 +48,17 @@ public class AirSpout extends AirAbility {
if (!isWithinMaxSpoutHeight(heightRemoveThreshold)) {
return;
}
-
+
new Flight(player);
start();
bPlayer.addCooldown(this);
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean removeSpouts(Location loc0, double radius, Player sourceplayer) {
boolean removed = false;
for (AirSpout spout : getAbilities(AirSpout.class)) {
@@ -74,7 +84,7 @@ public class AirSpout extends AirAbility {
player.setAllowFlight(true);
player.setFlying(true);
}
-
+
private boolean isWithinMaxSpoutHeight(double threshold) {
Block ground = getGround();
if (ground == null) {
@@ -100,21 +110,18 @@ public class AirSpout extends AirAbility {
@Override
public void progress() {
- if (player.isDead()
- || !player.isOnline()
- || !bPlayer.canBendIgnoreBindsCooldowns(this)
- || !bPlayer.canBind(this)) {
+ if (player.isDead() || !player.isOnline() || !bPlayer.canBendIgnoreBindsCooldowns(this) || !bPlayer.canBind(this)) {
remove();
return;
}
-
+
double heightRemoveThreshold = 2;
if (!isWithinMaxSpoutHeight(heightRemoveThreshold)) {
remove();
return;
}
-
- if(!bPlayer.canBind(this)) {
+
+ if (!bPlayer.canBind(this)) {
remove();
return;
}
@@ -159,8 +166,8 @@ public class AirSpout extends AirAbility {
if (!player.getWorld().equals(block.getWorld())) {
return;
}
- if (System.currentTimeMillis() >= startTime + interval) {
- startTime = System.currentTimeMillis();
+ if (System.currentTimeMillis() >= animTime + interval) {
+ animTime = System.currentTimeMillis();
Location location = block.getLocation();
Location playerloc = player.getLocation();
location = new Location(location.getWorld(), playerloc.getX(), location.getY(), playerloc.getZ());
@@ -191,7 +198,7 @@ public class AirSpout extends AirAbility {
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return false;
@@ -202,6 +209,22 @@ public class AirSpout extends AirAbility {
return true;
}
+ @Override
+ public boolean isCollidable() {
+ return true;
+ }
+
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ Location topLoc = player.getLocation().getBlock().getLocation();
+ double ySpacing = 3;
+ for (double i = 0; i <= height; i += ySpacing) {
+ locations.add(topLoc.clone().add(0, -i, 0));
+ }
+ return locations;
+ }
+
public int getAngle() {
return angle;
}
@@ -210,6 +233,14 @@ public class AirSpout extends AirAbility {
this.angle = angle;
}
+ public long getAnimTime() {
+ return animTime;
+ }
+
+ public void setAnimTime(long animTime) {
+ this.animTime = animTime;
+ }
+
public long getInterval() {
return interval;
}
@@ -229,5 +260,5 @@ public class AirSpout extends AirAbility {
public void setCooldown(long cooldown) {
this.cooldown = cooldown;
}
-
+
}
diff --git a/src/com/projectkorra/projectkorra/airbending/AirSuction.java b/src/com/projectkorra/projectkorra/airbending/AirSuction.java
index e4c469ad..ced2dcab 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirSuction.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirSuction.java
@@ -14,6 +14,7 @@ import com.projectkorra.projectkorra.BendingPlayer;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.AirAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
@@ -24,7 +25,7 @@ public class AirSuction extends AirAbility {
private static final int MAX_TICKS = 10000;
private static final Map ORIGINS = new ConcurrentHashMap<>();
-
+
private boolean hasOtherOrigin;
private int ticks;
private int particleCount;
@@ -37,10 +38,10 @@ public class AirSuction extends AirAbility {
private Location location;
private Location origin;
private Vector direction;
-
+
public AirSuction(Player player) {
super(player);
-
+
if (bPlayer.isOnCooldown(this)) {
return;
} else if (player.getEyeLocation().getBlock().isLiquid()) {
@@ -133,8 +134,7 @@ public class AirSuction extends AirAbility {
Location location = origin.clone();
for (double i = 1; i <= range; i++) {
location = origin.clone().add(direction.clone().multiply(i));
- if (!isTransparent(location.getBlock())
- || GeneralMethods.isRegionProtectedFromBuild(this, location)) {
+ if (!isTransparent(location.getBlock()) || GeneralMethods.isRegionProtectedFromBuild(this, location)) {
return origin.clone().add(direction.clone().multiply(i - 1));
}
}
@@ -178,7 +178,7 @@ public class AirSuction extends AirAbility {
push.setY(max);
}
}
- if(location.getWorld().equals(origin.getWorld())) {
+ if (location.getWorld().equals(origin.getWorld())) {
factor *= 1 - location.distance(origin) / (2 * range);
}
@@ -216,6 +216,11 @@ public class AirSuction extends AirAbility {
advanceLocation();
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean removeAirSuctionsAroundPoint(Location location, double radius) {
boolean removed = false;
for (AirSuction airSuction : getAbilities(AirSuction.class)) {
@@ -244,7 +249,7 @@ public class AirSuction extends AirAbility {
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -255,6 +260,11 @@ public class AirSuction extends AirAbility {
return false;
}
+ @Override
+ public double getCollisionRadius() {
+ return getRadius();
+ }
+
public Location getOrigin() {
return origin;
}
@@ -346,5 +356,5 @@ public class AirSuction extends AirAbility {
public static double getSelectRange() {
return getConfig().getDouble("Abilities.Air.AirSuction.SelectRange");
}
-
+
}
diff --git a/src/com/projectkorra/projectkorra/airbending/AirSwipe.java b/src/com/projectkorra/projectkorra/airbending/AirSwipe.java
index af09fa27..42212042 100644
--- a/src/com/projectkorra/projectkorra/airbending/AirSwipe.java
+++ b/src/com/projectkorra/projectkorra/airbending/AirSwipe.java
@@ -1,20 +1,11 @@
package com.projectkorra.projectkorra.airbending;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ProjectKorra;
-import com.projectkorra.projectkorra.ability.AirAbility;
-import com.projectkorra.projectkorra.ability.CoreAbility;
-import com.projectkorra.projectkorra.ability.EarthAbility;
-import com.projectkorra.projectkorra.ability.WaterAbility;
-import com.projectkorra.projectkorra.avatar.AvatarState;
-import com.projectkorra.projectkorra.command.Commands;
-import com.projectkorra.projectkorra.earthbending.EarthBlast;
-import com.projectkorra.projectkorra.firebending.Combustion;
-import com.projectkorra.projectkorra.firebending.FireBlast;
-import com.projectkorra.projectkorra.firebending.Illumination;
-import com.projectkorra.projectkorra.util.DamageHandler;
-import com.projectkorra.projectkorra.util.Flight;
-import com.projectkorra.projectkorra.waterbending.WaterManipulation;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -25,19 +16,24 @@ import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.ConcurrentHashMap;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ProjectKorra;
+import com.projectkorra.projectkorra.ability.AirAbility;
+import com.projectkorra.projectkorra.ability.CoreAbility;
+import com.projectkorra.projectkorra.ability.EarthAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
+import com.projectkorra.projectkorra.avatar.AvatarState;
+import com.projectkorra.projectkorra.command.Commands;
+import com.projectkorra.projectkorra.firebending.Illumination;
+import com.projectkorra.projectkorra.util.DamageHandler;
+import com.projectkorra.projectkorra.util.Flight;
public class AirSwipe extends AirAbility {
// Limiting the entities reduces the risk of crashing
private static final int MAX_AFFECTABLE_ENTITIES = 10;
- private static final Integer[] BREAKABLES = {6, 31, 32, 37, 38, 39, 40, 59, 81, 83, 106, 175};
-
+ private static final Integer[] BREAKABLES = { 6, 31, 32, 37, 38, 39, 40, 59, 81, 83, 106, 175 };
+
private boolean charging;
private int arc;
private int particles;
@@ -54,14 +50,14 @@ public class AirSwipe extends AirAbility {
private Random random;
private Map elements;
private ArrayList affectedEntities;
-
+
public AirSwipe(Player player) {
this(player, false);
}
public AirSwipe(Player player, boolean charging) {
super(player);
-
+
if (CoreAbility.hasAbility(player, AirSwipe.class)) {
for (AirSwipe ability : CoreAbility.getAbilities(player, AirSwipe.class)) {
if (ability.charging) {
@@ -71,7 +67,7 @@ public class AirSwipe extends AirAbility {
}
}
}
-
+
this.charging = charging;
this.origin = player.getEyeLocation();
this.particles = getConfig().getInt("Abilities.Air.AirSwipe.Particles");
@@ -88,23 +84,28 @@ public class AirSwipe extends AirAbility {
this.random = new Random();
this.elements = new ConcurrentHashMap<>();
this.affectedEntities = new ArrayList<>();
-
+
if (bPlayer.isOnCooldown(this) || player.getEyeLocation().getBlock().isLiquid()) {
remove();
return;
}
-
+
if (!bPlayer.canBend(this)) {
remove();
return;
}
-
+
if (!charging) {
launch();
}
start();
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean removeSwipesAroundPoint(Location loc, double radius) {
boolean removed = false;
for (AirSwipe aswipe : getAbilities(AirSwipe.class)) {
@@ -130,31 +131,15 @@ public class AirSwipe extends AirAbility {
location = location.clone().add(direction.clone().multiply(speed));
elements.put(direction, location);
- if (location.distanceSquared(origin) > range * range
- || GeneralMethods.isRegionProtectedFromBuild(this, location)) {
+ if (location.distanceSquared(origin) > range * range || GeneralMethods.isRegionProtectedFromBuild(this, location)) {
elements.remove(direction);
} else {
- removeAirSpouts(location, player);
- WaterAbility.removeWaterSpouts(location, player);
- EarthAbility.removeSandSpouts(location, player);
-
-
- if (EarthBlast.annihilateBlasts(location, radius, player)
- || WaterManipulation.annihilateBlasts(location, radius, player)
- || FireBlast.annihilateBlasts(location, radius, player)
- || Combustion.removeAroundPoint(location, radius)) {
- elements.remove(direction);
- damage = 0;
- remove();
- continue;
- }
-
Block block = location.getBlock();
if (!EarthAbility.isTransparent(player, block)) {
remove();
return;
}
-
+
for (Block testblock : GeneralMethods.getBlocksAroundPoint(location, radius)) {
if (testblock.getType() == Material.FIRE) {
testblock.setType(Material.AIR);
@@ -193,9 +178,6 @@ public class AirSwipe extends AirAbility {
}
private void affectPeople(Location location, Vector direction) {
- WaterAbility.removeWaterSpouts(location, player);
- removeAirSpouts(location, player);
- removeAirSpouts(location, player);
final List entities = GeneralMethods.getEntitiesAroundPoint(location, radius);
final Vector fDirection = direction;
@@ -280,12 +262,12 @@ public class AirSwipe extends AirAbility {
remove();
return;
}
-
+
if (player.isDead() || !player.isOnline()) {
remove();
return;
}
-
+
if (!charging) {
if (elements.isEmpty()) {
remove();
@@ -295,12 +277,12 @@ public class AirSwipe extends AirAbility {
} else {
if (!player.isSneaking()) {
double factor = 1;
- if (System.currentTimeMillis() >= startTime + maxChargeTime) {
+ if (System.currentTimeMillis() >= getStartTime() + maxChargeTime) {
factor = maxChargeFactor;
} else if (bPlayer.isAvatarState()) {
factor = AvatarState.getValue(factor);
} else {
- factor = maxChargeFactor * (double) (System.currentTimeMillis() - startTime) / (double) maxChargeTime;
+ factor = maxChargeFactor * (double) (System.currentTimeMillis() - getStartTime()) / (double) maxChargeTime;
}
charging = false;
@@ -308,7 +290,7 @@ public class AirSwipe extends AirAbility {
factor = Math.max(1, factor);
damage *= factor;
pushFactor *= factor;
- } else if (System.currentTimeMillis() >= startTime + maxChargeTime) {
+ } else if (System.currentTimeMillis() >= getStartTime() + maxChargeTime) {
playAirbendingParticles(player.getEyeLocation(), particles);
}
}
@@ -328,7 +310,7 @@ public class AirSwipe extends AirAbility {
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -339,6 +321,25 @@ public class AirSwipe extends AirAbility {
return false;
}
+ @Override
+ public boolean isCollidable() {
+ return origin != null;
+ }
+
+ @Override
+ public double getCollisionRadius() {
+ return getRadius();
+ }
+
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (Location swipeLoc : elements.values()) {
+ locations.add(swipeLoc);
+ }
+ return locations;
+ }
+
public Location getOrigin() {
return origin;
}
@@ -454,5 +455,5 @@ public class AirSwipe extends AirAbility {
public void setStepSize(int stepSize) {
this.stepSize = stepSize;
}
-
+
}
diff --git a/src/com/projectkorra/projectkorra/airbending/Suffocate.java b/src/com/projectkorra/projectkorra/airbending/Suffocate.java
index 3539721b..832c32dc 100644
--- a/src/com/projectkorra/projectkorra/airbending/Suffocate.java
+++ b/src/com/projectkorra/projectkorra/airbending/Suffocate.java
@@ -20,10 +20,11 @@ import com.projectkorra.projectkorra.util.DamageHandler;
/**
* Suffocate
*
- * Suffocate is an air ability that causes entities to be surrounded by a sphere air that causes
- * constant damage after a configurable delay. Suffocate also causes Blinding and Slowing affects to
- * entities depending on how the ability is configured. While in AvatarState this ability can be
- * used on multiple entities within a large radius. If the user is damaged while performing this
+ * Suffocate is an air ability that causes entities to be surrounded by a sphere
+ * air that causes constant damage after a configurable delay. Suffocate also
+ * causes Blinding and Slowing affects to entities depending on how the ability
+ * is configured. While in AvatarState this ability can be used on multiple
+ * entities within a large radius. If the user is damaged while performing this
* ability then the ability is removed.
*/
public class Suffocate extends AirAbility {
@@ -54,7 +55,7 @@ public class Suffocate extends AirAbility {
private Suffocate ability;
private ArrayList tasks;
private ArrayList targets;
-
+
public Suffocate(Player player) {
super(player);
ability = this;
@@ -131,7 +132,7 @@ public class Suffocate extends AirAbility {
targets.add((LivingEntity) target);
}
}
-
+
if (!canSuffocateUndead) {
for (int i = 0; i < targets.size(); i++) {
LivingEntity target = targets.get(i);
@@ -150,10 +151,7 @@ public class Suffocate extends AirAbility {
public void progress() {
for (int i = 0; i < targets.size(); i++) {
LivingEntity target = targets.get(i);
- if (target.isDead()
- || !target.getWorld().equals(player.getWorld())
- || target.getLocation().distanceSquared(player.getEyeLocation()) > range * range
- || GeneralMethods.isRegionProtectedFromBuild(this, target.getLocation())) {
+ if (target.isDead() || !target.getWorld().equals(player.getWorld()) || target.getLocation().distanceSquared(player.getEyeLocation()) > range * range || GeneralMethods.isRegionProtectedFromBuild(this, target.getLocation())) {
breakSuffocateLocal(target);
i--;
} else if (target instanceof Player) {
@@ -171,11 +169,10 @@ public class Suffocate extends AirAbility {
if (requireConstantAim) {
double dist = 0;
- if(player.getWorld().equals(targets.get(0).getWorld())) {
+ if (player.getWorld().equals(targets.get(0).getWorld())) {
dist = player.getEyeLocation().distance(targets.get(0).getEyeLocation());
}
- Location targetLoc = player.getEyeLocation().clone()
- .add(player.getEyeLocation().getDirection().normalize().multiply(dist));
+ Location targetLoc = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().normalize().multiply(dist));
List ents = GeneralMethods.getEntitiesAroundPoint(targetLoc, constantAimRadius);
for (int i = 0; i < targets.size(); i++) {
@@ -191,7 +188,7 @@ public class Suffocate extends AirAbility {
}
}
- if (System.currentTimeMillis() - startTime < chargeTime) {
+ if (System.currentTimeMillis() - getStartTime() < chargeTime) {
return;
} else if (!started) {
started = true;
@@ -257,7 +254,8 @@ public class Suffocate extends AirAbility {
}
/**
- * Removes an instance of Suffocate if player is the one suffocating entities
+ * Removes an instance of Suffocate if player is the one suffocating
+ * entities
**/
public static void remove(Player player) {
Suffocate suff = getAbility(player, Suffocate.class);
@@ -267,9 +265,9 @@ public class Suffocate extends AirAbility {
}
/**
- * Removes all instances of Suffocate at loc within the radius threshold. The location of a
- * Suffocate is defined at the benders location, not the location of the entities being
- * suffocated.
+ * Removes all instances of Suffocate at loc within the radius threshold.
+ * The location of a Suffocate is defined at the benders location, not the
+ * location of the entities being suffocated.
*
* @param causer The player causing this instance to be removed
**/
@@ -290,13 +288,14 @@ public class Suffocate extends AirAbility {
}
/**
- * Animates this instance of the Suffocate ability. Depending on the specific time (dt) the
- * ability will create a different set of SuffocationSpirals.
+ * Animates this instance of the Suffocate ability. Depending on the
+ * specific time (dt) the ability will create a different set of
+ * SuffocationSpirals.
*/
public void animate() {
int steps = 8 * particleCount;
long curTime = System.currentTimeMillis();
- long dt = curTime - startTime - chargeTime;
+ long dt = curTime - getStartTime() - chargeTime;
long delay = 2 / particleCount;
long t1 = (long) (1500 * animationSpeed);
long t2 = (long) (2500 * animationSpeed);
@@ -305,10 +304,8 @@ public class Suffocate extends AirAbility {
for (LivingEntity lent : targets) {
final LivingEntity target = lent;
if (dt < t1) {
- new SuffocateSpiral(target, steps, radius, delay, 0, 0.25 - (0.25 * (double) dt / (double) t1), 0,
- SpiralType.HORIZONTAL1);
- new SuffocateSpiral(target, steps, radius, delay, 0, 0.25 - (0.25 * (double) dt / (double) t1), 0,
- SpiralType.HORIZONTAL2);
+ new SuffocateSpiral(target, steps, radius, delay, 0, 0.25 - (0.25 * (double) dt / (double) t1), 0, SpiralType.HORIZONTAL1);
+ new SuffocateSpiral(target, steps, radius, delay, 0, 0.25 - (0.25 * (double) dt / (double) t1), 0, SpiralType.HORIZONTAL2);
} else if (dt < t2) {
new SuffocateSpiral(target, steps, radius, delay, 0, 0, 0, SpiralType.HORIZONTAL1);
new SuffocateSpiral(target, steps * 2, radius, delay, 0, 0, 0, SpiralType.VERTICAL1);
@@ -318,15 +315,9 @@ public class Suffocate extends AirAbility {
new SuffocateSpiral(target, steps, radius, delay, 0, 0, 0, SpiralType.VERTICAL1);
new SuffocateSpiral(target, steps, radius, delay, 0, 0, 0, SpiralType.VERTICAL2);
} else if (dt < t4) {
- new SuffocateSpiral(target, steps, radius
- - Math.min(radius * 3 / 4, (radius * 3.0 / 4 * ((double) (dt - t3) / (double) (t4 - t3)))), delay, 0, 0,
- 0, SpiralType.HORIZONTAL1);
- new SuffocateSpiral(target, steps, radius
- - Math.min(radius * 3 / 4, (radius * 3.0 / 4 * ((double) (dt - t3) / (double) (t4 - t3)))), delay, 0, 0,
- 0, SpiralType.VERTICAL1);
- new SuffocateSpiral(target, steps, radius
- - Math.min(radius * 3 / 4, (radius * 3.0 / 4 * ((double) (dt - t3) / (double) (t4 - t3)))), delay, 0, 0,
- 0, SpiralType.VERTICAL2);
+ new SuffocateSpiral(target, steps, radius - Math.min(radius * 3 / 4, (radius * 3.0 / 4 * ((double) (dt - t3) / (double) (t4 - t3)))), delay, 0, 0, 0, SpiralType.HORIZONTAL1);
+ new SuffocateSpiral(target, steps, radius - Math.min(radius * 3 / 4, (radius * 3.0 / 4 * ((double) (dt - t3) / (double) (t4 - t3)))), delay, 0, 0, 0, SpiralType.VERTICAL1);
+ new SuffocateSpiral(target, steps, radius - Math.min(radius * 3 / 4, (radius * 3.0 / 4 * ((double) (dt - t3) / (double) (t4 - t3)))), delay, 0, 0, 0, SpiralType.VERTICAL2);
} else {
new SuffocateSpiral(target, steps, radius - (radius * 3.0 / 4.0), delay, 0, 0, 0, SpiralType.HORIZONTAL1);
new SuffocateSpiral(target, steps, radius - (radius * 3.0 / 4.0), delay, 0, 0, 0, SpiralType.VERTICAL1);
@@ -354,9 +345,9 @@ public class Suffocate extends AirAbility {
}
/**
- * ** Animates a Spiral of air particles around a location or a targetted entity. The direction
- * of the spiral is determined by SpiralType, and each type is calculated independently from one
- * another.
+ * Animates a Spiral of air particles around a location or a targetted
+ * entity. The direction of the spiral is determined by SpiralType, and each
+ * type is calculated independently from one another.
*/
public class SuffocateSpiral extends BukkitRunnable {
private Location startLoc;
@@ -378,8 +369,7 @@ public class Suffocate extends AirAbility {
* @param dz z offset
* @param type Spiral animation direction
*/
- public SuffocateSpiral(LivingEntity lent, int totalSteps, double radius, long interval, double dx, double dy, double dz,
- SpiralType type) {
+ public SuffocateSpiral(LivingEntity lent, int totalSteps, double radius, long interval, double dx, double dy, double dz, SpiralType type) {
this.target = lent;
this.totalSteps = totalSteps;
this.radius = radius;
@@ -403,8 +393,7 @@ public class Suffocate extends AirAbility {
* @param dz z offset
* @param type Spiral animation direction
*/
- public SuffocateSpiral(Location startLoc, int totalSteps, double radius, long interval, double dx, double dy, double dz,
- SpiralType type) {
+ public SuffocateSpiral(Location startLoc, int totalSteps, double radius, long interval, double dx, double dy, double dz, SpiralType type) {
this.startLoc = startLoc;
this.totalSteps = totalSteps;
this.radius = radius;
@@ -483,7 +472,7 @@ public class Suffocate extends AirAbility {
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -494,6 +483,13 @@ public class Suffocate extends AirAbility {
return false;
}
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ locations.add(player.getLocation());
+ return locations;
+ }
+
public boolean isStarted() {
return started;
}
diff --git a/src/com/projectkorra/projectkorra/airbending/Tornado.java b/src/com/projectkorra/projectkorra/airbending/Tornado.java
index 72823cdb..d764de0d 100644
--- a/src/com/projectkorra/projectkorra/airbending/Tornado.java
+++ b/src/com/projectkorra/projectkorra/airbending/Tornado.java
@@ -36,7 +36,7 @@ public class Tornado extends AirAbility {
public Tornado(Player player) {
super(player);
-
+
this.range = getConfig().getDouble("Abilities.Air.Tornado.Range");
this.origin = player.getTargetBlock((HashSet) null, (int) range).getLocation();
this.origin.setY(origin.getY() - 1.0 / 10.0 * currentHeight);
@@ -77,7 +77,7 @@ public class Tornado extends AirAbility {
}
rotateTornado();
}
-
+
@Override
public void remove() {
super.remove();
@@ -199,7 +199,7 @@ public class Tornado extends AirAbility {
public long getCooldown() {
return 0;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -210,6 +210,11 @@ public class Tornado extends AirAbility {
return false;
}
+ @Override
+ public double getCollisionRadius() {
+ return getRadius();
+ }
+
public Location getOrigin() {
return origin;
}
diff --git a/src/com/projectkorra/projectkorra/chiblocking/ChiCombo.java b/src/com/projectkorra/projectkorra/chiblocking/ChiCombo.java
index 7a521b06..66f49a5d 100644
--- a/src/com/projectkorra/projectkorra/chiblocking/ChiCombo.java
+++ b/src/com/projectkorra/projectkorra/chiblocking/ChiCombo.java
@@ -192,7 +192,7 @@ public class ChiCombo extends ChiAbility implements ComboAbility {
public class Immobilize extends ChiCombo {
- public Immobilize(Player player, String name) {
+ public Immobilize(Player player) {
super(player, "Immobilize");
}
diff --git a/src/com/projectkorra/projectkorra/configuration/ConfigManager.java b/src/com/projectkorra/projectkorra/configuration/ConfigManager.java
index 51e73b7b..7d191c1a 100644
--- a/src/com/projectkorra/projectkorra/configuration/ConfigManager.java
+++ b/src/com/projectkorra/projectkorra/configuration/ConfigManager.java
@@ -630,7 +630,7 @@ public class ConfigManager {
config.addDefault("Abilities.Water.IceBlast.Damage", 3);
config.addDefault("Abilities.Water.IceBlast.Range", 20);
config.addDefault("Abilities.Water.IceBlast.DeflectRange", 3);
- config.addDefault("Abilities.Water.IceBlast.CollisionRadius", 2);
+ config.addDefault("Abilities.Water.IceBlast.CollisionRadius", 0.5);
config.addDefault("Abilities.Water.IceBlast.Interval", 20);
config.addDefault("Abilities.Water.IceBlast.Cooldown", 1500);
@@ -650,7 +650,7 @@ public class ConfigManager {
config.addDefault("Abilities.Water.IceSpike.Field.Cooldown", 2000);
config.addDefault("Abilities.Water.IceSpike.Blast.Range", 20);
config.addDefault("Abilities.Water.IceSpike.Blast.Damage", 1);
- config.addDefault("Abilities.Water.IceSpike.Blast.CollisionRadius", 2);
+ config.addDefault("Abilities.Water.IceSpike.Blast.CollisionRadius", 0.5);
config.addDefault("Abilities.Water.IceSpike.Blast.DeflectRange", 3);
config.addDefault("Abilities.Water.IceSpike.Blast.Cooldown", 500);
config.addDefault("Abilities.Water.IceSpike.Blast.SlowCooldown", 5000);
@@ -775,7 +775,7 @@ public class ConfigManager {
config.addDefault("Abilities.Water.WaterManipulation.Damage", 3.0);
config.addDefault("Abilities.Water.WaterManipulation.Range", 25);
config.addDefault("Abilities.Water.WaterManipulation.SelectRange", 16);
- config.addDefault("Abilities.Water.WaterManipulation.CollisionRadius", 2);
+ config.addDefault("Abilities.Water.WaterManipulation.CollisionRadius", 0.5);
config.addDefault("Abilities.Water.WaterManipulation.DeflectRange", 3);
config.addDefault("Abilities.Water.WaterManipulation.Speed", 35);
config.addDefault("Abilities.Water.WaterManipulation.Push", 0.3);
@@ -844,7 +844,7 @@ public class ConfigManager {
config.addDefault("Abilities.Earth.EarthBlast.Push", 0.3);
config.addDefault("Abilities.Earth.EarthBlast.Cooldown", 500);
config.addDefault("Abilities.Earth.EarthBlast.DeflectRange", 3);
- config.addDefault("Abilities.Earth.EarthBlast.CollisionRadius", 2);
+ config.addDefault("Abilities.Earth.EarthBlast.CollisionRadius", 0.5);
config.addDefault("Abilities.Earth.EarthGrab.Enabled", true);
config.addDefault("Abilities.Earth.EarthGrab.SelectRange", 20);
@@ -974,7 +974,7 @@ public class ConfigManager {
config.addDefault("Abilities.Fire.FireBlast.Enabled", true);
config.addDefault("Abilities.Fire.FireBlast.Speed", 20);
config.addDefault("Abilities.Fire.FireBlast.Range", 20);
- config.addDefault("Abilities.Fire.FireBlast.CollisionRadius", 2);
+ config.addDefault("Abilities.Fire.FireBlast.CollisionRadius", 0.5);
config.addDefault("Abilities.Fire.FireBlast.Push", 0.3);
config.addDefault("Abilities.Fire.FireBlast.Damage", 3);
config.addDefault("Abilities.Fire.FireBlast.Cooldown", 1500);
diff --git a/src/com/projectkorra/projectkorra/earthbending/Collapse.java b/src/com/projectkorra/projectkorra/earthbending/Collapse.java
index a0c636d0..57abf294 100644
--- a/src/com/projectkorra/projectkorra/earthbending/Collapse.java
+++ b/src/com/projectkorra/projectkorra/earthbending/Collapse.java
@@ -1,5 +1,7 @@
package com.projectkorra.projectkorra.earthbending;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -25,15 +27,15 @@ public class Collapse extends EarthAbility {
private Vector direction;
private Block block;
private Map affectedBlocks;
-
+
public Collapse(Player player) {
super(player);
setFields();
-
+
if (!bPlayer.canBend(this) || bPlayer.isOnCooldown("CollapsePillar")) {
return;
}
-
+
block = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.LEFT_CLICK);
if (block == null) {
return;
@@ -83,7 +85,7 @@ public class Collapse extends EarthAbility {
private void loadAffectedBlocks() {
affectedBlocks.clear();
Block thisBlock;
-
+
for (int i = 0; i <= distance; i++) {
thisBlock = block.getWorld().getBlockAt(location.clone().add(direction.clone().multiply(-i)));
affectedBlocks.put(thisBlock, thisBlock);
@@ -125,7 +127,7 @@ public class Collapse extends EarthAbility {
if (distance == 0) {
return false;
}
-
+
moveEarth(block, direction, distance);
loadAffectedBlocks();
return location.distanceSquared(origin) < distance * distance;
@@ -156,6 +158,15 @@ public class Collapse extends EarthAbility {
return false;
}
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (Block block : affectedBlocks.values()) {
+ locations.add(block.getLocation());
+ }
+ return locations;
+ }
+
public Location getOrigin() {
return origin;
}
diff --git a/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java b/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java
index f7fad93d..6acbc361 100644
--- a/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java
+++ b/src/com/projectkorra/projectkorra/earthbending/EarthBlast.java
@@ -1,16 +1,6 @@
package com.projectkorra.projectkorra.earthbending;
-import com.projectkorra.projectkorra.BendingPlayer;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ability.AirAbility;
-import com.projectkorra.projectkorra.ability.EarthAbility;
-import com.projectkorra.projectkorra.ability.WaterAbility;
-import com.projectkorra.projectkorra.firebending.Combustion;
-import com.projectkorra.projectkorra.firebending.FireBlast;
-import com.projectkorra.projectkorra.util.BlockSource;
-import com.projectkorra.projectkorra.util.ClickType;
-import com.projectkorra.projectkorra.util.DamageHandler;
-import com.projectkorra.projectkorra.waterbending.WaterManipulation;
+import java.util.ArrayList;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -20,7 +10,14 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
-import java.util.ArrayList;
+import com.projectkorra.projectkorra.BendingPlayer;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.AirAbility;
+import com.projectkorra.projectkorra.ability.EarthAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
+import com.projectkorra.projectkorra.util.BlockSource;
+import com.projectkorra.projectkorra.util.ClickType;
+import com.projectkorra.projectkorra.util.DamageHandler;
public class EarthBlast extends EarthAbility {
@@ -47,7 +44,7 @@ public class EarthBlast extends EarthAbility {
public EarthBlast(Player player) {
super(player);
-
+
this.isProgressing = false;
this.isAtDestination = false;
this.isSettingUp = true;
@@ -59,10 +56,10 @@ public class EarthBlast extends EarthAbility {
this.damage = getConfig().getDouble("Abilities.Earth.EarthBlast.Damage");
this.speed = getConfig().getDouble("Abilities.Earth.EarthBlast.Speed");
this.pushFactor = getConfig().getDouble("Abilities.Earth.EarthBlast.Push");
- this.selectRange = getConfig().getDouble("Abilities.Earth.EarthBlast.SelectRange");
+ this.selectRange = getConfig().getDouble("Abilities.Earth.EarthBlast.SelectRange");
this.time = System.currentTimeMillis();
this.interval = (long) (1000.0 / speed);
-
+
if (prepare()) {
start();
time = System.currentTimeMillis();
@@ -84,9 +81,7 @@ public class EarthBlast extends EarthAbility {
Location location = player.getEyeLocation();
Vector vector = location.getDirection();
Location mloc = blast.location;
- if (mloc.distanceSquared(location) <= range * range
- && GeneralMethods.getDistanceFromLine(vector, location, blast.location) < deflectRange
- && mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
+ if (mloc.distanceSquared(location) <= range * range && GeneralMethods.getDistanceFromLine(vector, location, blast.location) < deflectRange && mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
blast.remove();
remove();
return;
@@ -99,7 +94,7 @@ public class EarthBlast extends EarthAbility {
if (EarthPassive.isPassiveSand(sourceBlock)) {
EarthPassive.revertSand(sourceBlock);
}
-
+
sourceData = sourceBlock.getData();
if (sourceBlock.getType() == Material.SAND) {
sourceType = Material.SAND;
@@ -107,7 +102,7 @@ public class EarthBlast extends EarthAbility {
sourceBlock.setType(Material.RED_SANDSTONE);
} else {
sourceBlock.setType(Material.SANDSTONE);
- }
+ }
} else if (sourceBlock.getType() == Material.STEP) {
sourceBlock.setType(Material.STEP);
sourceType = Material.STEP;
@@ -125,7 +120,7 @@ public class EarthBlast extends EarthAbility {
private Location getTargetLocation() {
Entity target = GeneralMethods.getTargetedEntity(player, range, new ArrayList());
Location location;
-
+
if (target == null) {
location = GeneralMethods.getTargetedLocation(player, range);
} else {
@@ -139,7 +134,7 @@ public class EarthBlast extends EarthAbility {
if (block == null || !isEarthbendable(block)) {
return false;
}
-
+
boolean selectedABlockInUse = false;
for (EarthBlast blast : getAbilities(player, EarthBlast.class)) {
if (!blast.isProgressing) {
@@ -148,11 +143,11 @@ public class EarthBlast extends EarthAbility {
selectedABlockInUse = true;
}
}
-
+
if (selectedABlockInUse) {
return false;
}
-
+
checkForCollision();
if (block.getLocation().distanceSquared(player.getLocation()) > selectRange * selectRange) {
return false;
@@ -169,7 +164,7 @@ public class EarthBlast extends EarthAbility {
remove();
return;
}
-
+
if (System.currentTimeMillis() - time >= interval) {
time = System.currentTimeMillis();
@@ -213,8 +208,8 @@ public class EarthBlast extends EarthAbility {
}
location = location.clone().add(direction);
- Block block = location.getBlock();
-
+ Block block = location.getBlock();
+
if (block.getLocation().equals(sourceBlock.getLocation())) {
location = location.clone().add(direction);
block = location.getBlock();
@@ -229,19 +224,6 @@ public class EarthBlast extends EarthAbility {
location = location.clone().subtract(direction);
direction = GeneralMethods.getDirection(location, destination).normalize();
location = location.clone().add(direction);
-
- WaterAbility.removeWaterSpouts(location, player);
- AirAbility.removeAirSpouts(location, player);
- EarthAbility.removeSandSpouts(location, player);
-
- if (EarthBlast.annihilateBlasts(location, collisionRadius, player)
- || WaterManipulation.annihilateBlasts(location, collisionRadius, player)
- || FireBlast.annihilateBlasts(location, collisionRadius, player)) {
- remove();
- return;
- }
-
- Combustion.removeAroundPoint(location, collisionRadius);
Block block2 = location.getBlock();
if (block2.getLocation().equals(sourceBlock.getLocation())) {
@@ -263,12 +245,12 @@ public class EarthBlast extends EarthAbility {
}
if (entity instanceof LivingEntity && (entity.getEntityId() != player.getEntityId() || canHitSelf)) {
AirAbility.breakBreathbendingHold(entity);
-
+
Location location = player.getEyeLocation();
Vector vector = location.getDirection();
entity.setVelocity(vector.normalize().multiply(pushFactor));
- double damage = this.damage;
-
+ double damage = this.damage;
+
if (isMetal(sourceBlock) && bPlayer.canMetalbend()) {
damage = getMetalAugment(damage);
}
@@ -290,7 +272,7 @@ public class EarthBlast extends EarthAbility {
}
moveEarthBlock(sourceBlock, block);
-
+
if (block.getType() == Material.SAND) {
block.setType(Material.SANDSTONE);
}
@@ -311,8 +293,7 @@ public class EarthBlast extends EarthAbility {
sourceType = Material.SAND;
sourceBlock.setType(sourceType);
sourceBlock.setData((byte) 0x1);
- }
- else {
+ } else {
sourceBlock.setType(sourceType);
}
}
@@ -338,7 +319,7 @@ public class EarthBlast extends EarthAbility {
@Override
public void remove() {
super.remove();
- if(destination != null && sourceBlock != null) {
+ if (destination != null && sourceBlock != null) {
sourceBlock.setType(Material.AIR);
} else if (sourceBlock != null) {
if (sourceBlock.getType() == Material.SAND) {
@@ -360,13 +341,13 @@ public class EarthBlast extends EarthAbility {
if (sourceBlock == null || !sourceBlock.getWorld().equals(player.getWorld())) {
return;
}
-
+
if (getMovedEarth().containsKey(sourceBlock)) {
if (!isEarthRevertOn()) {
removeRevertIndex(sourceBlock);
}
}
-
+
Entity target = GeneralMethods.getTargetedEntity(player, range, new ArrayList());
if (target == null) {
destination = getTargetEarthBlock((int) range).getLocation();
@@ -378,12 +359,12 @@ public class EarthBlast extends EarthAbility {
firstDestination.setY(destination.getY());
destination = GeneralMethods.getPointOnLine(firstDestination, destination, range);
}
-
+
if (destination.distanceSquared(location) <= 1) {
isProgressing = false;
destination = null;
} else {
- isProgressing = true;
+ isProgressing = true;
playEarthbendingSound(sourceBlock.getLocation());
Material currentType = sourceBlock.getType();
@@ -393,11 +374,16 @@ public class EarthBlast extends EarthAbility {
addTempAirBlock(sourceBlock);
} else {
sourceBlock.breakNaturally();
- }
+ }
sourceBlock.setType(currentType);
}
}
-
+
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean annihilateBlasts(Location location, double radius, Player source) {
boolean broke = false;
for (EarthBlast blast : getAbilities(EarthBlast.class)) {
@@ -409,7 +395,7 @@ public class EarthBlast extends EarthAbility {
}
}
return broke;
- }
+ }
public static ArrayList getAroundPoint(Location location, double radius) {
ArrayList list = new ArrayList();
@@ -447,11 +433,8 @@ public class EarthBlast extends EarthAbility {
Location location = player.getEyeLocation();
Vector vector = location.getDirection();
Location mloc = blast.location;
-
- if (mloc.distanceSquared(location) <= blast.range * blast.range
- && GeneralMethods.getDistanceFromLine(vector, location, blast.location) < blast.deflectRange
- && mloc.distanceSquared(location.clone().add(vector))
- < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
+
+ if (mloc.distanceSquared(location) <= blast.range * blast.range && GeneralMethods.getDistanceFromLine(vector, location, blast.location) < blast.deflectRange && mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
blast.redirect(player, blast.getTargetLocation());
}
@@ -472,11 +455,11 @@ public class EarthBlast extends EarthAbility {
ArrayList ignore = new ArrayList();
BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
EarthBlast earthBlast = null;
-
+
if (bPlayer == null) {
return;
}
-
+
for (EarthBlast blast : getAbilities(player, EarthBlast.class)) {
if (!blast.isProgressing && bPlayer.canBend(blast)) {
blast.throwEarth();
@@ -505,7 +488,7 @@ public class EarthBlast extends EarthAbility {
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -516,6 +499,16 @@ public class EarthBlast extends EarthAbility {
return false;
}
+ @Override
+ public boolean isCollidable() {
+ return isProgressing;
+ }
+
+ @Override
+ public double getCollisionRadius() {
+ return collisionRadius;
+ }
+
public boolean isProgressing() {
return isProgressing;
}
@@ -612,10 +605,6 @@ public class EarthBlast extends EarthAbility {
this.deflectRange = deflectRange;
}
- public double getCollisionRadius() {
- return collisionRadius;
- }
-
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}
@@ -660,4 +649,4 @@ public class EarthBlast extends EarthAbility {
this.location = location;
}
-}
\ No newline at end of file
+}
diff --git a/src/com/projectkorra/projectkorra/earthbending/EarthSmash.java b/src/com/projectkorra/projectkorra/earthbending/EarthSmash.java
index 0d37afb7..0f93e0da 100644
--- a/src/com/projectkorra/projectkorra/earthbending/EarthSmash.java
+++ b/src/com/projectkorra/projectkorra/earthbending/EarthSmash.java
@@ -1,14 +1,8 @@
package com.projectkorra.projectkorra.earthbending;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ability.AirAbility;
-import com.projectkorra.projectkorra.ability.EarthAbility;
-import com.projectkorra.projectkorra.ability.WaterAbility;
-import com.projectkorra.projectkorra.avatar.AvatarState;
-import com.projectkorra.projectkorra.util.ClickType;
-import com.projectkorra.projectkorra.util.DamageHandler;
-import com.projectkorra.projectkorra.util.ParticleEffect;
-import com.projectkorra.projectkorra.util.TempBlock;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
import org.bukkit.Effect;
import org.bukkit.Location;
@@ -19,12 +13,16 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.EarthAbility;
+import com.projectkorra.projectkorra.avatar.AvatarState;
+import com.projectkorra.projectkorra.util.ClickType;
+import com.projectkorra.projectkorra.util.DamageHandler;
+import com.projectkorra.projectkorra.util.ParticleEffect;
+import com.projectkorra.projectkorra.util.TempBlock;
public class EarthSmash extends EarthAbility {
-
+
public static enum State {
START, LIFTING, LIFTED, GRABBED, SHOT, FLYING, REMOVED
}
@@ -64,7 +62,7 @@ public class EarthSmash extends EarthAbility {
public EarthSmash(Player player, ClickType type) {
super(player);
-
+
this.state = State.START;
this.requiredBendableBlocks = getConfig().getInt("Abilities.Earth.EarthSmash.RequiredBendableBlocks");
this.maxBlocksToPassThrough = getConfig().getInt("Abilities.Earth.EarthSmash.MaxBlocksToPassThrough");
@@ -89,7 +87,7 @@ public class EarthSmash extends EarthAbility {
this.affectedEntities = new ArrayList<>();
this.currentBlocks = new ArrayList<>();
this.affectedBlocks = new ArrayList<>();
-
+
if (type == ClickType.SHIFT_DOWN || type == ClickType.SHIFT_UP && !player.isSneaking()) {
if (bPlayer.isAvatarState()) {
selectRange = AvatarState.getValue(selectRange);
@@ -119,17 +117,17 @@ public class EarthSmash extends EarthAbility {
}
grabbedSmash = aimingAtSmashCheck(player, State.SHOT);
}
-
+
if (grabbedSmash != null) {
grabbedSmash.state = State.GRABBED;
grabbedSmash.grabbedDistance = 0;
- if(grabbedSmash.location.getWorld().equals(player.getWorld())) {
+ if (grabbedSmash.location.getWorld().equals(player.getWorld())) {
grabbedSmash.grabbedDistance = grabbedSmash.location.distance(player.getEyeLocation());
}
grabbedSmash.player = player;
return;
}
-
+
start();
} else if (type == ClickType.LEFT_CLICK && player.isSneaking()) {
for (EarthSmash smash : getAbilities(EarthSmash.class)) {
@@ -155,11 +153,11 @@ public class EarthSmash extends EarthAbility {
@Override
public void progress() {
progressCounter++;
- if (state == State.LIFTED && removeTimer > 0 && System.currentTimeMillis() - startTime > removeTimer) {
+ if (state == State.LIFTED && removeTimer > 0 && System.currentTimeMillis() - getStartTime() > removeTimer) {
remove();
return;
}
-
+
if (state == State.START) {
if (!bPlayer.canBend(this)) {
remove();
@@ -174,7 +172,7 @@ public class EarthSmash extends EarthAbility {
if (state == State.START && progressCounter > 1) {
if (!player.isSneaking()) {
- if (System.currentTimeMillis() - startTime >= chargeTime) {
+ if (System.currentTimeMillis() - getStartTime() >= chargeTime) {
origin = getEarthSourceBlock(selectRange);
if (origin == null) {
remove();
@@ -187,7 +185,7 @@ public class EarthSmash extends EarthAbility {
remove();
return;
}
- } else if (System.currentTimeMillis() - startTime > chargeTime) {
+ } else if (System.currentTimeMillis() - getStartTime() > chargeTime) {
Location tempLoc = player.getEyeLocation().add(player.getEyeLocation().getDirection().normalize().multiply(1.2));
tempLoc.add(0, 0.3, 0);
ParticleEffect.SMOKE.display(tempLoc, 0.3F, 0.1F, 0.3F, 0, 4);
@@ -210,10 +208,7 @@ public class EarthSmash extends EarthAbility {
break;
}
}
-
- WaterAbility.removeWaterSpouts(location, 2, player);
- AirAbility.removeAirSpouts(location, 2, player);
- EarthAbility.removeSandSpouts(location, player);
+
draw();
return;
} else {
@@ -227,20 +222,18 @@ public class EarthSmash extends EarthAbility {
remove();
return;
}
-
+
revert();
location.add(GeneralMethods.getDirection(location, destination).normalize().multiply(1));
if (location.distanceSquared(destination) < 4) {
remove();
return;
}
-
+
// If an earthsmash runs into too many blocks we should remove it
int badBlocksFound = 0;
for (Block block : getBlocks()) {
- if (block.getType() != Material.AIR && (!isTransparent(block)
- || block.getType() == Material.WATER
- || block.getType() == Material.STATIONARY_WATER)) {
+ if (block.getType() != Material.AIR && (!isTransparent(block) || block.getType() == Material.WATER || block.getType() == Material.STATIONARY_WATER)) {
badBlocksFound++;
}
}
@@ -249,8 +242,6 @@ public class EarthSmash extends EarthAbility {
remove();
return;
}
- WaterAbility.removeWaterSpouts(location, 2, player);
- AirAbility.removeAirSpouts(location, 2, player);
shootingCollisionDetection();
draw();
smashToSmashCollisionDetection();
@@ -298,10 +289,10 @@ public class EarthSmash extends EarthAbility {
/**
* Begins animating the EarthSmash from the ground. The lift animation
- * consists of 3 steps, and each one has to design the shape in the
- * ground that removes the Earthbendable material. We also need to make
- * sure that there is a clear path for the EarthSmash to rise, and that
- * there is enough Earthbendable material for it to be created.
+ * consists of 3 steps, and each one has to design the shape in the ground
+ * that removes the Earthbendable material. We also need to make sure that
+ * there is a clear path for the EarthSmash to rise, and that there is
+ * enough Earthbendable material for it to be created.
*/
@SuppressWarnings("deprecation")
public void animateLift() {
@@ -368,7 +359,7 @@ public class EarthSmash extends EarthAbility {
}
}
}
-
+
/*
* We needed to calculate all of the blocks based on the
* location being 1 above the initial bending block, however we
@@ -424,14 +415,13 @@ public class EarthSmash extends EarthAbility {
}
/**
- * Checks to see which of the blocks are still attached to the
- * EarthSmash, remember that blocks can be broken or used in other
- * abilities so we need to double check and remove any that are not
- * still attached.
+ * Checks to see which of the blocks are still attached to the EarthSmash,
+ * remember that blocks can be broken or used in other abilities so we need
+ * to double check and remove any that are not still attached.
*
- * Also when we remove the blocks from instances, movedearth, or tempair
- * we should do it on a delay because tempair takes a couple seconds
- * before the block shows up in that map.
+ * Also when we remove the blocks from instances, movedearth, or tempair we
+ * should do it on a delay because tempair takes a couple seconds before the
+ * block shows up in that map.
*/
public void checkRemainingBlocks() {
for (int i = 0; i < currentBlocks.size(); i++) {
@@ -452,9 +442,8 @@ public class EarthSmash extends EarthAbility {
}
/**
- * Gets the blocks surrounding the EarthSmash's loc. This method ignores
- * the blocks that should be Air, and only returns the ones that are
- * dirt.
+ * Gets the blocks surrounding the EarthSmash's loc. This method ignores the
+ * blocks that should be Air, and only returns the ones that are dirt.
*/
public List getBlocks() {
List blocks = new ArrayList();
@@ -473,8 +462,8 @@ public class EarthSmash extends EarthAbility {
}
/**
- * Gets the blocks surrounding the EarthSmash's loc. This method returns
- * all the blocks surrounding the loc, including dirt and air.
+ * Gets the blocks surrounding the EarthSmash's loc. This method returns all
+ * the blocks surrounding the loc, including dirt and air.
*/
public List getBlocksIncludingInner() {
List blocks = new ArrayList();
@@ -489,7 +478,7 @@ public class EarthSmash extends EarthAbility {
}
return blocks;
}
-
+
/**
* Switches the Sand Material and Gravel to SandStone and stone
* respectively, since gravel and sand cannot be bent due to gravity.
@@ -516,17 +505,16 @@ public class EarthSmash extends EarthAbility {
}
return tempMat;
}
-
+
/**
* Determines if a player is trying to grab an EarthSmash. A player is
- * trying to grab an EarthSmash if they are staring at it and holding
- * shift.
+ * trying to grab an EarthSmash if they are staring at it and holding shift.
*/
private EarthSmash aimingAtSmashCheck(Player player, State reqState) {
if (!allowGrab) {
return null;
}
-
+
List blocks = GeneralMethods.getBlocksAroundPoint(GeneralMethods.getTargetedLocation(player, grabRange, GeneralMethods.NON_OPAQUE), 1);
for (EarthSmash smash : getAbilities(EarthSmash.class)) {
if (reqState == null || smash.state == reqState) {
@@ -534,8 +522,7 @@ public class EarthSmash extends EarthAbility {
if (block == null || smash.getLocation() == null) {
continue;
}
- if (block.getLocation().getWorld() == smash.location.getWorld()
- && block.getLocation().distanceSquared(smash.location) <= Math.pow(grabDetectionRadius, 2)) {
+ if (block.getLocation().getWorld() == smash.location.getWorld() && block.getLocation().distanceSquared(smash.location) <= Math.pow(grabDetectionRadius, 2)) {
return smash;
}
}
@@ -546,8 +533,8 @@ public class EarthSmash extends EarthAbility {
/**
* This method handles any collision between an EarthSmash and the
- * surrounding entities, the method only applies to earthsmashes that
- * have already been shot.
+ * surrounding entities, the method only applies to earthsmashes that have
+ * already been shot.
*/
public void shootingCollisionDetection() {
List entities = GeneralMethods.getEntitiesAroundPoint(location, flightDetectionRadius);
@@ -561,28 +548,27 @@ public class EarthSmash extends EarthAbility {
}
}
}
-
+
/**
* EarthSmash to EarthSmash collision can only happen when one of the
- * Smashes have been shot by a player. If we find out that one of them
- * have collided then we want to return since a smash can only remove 1
- * at a time.
+ * Smashes have been shot by a player. If we find out that one of them have
+ * collided then we want to return since a smash can only remove 1 at a
+ * time.
*/
public void smashToSmashCollisionDetection() {
for (EarthSmash smash : getAbilities(EarthSmash.class)) {
- if (smash.location != null && smash != this && smash.location.getWorld() == location.getWorld()
- && smash.location.distanceSquared(location) < Math.pow(flightDetectionRadius, 2)) {
+ if (smash.location != null && smash != this && smash.location.getWorld() == location.getWorld() && smash.location.distanceSquared(location) < Math.pow(flightDetectionRadius, 2)) {
smash.remove();
remove();
return;
}
}
}
-
+
/**
* Determines whether or not a player is trying to fly ontop of an
- * EarthSmash. A player is considered "flying" if they are standing
- * ontop of the earthsmash and holding shift.
+ * EarthSmash. A player is considered "flying" if they are standing ontop of
+ * the earthsmash and holding shift.
*/
private static EarthSmash flyingInSmashCheck(Player player) {
for (EarthSmash smash : getAbilities(EarthSmash.class)) {
@@ -591,8 +577,7 @@ public class EarthSmash extends EarthAbility {
}
//Check to see if the player is standing on top of the smash.
if (smash.state == State.LIFTED) {
- if (smash.location.getWorld().equals(player.getWorld())
- && smash.location.clone().add(0, 2, 0).distanceSquared(player.getLocation()) <= Math.pow(smash.flightDetectionRadius, 2)) {
+ if (smash.location.getWorld().equals(player.getWorld()) && smash.location.clone().add(0, 2, 0).distanceSquared(player.getLocation()) <= Math.pow(smash.flightDetectionRadius, 2)) {
return smash;
}
}
@@ -601,12 +586,11 @@ public class EarthSmash extends EarthAbility {
}
/**
- * A BlockRepresenter is used to keep track of each of the individual
- * types of blocks that are attached to an EarthSmash. Without the
- * representer then an EarthSmash can only be made up of 1 material at a
- * time. For example, an ESmash that is entirely dirt, coalore, or
- * sandstone. Using the representer will allow all the materials to be
- * mixed together.
+ * A BlockRepresenter is used to keep track of each of the individual types
+ * of blocks that are attached to an EarthSmash. Without the representer
+ * then an EarthSmash can only be made up of 1 material at a time. For
+ * example, an ESmash that is entirely dirt, coalore, or sandstone. Using
+ * the representer will allow all the materials to be mixed together.
*/
public class BlockRepresenter {
private int x, y, z;
@@ -706,7 +690,7 @@ public class EarthSmash extends EarthAbility {
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -717,6 +701,15 @@ public class EarthSmash extends EarthAbility {
return false;
}
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (TempBlock tblock : affectedBlocks) {
+ locations.add(tblock.getLocation());
+ }
+ return locations;
+ }
+
public boolean isAllowGrab() {
return allowGrab;
}
@@ -836,7 +829,7 @@ public class EarthSmash extends EarthAbility {
public void setGrabRange(double grabRange) {
this.grabRange = grabRange;
}
-
+
public double getSelectRange() {
return selectRange;
}
diff --git a/src/com/projectkorra/projectkorra/earthbending/EarthTunnel.java b/src/com/projectkorra/projectkorra/earthbending/EarthTunnel.java
index cdea4f58..c1a8e375 100644
--- a/src/com/projectkorra/projectkorra/earthbending/EarthTunnel.java
+++ b/src/com/projectkorra/projectkorra/earthbending/EarthTunnel.java
@@ -1,6 +1,8 @@
package com.projectkorra.projectkorra.earthbending;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -16,7 +18,7 @@ import com.projectkorra.projectkorra.configuration.ConfigManager;
import com.projectkorra.projectkorra.util.TempBlock;
public class EarthTunnel extends EarthAbility {
-
+
private long interval;
private long time;
private double depth;
@@ -32,10 +34,10 @@ public class EarthTunnel extends EarthAbility {
private Vector direction;
public static Map airBlocks = new ConcurrentHashMap();
-
+
public EarthTunnel(Player player) {
super(player);
-
+
this.maxRadius = getConfig().getDouble("Abilities.Earth.EarthTunnel.MaxRadius");
this.range = getConfig().getDouble("Abilities.Earth.EarthTunnel.Range");
this.radius = getConfig().getDouble("Abilities.Earth.EarthTunnel.Radius");
@@ -43,21 +45,21 @@ public class EarthTunnel extends EarthAbility {
this.revert = getConfig().getBoolean("Abilities.Earth.EarthTunnel.Revert");
this.radiusIncrement = radius;
this.time = System.currentTimeMillis();
-
+
this.location = player.getEyeLocation().clone();
this.origin = player.getTargetBlock((HashSet) null, (int) range).getLocation();
this.block = origin.getBlock();
this.direction = location.getDirection().clone().normalize();
this.depth = 0;
- if(origin.getWorld().equals(location.getWorld())) {
- this.depth = Math.max(0, origin.distance(location) - 1);
+ if (origin.getWorld().equals(location.getWorld())) {
+ this.depth = Math.max(0, origin.distance(location) - 1);
}
this.angle = 0;
if (!bPlayer.canBend(this)) {
return;
}
-
+
start();
}
@@ -67,7 +69,7 @@ public class EarthTunnel extends EarthAbility {
remove();
return;
}
-
+
if (System.currentTimeMillis() - time >= interval) {
time = System.currentTimeMillis();
if (Math.abs(Math.toDegrees(player.getEyeLocation().getDirection().angle(direction))) > 20 || !player.isSneaking()) {
@@ -79,7 +81,7 @@ public class EarthTunnel extends EarthAbility {
remove();
return;
}
-
+
if (angle >= 360) {
angle = 0;
if (radius >= maxRadius) {
@@ -96,11 +98,11 @@ public class EarthTunnel extends EarthAbility {
} else {
angle += 20;
}
-
+
Vector vec = GeneralMethods.getOrthogonalVector(direction, angle, radius);
block = location.clone().add(direction.clone().normalize().multiply(depth)).add(vec).getBlock();
}
-
+
if (revert) {
if (getMovedEarth().containsKey(block)) {
block.setType(Material.AIR);
@@ -128,7 +130,7 @@ public class EarthTunnel extends EarthAbility {
public long getCooldown() {
return 0;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -139,6 +141,15 @@ public class EarthTunnel extends EarthAbility {
return false;
}
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (TempBlock tblock : airBlocks.keySet()) {
+ locations.add(tblock.getLocation());
+ }
+ return locations;
+ }
+
public long getInterval() {
return interval;
}
@@ -230,7 +241,7 @@ public class EarthTunnel extends EarthAbility {
public void setLocation(Location location) {
this.location = location;
}
-
+
public static void revertAirBlocks() {
if (ConfigManager.defaultConfig.get().getBoolean("Abilities.Earth.EarthTunnel.Revert")) {
for (TempBlock tempBlock : EarthTunnel.airBlocks.keySet()) {
@@ -241,5 +252,5 @@ public class EarthTunnel extends EarthAbility {
}
}
}
-
+
}
diff --git a/src/com/projectkorra/projectkorra/earthbending/LavaFlow.java b/src/com/projectkorra/projectkorra/earthbending/LavaFlow.java
index 093db5df..c056f401 100644
--- a/src/com/projectkorra/projectkorra/earthbending/LavaFlow.java
+++ b/src/com/projectkorra/projectkorra/earthbending/LavaFlow.java
@@ -18,12 +18,13 @@ import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
public class LavaFlow extends LavaAbility {
-
+
public static enum AbilityType {
SHIFT, CLICK
}
@@ -31,7 +32,7 @@ public class LavaFlow extends LavaAbility {
private static final Map TEMP_LAVA_BLOCKS = new ConcurrentHashMap<>();
private static final Map TEMP_LAND_BLOCKS = new ConcurrentHashMap<>();
private static final Map TEMP_AIR_BLOCKS = new ConcurrentHashMap<>();
-
+
private boolean removing;
private boolean makeLava;
private boolean clickIsFinished;
@@ -66,7 +67,7 @@ public class LavaFlow extends LavaAbility {
private ArrayList affectedBlocks;
private ArrayList tasks;
private Material revertMaterial;
-
+
/**
* Creates a new LavaFlow ability and initializes all of the variables and
* cooldowns. The ability is not guaranteed to continue, it may be the case
@@ -155,7 +156,7 @@ public class LavaFlow extends LavaAbility {
remove();
return;
}
-
+
long cooldown = makeLava ? clickLavaCooldown : clickLandCooldown;
origin = sourceBlock.getLocation();
makeLava = !isLava(sourceBlock);
@@ -187,7 +188,7 @@ public class LavaFlow extends LavaAbility {
}
Random random = new Random();
-
+
if (type == AbilityType.SHIFT) {
if (System.currentTimeMillis() - time > shiftRemoveDelay) {
remove();
@@ -249,23 +250,20 @@ public class LavaFlow extends LavaAbility {
createLava(block);
}
}
-
+
}
- } else if (Math.random() < particleDensity
- && dSquared < Math.pow(currentRadius + particleDensity, 2)
- && currentRadius + particleDensity < shiftMaxRadius
- && random.nextInt(3) == 0) {
+ } else if (Math.random() < particleDensity && dSquared < Math.pow(currentRadius + particleDensity, 2) && currentRadius + particleDensity < shiftMaxRadius && random.nextInt(3) == 0) {
ParticleEffect.LAVA.display(loc, (float) Math.random(), (float) Math.random(), (float) Math.random(), 0, 1);
}
}
}
-
- if(!shiftIsFinished) {
+
+ if (!shiftIsFinished) {
if (random.nextInt(10) == 0) {
ParticleEffect.LAVA.display(player.getLocation(), (float) Math.random(), (float) Math.random(), (float) Math.random(), 0, 1);
}
}
-
+
currentRadius += shiftFlowSpeed;
if (currentRadius > shiftMaxRadius) {
currentRadius = shiftMaxRadius;
@@ -274,16 +272,17 @@ public class LavaFlow extends LavaAbility {
}
} else if (type == AbilityType.CLICK) {
/*
- * The variable makeLava refers to whether or not the ability is trying
- * to remove land in place of lava or if makeLava = false then lava is
- * being replaced with land.
+ * The variable makeLava refers to whether or not the ability is
+ * trying to remove land in place of lava or if makeLava = false
+ * then lava is being replaced with land.
*
- * Notice we have separate variables between both versions, because most
- * of the time making lava will have longer delays and longer cooldowns.
+ * Notice we have separate variables between both versions, because
+ * most of the time making lava will have longer delays and longer
+ * cooldowns.
*/
long curTime = System.currentTimeMillis() - time;
double delay = makeLava ? clickLavaDelay : clickLandDelay;
-
+
if (makeLava && curTime > clickLavaCleanupDelay) {
remove();
return;
@@ -297,9 +296,8 @@ public class LavaFlow extends LavaAbility {
for (double z = -clickLavaRadius; z <= clickLavaRadius; z++) {
Location loc = origin.clone().add(x, 0, z);
Block tempBlock = GeneralMethods.getTopBlock(loc, upwardFlow, downwardFlow);
-
- if (tempBlock != null && !isLava(tempBlock) && Math.random() < particleDensity
- && tempBlock.getLocation().distanceSquared(origin) <= Math.pow(clickLavaRadius, 2)) {
+
+ if (tempBlock != null && !isLava(tempBlock) && Math.random() < particleDensity && tempBlock.getLocation().distanceSquared(origin) <= Math.pow(clickLavaRadius, 2)) {
if (random.nextInt(3) == 0) {
ParticleEffect.LAVA.display(loc, (float) Math.random(), (float) Math.random(), (float) Math.random(), 0, 1);
}
@@ -317,7 +315,7 @@ public class LavaFlow extends LavaAbility {
if (!clickIsFinished) {
clickIsFinished = true;
double radius = makeLava ? clickLavaRadius : clickLandRadius;
-
+
for (double x = -radius; x <= radius; x++) {
for (double z = -radius; z <= radius; z++) {
Location loc = origin.clone().add(x, 0, z);
@@ -398,14 +396,15 @@ public class LavaFlow extends LavaAbility {
TempBlock tb = new TempBlock(above, Material.AIR, (byte) 0);
TEMP_AIR_BLOCKS.put(above, tb);
affectedBlocks.add(tb);
- } else return;
- }
+ } else
+ return;
+ }
TempBlock tblock = new TempBlock(block, Material.LAVA, (byte) 0);
TEMP_LAVA_BLOCKS.put(block, tblock);
affectedBlocks.add(tblock);
-
+
if (allowNaturalFlow) {
-// ProjectKorra.plugin.getLogger().info("Flow free!");
+ // ProjectKorra.plugin.getLogger().info("Flow free!");
TempBlock.removeBlock(block);
}
}
@@ -469,7 +468,7 @@ public class LavaFlow extends LavaAbility {
tblock.getBlock().getRelative(BlockFace.UP).setType(Material.DOUBLE_PLANT);
tblock.getBlock().getRelative(BlockFace.UP).setData((byte) (tblock.getState().getRawData() + 8));
}
-
+
}
}.runTaskLater(ProjectKorra.plugin, (long) (i / shiftRemoveSpeed));
@@ -515,7 +514,6 @@ public class LavaFlow extends LavaAbility {
task.cancel();
}
}
-
/**
* Returns a list of all the Lava blocks that are adjacent to the block at
@@ -546,7 +544,7 @@ public class LavaFlow extends LavaAbility {
public static ArrayList getAdjacentBlocks(Location loc) {
ArrayList list = new ArrayList();
Block block = loc.getBlock();
-
+
for (int x = -1; x <= 1; x++) {
for (int y = -2; y <= 1; y++) {
for (int z = -1; z <= 1; z++) {
@@ -594,18 +592,18 @@ public class LavaFlow extends LavaAbility {
}
return list;
}
-
+
public static Material getRevertMaterial() {
Material m = Material.STONE;
LavaFlow lf = (LavaFlow) CoreAbility.getAbility("LavaFlow");
m = lf.revertMaterial;
return m;
}
-
+
public static Map getTempLandBlocks() {
return TEMP_LAND_BLOCKS;
}
-
+
public static Map getTempLavaBlocks() {
return TEMP_LAVA_BLOCKS;
}
@@ -629,7 +627,7 @@ public class LavaFlow extends LavaAbility {
public long getCooldown() {
return type == AbilityType.CLICK ? clickLandCooldown : shiftCooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -640,6 +638,15 @@ public class LavaFlow extends LavaAbility {
return false;
}
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (TempBlock tblock : affectedBlocks) {
+ locations.add(tblock.getLocation());
+ }
+ return locations;
+ }
+
public boolean isRemoving() {
return removing;
}
@@ -895,5 +902,5 @@ public class LavaFlow extends LavaAbility {
public ArrayList getTasks() {
return tasks;
}
-
+
}
diff --git a/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java b/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java
index 0b8eccb3..20220128 100644
--- a/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java
+++ b/src/com/projectkorra/projectkorra/earthbending/RaiseEarth.java
@@ -13,6 +13,8 @@ import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -178,6 +180,15 @@ public class RaiseEarth extends EarthAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (Block block : affectedBlocks.values()) {
+ locations.add(block.getLocation());
+ }
+ return locations;
+ }
public int getDistance() {
return distance;
diff --git a/src/com/projectkorra/projectkorra/earthbending/Ripple.java b/src/com/projectkorra/projectkorra/earthbending/Ripple.java
index 04ee67d1..9ada5849 100644
--- a/src/com/projectkorra/projectkorra/earthbending/Ripple.java
+++ b/src/com/projectkorra/projectkorra/earthbending/Ripple.java
@@ -1,10 +1,8 @@
package com.projectkorra.projectkorra.earthbending;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ability.AirAbility;
-import com.projectkorra.projectkorra.ability.EarthAbility;
-import com.projectkorra.projectkorra.avatar.AvatarState;
-import com.projectkorra.projectkorra.util.DamageHandler;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -16,9 +14,11 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.AirAbility;
+import com.projectkorra.projectkorra.ability.EarthAbility;
+import com.projectkorra.projectkorra.avatar.AvatarState;
+import com.projectkorra.projectkorra.util.DamageHandler;
public class Ripple extends EarthAbility {
@@ -328,6 +328,11 @@ public class Ripple extends EarthAbility {
return false;
}
+ @Override
+ public ArrayList getLocations() {
+ return locations;
+ }
+
public int getStep() {
return step;
}
@@ -416,10 +421,6 @@ public class Ripple extends EarthAbility {
this.block4 = block4;
}
- public ArrayList getLocations() {
- return locations;
- }
-
public ArrayList getEntities() {
return entities;
}
diff --git a/src/com/projectkorra/projectkorra/earthbending/SandSpout.java b/src/com/projectkorra/projectkorra/earthbending/SandSpout.java
index 1925f6ac..57d81b63 100644
--- a/src/com/projectkorra/projectkorra/earthbending/SandSpout.java
+++ b/src/com/projectkorra/projectkorra/earthbending/SandSpout.java
@@ -1,9 +1,9 @@
package com.projectkorra.projectkorra.earthbending;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ability.SandAbility;
-import com.projectkorra.projectkorra.util.DamageHandler;
-import com.projectkorra.projectkorra.util.Flight;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Random;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -13,8 +13,10 @@ import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
-import java.util.Collection;
-import java.util.Random;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.SandAbility;
+import com.projectkorra.projectkorra.util.DamageHandler;
+import com.projectkorra.projectkorra.util.Flight;
public class SandSpout extends SandAbility {
@@ -259,6 +261,20 @@ public class SandSpout extends SandAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ if (player == null) {
+ return locations;
+ }
+ Location top = player.getLocation();
+ double ySpacing = 2;
+ for (double i = 0; i < this.getHeight(); i += ySpacing) {
+ locations.add(top.clone().add(0, -i, 0));
+ }
+ return locations;
+ }
public boolean isCanSpiral() {
return canSpiral;
diff --git a/src/com/projectkorra/projectkorra/earthbending/Shockwave.java b/src/com/projectkorra/projectkorra/earthbending/Shockwave.java
index a4053149..9c828a45 100644
--- a/src/com/projectkorra/projectkorra/earthbending/Shockwave.java
+++ b/src/com/projectkorra/projectkorra/earthbending/Shockwave.java
@@ -64,7 +64,7 @@ public class Shockwave extends EarthAbility {
return;
}
- if (System.currentTimeMillis() > startTime + chargeTime && !charged) {
+ if (System.currentTimeMillis() > getStartTime() + chargeTime && !charged) {
charged = true;
}
diff --git a/src/com/projectkorra/projectkorra/event/AbilityCollisionEvent.java b/src/com/projectkorra/projectkorra/event/AbilityCollisionEvent.java
new file mode 100644
index 00000000..82deed93
--- /dev/null
+++ b/src/com/projectkorra/projectkorra/event/AbilityCollisionEvent.java
@@ -0,0 +1,42 @@
+package com.projectkorra.projectkorra.event;
+
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import com.projectkorra.projectkorra.ability.util.Collision;
+
+public class AbilityCollisionEvent extends Event implements Cancellable {
+
+ private static final HandlerList HANDLERS = new HandlerList();
+
+ private boolean cancelled;
+ private Collision collision;
+
+ public AbilityCollisionEvent(Collision collision) {
+ this.collision = collision;
+ this.cancelled = false;
+ }
+
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ public void setCancelled(boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+
+ public Collision getCollision() {
+ return collision;
+ }
+
+ public void setCollision(Collision collision) {
+ this.collision = collision;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return HANDLERS;
+ }
+
+}
diff --git a/src/com/projectkorra/projectkorra/firebending/Combustion.java b/src/com/projectkorra/projectkorra/firebending/Combustion.java
index 47d90909..b42f113c 100644
--- a/src/com/projectkorra/projectkorra/firebending/Combustion.java
+++ b/src/com/projectkorra/projectkorra/firebending/Combustion.java
@@ -4,6 +4,7 @@ import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.CombustionAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect;
@@ -77,6 +78,11 @@ public class Combustion extends CombustionAbility {
}
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean removeAroundPoint(Location loc, double radius) {
for (Combustion combustion : getAbilities(Combustion.class)) {
if (combustion.location.getWorld().equals(loc.getWorld())) {
@@ -176,6 +182,11 @@ public class Combustion extends CombustionAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public double getCollisionRadius() {
+ return getRadius();
+ }
public boolean isBreakBlocks() {
return breakBlocks;
diff --git a/src/com/projectkorra/projectkorra/firebending/FireBlast.java b/src/com/projectkorra/projectkorra/firebending/FireBlast.java
index 2c165f54..4b7015fd 100644
--- a/src/com/projectkorra/projectkorra/firebending/FireBlast.java
+++ b/src/com/projectkorra/projectkorra/firebending/FireBlast.java
@@ -1,17 +1,8 @@
package com.projectkorra.projectkorra.firebending;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ProjectKorra;
-import com.projectkorra.projectkorra.ability.AirAbility;
-import com.projectkorra.projectkorra.ability.EarthAbility;
-import com.projectkorra.projectkorra.ability.FireAbility;
-import com.projectkorra.projectkorra.ability.WaterAbility;
-import com.projectkorra.projectkorra.avatar.AvatarState;
-import com.projectkorra.projectkorra.earthbending.EarthBlast;
-import com.projectkorra.projectkorra.util.DamageHandler;
-import com.projectkorra.projectkorra.util.ParticleEffect;
-import com.projectkorra.projectkorra.waterbending.PlantRegrowth;
-import com.projectkorra.projectkorra.waterbending.WaterManipulation;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
import org.bukkit.Location;
import org.bukkit.Material;
@@ -23,9 +14,15 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ProjectKorra;
+import com.projectkorra.projectkorra.ability.AirAbility;
+import com.projectkorra.projectkorra.ability.FireAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
+import com.projectkorra.projectkorra.avatar.AvatarState;
+import com.projectkorra.projectkorra.util.DamageHandler;
+import com.projectkorra.projectkorra.util.ParticleEffect;
+import com.projectkorra.projectkorra.waterbending.PlantRegrowth;
public class FireBlast extends FireAbility {
@@ -196,18 +193,6 @@ public class FireBlast extends FireAbility {
return;
}
- WaterAbility.removeWaterSpouts(location, player);
- AirAbility.removeAirSpouts(location, player);
- EarthAbility.removeSandSpouts(location, player);
-
- Player source = player;
- if (EarthBlast.annihilateBlasts(location, collisionRadius, source)
- || WaterManipulation.annihilateBlasts(location, collisionRadius, source)
- || FireBlast.annihilateBlasts(location, collisionRadius, source)) {
- remove();
- return;
- }
-
for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, collisionRadius)) {
affect(entity);
if (entity instanceof LivingEntity) {
@@ -218,6 +203,11 @@ public class FireBlast extends FireAbility {
advanceLocation();
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean annihilateBlasts(Location location, double radius, Player source) {
boolean broke = false;
for (FireBlast blast : getAbilities(FireBlast.class)) {
@@ -284,6 +274,11 @@ public class FireBlast extends FireAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public double getCollisionRadius() {
+ return collisionRadius;
+ }
public boolean isPowerFurnace() {
return powerFurnace;
@@ -349,10 +344,6 @@ public class FireBlast extends FireAbility {
this.speed = speed;
}
- public double getCollisionRadius() {
- return collisionRadius;
- }
-
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}
diff --git a/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java b/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java
index 6466290b..45012a1a 100644
--- a/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java
+++ b/src/com/projectkorra/projectkorra/firebending/FireBlastCharged.java
@@ -252,7 +252,7 @@ public class FireBlastCharged extends FireAbility {
return;
}
- if (System.currentTimeMillis() > startTime + chargeTime) {
+ if (System.currentTimeMillis() > getStartTime() + chargeTime) {
charged = true;
}
if (!player.isSneaking() && !launched) {
@@ -320,6 +320,16 @@ public class FireBlastCharged extends FireAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public boolean isCollidable() {
+ return this.launched;
+ }
+
+ @Override
+ public double getCollisionRadius() {
+ return collisionRadius;
+ }
public boolean isCharged() {
return charged;
@@ -393,10 +403,6 @@ public class FireBlastCharged extends FireAbility {
this.range = range;
}
- public double getCollisionRadius() {
- return collisionRadius;
- }
-
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}
diff --git a/src/com/projectkorra/projectkorra/firebending/FireBurst.java b/src/com/projectkorra/projectkorra/firebending/FireBurst.java
index 7a9b1bbb..b5751018 100644
--- a/src/com/projectkorra/projectkorra/firebending/FireBurst.java
+++ b/src/com/projectkorra/projectkorra/firebending/FireBurst.java
@@ -117,7 +117,7 @@ public class FireBurst extends FireAbility {
return;
}
- if (System.currentTimeMillis() > startTime + chargeTime && !charged) {
+ if (System.currentTimeMillis() > getStartTime() + chargeTime && !charged) {
charged = true;
}
diff --git a/src/com/projectkorra/projectkorra/firebending/FireCombo.java b/src/com/projectkorra/projectkorra/firebending/FireCombo.java
index 0a42b803..9c50454b 100644
--- a/src/com/projectkorra/projectkorra/firebending/FireCombo.java
+++ b/src/com/projectkorra/projectkorra/firebending/FireCombo.java
@@ -1,6 +1,7 @@
package com.projectkorra.projectkorra.firebending;
import java.util.ArrayList;
+import java.util.List;
import org.bukkit.Effect;
import org.bukkit.Location;
@@ -16,12 +17,11 @@ import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
-import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.ComboAbility;
-import com.projectkorra.projectkorra.ability.EarthAbility;
import com.projectkorra.projectkorra.ability.ElementalAbility;
import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.ability.WaterAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation;
import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.command.Commands;
@@ -30,26 +30,11 @@ import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect;
/*
- * TODO: Combo classes should eventually be rewritten so that each combo is treated
- * as an individual ability. In the mean time, we will just place "fake"
- * classes so that CoreAbility will register each ability.
+ * TODO: Combo classes should eventually be rewritten so that each combo is
+ * treated as an individual ability. In the mean time, we will just place "fake"
+ * classes so that CoreAbility will register each ability.
*/
public class FireCombo extends FireAbility implements ComboAbility {
-
- private static final ArrayList BLOCKABLE_ABILITIES = new ArrayList() {
- private static final long serialVersionUID = 0; {
- add("AirShield");
- add("FireShield");
- add("AirSwipe");
- add("FireBlast");
- add("EarthBlast");
- add("WaterManipulation");
- add("Combustion");
- add("FireKick");
- add("FireSpin");
- add("AirSweep");
- }
- };
private boolean firstTime;
private int progressCounter;
@@ -70,20 +55,20 @@ public class FireCombo extends FireAbility implements ComboAbility {
private Vector direction;
private ArrayList affectedEntities;
private ArrayList tasks;
-
+
public FireCombo(Player player, String ability) {
super(player);
this.ability = ability;
-
+
if (!bPlayer.canBendIgnoreBindsCooldowns(this)) {
return;
}
-
+
this.firstTime = true;
this.time = System.currentTimeMillis();
this.affectedEntities = new ArrayList<>();
this.tasks = new ArrayList<>();
-
+
if (ability.equalsIgnoreCase("FireKick")) {
this.damage = getConfig().getDouble("Abilities.Fire.FireCombo.FireKick.Damage");
this.range = getConfig().getDouble("Abilities.Fire.FireCombo.FireKick.Range");
@@ -112,7 +97,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
this.cooldown = getConfig().getLong("Abilities.Fire.FireCombo.JetBlaze.Cooldown");
this.fireTicks = getConfig().getDouble("Abilities.Fire.FireCombo.JetBlaze.FireTicks");
}
-
+
if (bPlayer.isAvatarState()) {
this.cooldown = 0;
this.damage = AvatarState.getValue(damage);
@@ -121,10 +106,9 @@ public class FireCombo extends FireAbility implements ComboAbility {
start();
}
-
/**
- * Returns all of the FireCombos created by a specific player but filters the abilities based on
- * shift or click.
+ * Returns all of the FireCombos created by a specific player but filters
+ * the abilities based on shift or click.
*/
public static ArrayList getFireCombo(Player player, ClickType type) {
ArrayList list = new ArrayList();
@@ -136,6 +120,11 @@ public class FireCombo extends FireAbility implements ComboAbility {
return list;
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean removeAroundPoint(Player player, String ability, Location loc, double radius) {
boolean removed = false;
for (FireCombo combo : getAbilities(FireCombo.class)) {
@@ -145,8 +134,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
if (ability.equalsIgnoreCase("FireKick") && combo.ability.equalsIgnoreCase("FireKick")) {
for (FireComboStream fs : combo.tasks) {
- if (fs.getLocation() != null && fs.getLocation().getWorld() == loc.getWorld()
- && Math.abs(fs.getLocation().distanceSquared(loc)) <= radius * radius) {
+ if (fs.getLocation() != null && fs.getLocation().getWorld() == loc.getWorld() && Math.abs(fs.getLocation().distanceSquared(loc)) <= radius * radius) {
fs.remove();
removed = true;
}
@@ -160,9 +148,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
}
}
}
- }
-
- else if (ability.equalsIgnoreCase("FireWheel") && combo.ability.equalsIgnoreCase("FireWheel")) {
+ } else if (ability.equalsIgnoreCase("FireWheel") && combo.ability.equalsIgnoreCase("FireWheel")) {
if (combo.location != null && Math.abs(combo.location.distanceSquared(loc)) <= radius * radius) {
combo.remove();
removed = true;
@@ -227,7 +213,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
}
}
}
-
+
if (!bPlayer.canBendIgnoreBindsCooldowns(this)) {
remove();
return;
@@ -239,7 +225,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
remove();
return;
}
-
+
bPlayer.addCooldown("FireKick", cooldown);
Vector eyeDir = player.getEyeLocation().getDirection().normalize().multiply(range);
destination = player.getEyeLocation().add(eyeDir);
@@ -262,17 +248,10 @@ public class FireCombo extends FireAbility implements ComboAbility {
player.getWorld().playSound(player.getLocation(), Sound.ITEM_FLINTANDSTEEL_USE, 0.5f, 1f);
}
location = tasks.get(0).getLocation();
- for (FireComboStream stream : tasks) {
- if (GeneralMethods.blockAbilities(player, BLOCKABLE_ABILITIES, stream.location, 2)) {
- stream.remove();
- }
- }
} else if (tasks.size() == 0) {
remove();
return;
- } AirAbility.removeAirSpouts(location, player);
- WaterAbility.removeWaterSpouts(location, player);
- EarthAbility.removeSandSpouts(location, player);
+ }
} else if (ability.equalsIgnoreCase("FireSpin")) {
if (destination == null) {
if (bPlayer.isOnCooldown("FireSpin") && !bPlayer.isAvatarState()) {
@@ -299,20 +278,11 @@ public class FireCombo extends FireAbility implements ComboAbility {
tasks.add(fs);
}
}
-
+
if (tasks.size() == 0) {
remove();
return;
}
-
- for (FireComboStream stream : tasks) {
- if (isWithinFireShield(stream.getLocation())) {
- stream.remove();
- }
- if (AirAbility.isWithinAirShield(stream.getLocation())) {
- stream.remove();
- }
- }
} else if (ability.equalsIgnoreCase("JetBlast")) {
if (System.currentTimeMillis() - time > 5000) {
remove();
@@ -323,7 +293,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
remove();
return;
}
-
+
bPlayer.addCooldown("JetBlast", cooldown);
firstTime = false;
float spread = 0F;
@@ -332,9 +302,8 @@ public class FireCombo extends FireAbility implements ComboAbility {
}
FireJet fj = getAbility(player, FireJet.class);
fj.setSpeed(speed);
- FireComboStream fs = new FireComboStream(this,
- player.getVelocity().clone().multiply(-1), player.getLocation(), 3, 0.5, "JetBlast");
-
+ FireComboStream fs = new FireComboStream(this, player.getVelocity().clone().multiply(-1), player.getLocation(), 3, 0.5, "JetBlast");
+
fs.setDensity(1);
fs.setSpread(0.9F);
fs.setUseNewParticles(true);
@@ -404,7 +373,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
}
location.setY(topBlock.getY() + height);
FireComboStream fs = new FireComboStream(this, direction, location.clone().add(0, -1, 0), 5, 1, "FireWheel");
-
+
fs.setDensity(0);
fs.setSinglePoint(true);
fs.setCollisionRadius(1.5);
@@ -422,16 +391,12 @@ public class FireCombo extends FireAbility implements ComboAbility {
location = location.add(direction.clone().multiply(speed));
location.getWorld().playSound(location, Sound.BLOCK_FIRE_AMBIENT, 1, 1);
- if (GeneralMethods.blockAbilities(player, BLOCKABLE_ABILITIES, location, 2)) {
- remove();
- return;
- }
}
}
/**
- * Removes this instance of FireCombo, cleans up any blocks that are remaining in totalBlocks,
- * and cancels any remaining tasks.
+ * Removes this instance of FireCombo, cleans up any blocks that are
+ * remaining in totalBlocks, and cancels any remaining tasks.
*/
@Override
public void remove() {
@@ -470,7 +435,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
this.checkCollisionCounter = 0;
this.spread = 0;
this.collisionRadius = 2;
- this.particleEffect = ParticleEffect.FLAME;
+ this.particleEffect = ParticleEffect.FLAME;
this.fireCombo = fireCombo;
this.direction = direction;
this.speed = speed;
@@ -479,7 +444,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
this.distance = distance;
this.ability = ability;
}
-
+
@Override
public void run() {
Block block = location.getBlock();
@@ -506,7 +471,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
}
}
}
-
+
checkCollisionCounter++;
if (singlePoint) {
remove();
@@ -586,7 +551,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -596,7 +561,22 @@ public class FireCombo extends FireAbility implements ComboAbility {
public boolean isHarmlessAbility() {
return false;
}
-
+
+ @Override
+ public boolean isCollidable() {
+ // Override in subclasses
+ return false;
+ }
+
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (FireComboStream stream : tasks) {
+ locations.add(stream.getLocation());
+ }
+ return locations;
+ }
+
@Override
public String getInstructions() {
return null;
@@ -611,7 +591,25 @@ public class FireCombo extends FireAbility implements ComboAbility {
public ArrayList getCombination() {
return null;
}
-
+
+ public void handleCollisionFireStreams(Collision collision) {
+ if (collision.isRemovingFirst()) {
+ ArrayList newTasks = new ArrayList<>();
+ double collisionDistanceSquared = Math.pow(getCollisionRadius() + collision.getAbilitySecond().getCollisionRadius(), 2);
+ // Remove all of the streams that are by this specific ourLocation.
+ // Don't just do a single stream at a time or this algorithm becomes O(n^2) with
+ // Collision's detection algorithm.
+ for (FireComboStream stream : tasks) {
+ if (stream.getLocation().distanceSquared(collision.getLocationSecond()) > collisionDistanceSquared) {
+ newTasks.add(stream);
+ } else {
+ stream.cancel();
+ }
+ }
+ tasks = newTasks;
+ }
+ }
+
public boolean isHiddenAbility() {
return true;
}
@@ -736,10 +734,6 @@ public class FireCombo extends FireAbility implements ComboAbility {
this.direction = direction;
}
- public static ArrayList getBlockableAbilities() {
- return BLOCKABLE_ABILITIES;
- }
-
public ArrayList getAffectedEntities() {
return affectedEntities;
}
@@ -748,6 +742,10 @@ public class FireCombo extends FireAbility implements ComboAbility {
return tasks;
}
+ public void setTasks(ArrayList tasks) {
+ this.tasks = tasks;
+ }
+
public void setCooldown(long cooldown) {
this.cooldown = cooldown;
}
@@ -755,65 +753,91 @@ public class FireCombo extends FireAbility implements ComboAbility {
public void setLocation(Location location) {
this.location = location;
}
-
- public class FireKick extends FireCombo {
- public FireKick(Player player, String name) {
+ // Combo subclasses need to be static to be reflectively called in ComboManager
+ public static class FireKick extends FireCombo {
+
+ public FireKick(Player player) {
super(player, "FireKick");
}
-
+
@Override
public String getName() {
return "FireKick";
}
-
- }
-
- public class FireSpin extends FireCombo {
- public FireSpin(Player player, String name) {
+ @Override
+ public boolean isCollidable() {
+ return true;
+ }
+
+ @Override
+ public void handleCollision(Collision collision) {
+ handleCollisionFireStreams(collision);
+ }
+
+ }
+
+ public static class FireSpin extends FireCombo {
+
+ public FireSpin(Player player) {
super(player, "FireSpin");
}
-
+
@Override
public String getName() {
return "FireSpin";
}
-
- }
-
- public class FireWheel extends FireCombo {
- public FireWheel(Player player, String name) {
+ @Override
+ public boolean isCollidable() {
+ return true;
+ }
+
+ @Override
+ public void handleCollision(Collision collision) {
+ handleCollisionFireStreams(collision);
+ }
+
+ }
+
+ public static class FireWheel extends FireCombo {
+
+ public FireWheel(Player player) {
super(player, "FireWheel");
}
-
+
@Override
public String getName() {
return "FireWheel";
}
-
- }
-
- public class JetBlast extends FireCombo {
- public JetBlast(Player player, String name) {
+ @Override
+ public boolean isCollidable() {
+ return true;
+ }
+
+ }
+
+ public static class JetBlast extends FireCombo {
+
+ public JetBlast(Player player) {
super(player, "JetBlast");
}
-
+
@Override
public String getName() {
return "JetBlast";
}
-
- }
-
- public class JetBlaze extends FireCombo {
- public JetBlaze(Player player, String name) {
+ }
+
+ public static class JetBlaze extends FireCombo {
+
+ public JetBlaze(Player player) {
super(player, "JetBlaze");
}
-
+
@Override
public String getName() {
return "JetBlaze";
diff --git a/src/com/projectkorra/projectkorra/firebending/FireShield.java b/src/com/projectkorra/projectkorra/firebending/FireShield.java
index c92c0df9..6b2018f2 100644
--- a/src/com/projectkorra/projectkorra/firebending/FireShield.java
+++ b/src/com/projectkorra/projectkorra/firebending/FireShield.java
@@ -1,10 +1,7 @@
package com.projectkorra.projectkorra.firebending;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ability.FireAbility;
-import com.projectkorra.projectkorra.earthbending.EarthBlast;
-import com.projectkorra.projectkorra.util.ParticleEffect;
-import com.projectkorra.projectkorra.waterbending.WaterManipulation;
+import java.util.ArrayList;
+import java.util.Random;
import org.bukkit.Effect;
import org.bukkit.Location;
@@ -16,11 +13,13 @@ import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.util.Vector;
-import java.util.ArrayList;
-import java.util.Random;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.FireAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
+import com.projectkorra.projectkorra.util.ParticleEffect;
public class FireShield extends FireAbility {
-
+
private boolean shield;
private boolean ignite;
private long time;
@@ -30,6 +29,7 @@ public class FireShield extends FireAbility {
private double radius;
private double discRadius;
private double fireTicks;
+ private Location location;
private Random random;
public FireShield(Player player) {
@@ -38,7 +38,7 @@ public class FireShield extends FireAbility {
public FireShield(Player player, boolean shield) {
super(player);
-
+
this.shield = shield;
this.ignite = true;
this.interval = getConfig().getLong("Abilities.Fire.FireShield.Interval");
@@ -48,7 +48,7 @@ public class FireShield extends FireAbility {
this.discRadius = getConfig().getDouble("Abilities.Fire.FireShield.DiscRadius");
this.fireTicks = getConfig().getDouble("Abilities.Fire.FireShield.FireTicks");
this.random = new Random();
-
+
if (hasAbility(player, FireShield.class) || bPlayer.isOnCooldown("FireShield")) {
return;
} else if (!player.getEyeLocation().getBlock().isLiquid()) {
@@ -60,6 +60,11 @@ public class FireShield extends FireAbility {
}
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean isWithinShield(Location loc) {
for (FireShield fshield : getAbilities(FireShield.class)) {
Location playerLoc = fshield.player.getLocation();
@@ -74,7 +79,8 @@ public class FireShield extends FireAbility {
Location tempLoc = playerLoc.clone().add(playerLoc.multiply(fshield.discRadius));
if (!tempLoc.getWorld().equals(loc.getWorld())) {
return false;
- } else if (tempLoc.getWorld().equals(loc.getWorld()) && tempLoc.distance(loc) <= fshield.discRadius * fshield.discRadius) {
+ } else if (tempLoc.getWorld().equals(loc.getWorld())
+ && tempLoc.distance(loc) <= fshield.discRadius * fshield.discRadius) {
return true;
}
}
@@ -90,7 +96,7 @@ public class FireShield extends FireAbility {
} else if (!player.isSneaking() && shield) {
remove();
return;
- } else if (System.currentTimeMillis() > startTime + duration && !shield) {
+ } else if (System.currentTimeMillis() > getStartTime() + duration && !shield) {
remove();
return;
}
@@ -100,15 +106,15 @@ public class FireShield extends FireAbility {
if (shield) {
ArrayList blocks = new ArrayList<>();
- Location location = player.getEyeLocation().clone();
+ location = player.getEyeLocation().clone();
for (double theta = 0; theta < 180; theta += 20) {
for (double phi = 0; phi < 360; phi += 20) {
double rphi = Math.toRadians(phi);
double rtheta = Math.toRadians(theta);
-
- Block block = location .clone() .add(radius * Math.cos(rphi) * Math.sin(rtheta), radius * Math.cos(rtheta),
- radius * Math.sin(rphi) * Math.sin(rtheta)).getBlock();
+
+ Block block = location.clone().add(radius * Math.cos(rphi) * Math.sin(rtheta), radius * Math.cos(rtheta),
+ radius * Math.sin(rphi) * Math.sin(rtheta)).getBlock();
if (!blocks.contains(block) && !GeneralMethods.isSolid(block) && !block.isLiquid()) {
blocks.add(block);
}
@@ -142,13 +148,9 @@ public class FireShield extends FireAbility {
new FireDamageTimer(entity, player);
}
}
-
- FireBlast.removeFireBlastsAroundPoint(location, radius + 1);
- BlazeArc.removeAroundPoint(location, radius + 1);
- Combustion.removeAroundPoint(location, radius + 1);
} else {
ArrayList blocks = new ArrayList<>();
- Location location = player.getEyeLocation().clone();
+ location = player.getEyeLocation().clone();
Vector direction = location.getDirection();
location = location.clone().add(direction.multiply(radius));
@@ -184,11 +186,6 @@ public class FireShield extends FireAbility {
}
}
- FireBlast.removeFireBlastsAroundPoint(location, discRadius);
- WaterManipulation.removeAroundPoint(location, discRadius);
- EarthBlast.removeAroundPoint(location, discRadius);
- BlazeArc.removeAroundPoint(location, discRadius);
- Combustion.removeAroundPoint(location, discRadius);
for (Entity entity : GeneralMethods.getEntitiesAroundPoint(location, discRadius)) {
if (entity instanceof Projectile) {
entity.remove();
@@ -205,14 +202,14 @@ public class FireShield extends FireAbility {
@Override
public Location getLocation() {
- return player != null ? player.getLocation() : null;
+ return location;
}
@Override
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -222,6 +219,11 @@ public class FireShield extends FireAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public double getCollisionRadius() {
+ return shield ? radius : discRadius;
+ }
public boolean isShield() {
return shield;
@@ -290,5 +292,5 @@ public class FireShield extends FireAbility {
public void setCooldown(long cooldown) {
this.cooldown = cooldown;
}
-
+
}
diff --git a/src/com/projectkorra/projectkorra/firebending/Lightning.java b/src/com/projectkorra/projectkorra/firebending/Lightning.java
index 4412ae6d..dcdf3154 100644
--- a/src/com/projectkorra/projectkorra/firebending/Lightning.java
+++ b/src/com/projectkorra/projectkorra/firebending/Lightning.java
@@ -1,10 +1,7 @@
package com.projectkorra.projectkorra.firebending;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ProjectKorra;
-import com.projectkorra.projectkorra.ability.LightningAbility;
-import com.projectkorra.projectkorra.avatar.AvatarState;
-import com.projectkorra.projectkorra.util.DamageHandler;
+import java.util.ArrayList;
+import java.util.List;
import org.bukkit.Location;
import org.bukkit.Sound;
@@ -15,7 +12,11 @@ import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
-import java.util.ArrayList;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ProjectKorra;
+import com.projectkorra.projectkorra.ability.LightningAbility;
+import com.projectkorra.projectkorra.avatar.AvatarState;
+import com.projectkorra.projectkorra.util.DamageHandler;
public class Lightning extends LightningAbility {
@@ -52,6 +53,7 @@ public class Lightning extends LightningAbility {
private ArrayList affectedEntities;
private ArrayList arcs;
private ArrayList tasks;
+ private ArrayList locations;
public Lightning(Player player) {
super(player);
@@ -73,6 +75,7 @@ public class Lightning extends LightningAbility {
this.affectedEntities = new ArrayList<>();
this.arcs = new ArrayList<>();
this.tasks = new ArrayList<>();
+ this.locations = new ArrayList<>();
this.selfHitWater = getConfig().getBoolean("Abilities.Fire.Lightning.SelfHitWater");
this.selfHitClose = getConfig().getBoolean("Abilities.Fire.Lightning.SelfHitClose");
@@ -191,6 +194,8 @@ public class Lightning extends LightningAbility {
return;
}
+ locations.clear();
+
if (state == State.START) {
if (bPlayer.isOnCooldown(this)) {
remove();
@@ -504,6 +509,11 @@ public class Lightning extends LightningAbility {
return;
}
Block block = location.getBlock();
+ // We only want to consider this particle as part of the location
+ // on the its first tick, when it actually does the electrocution.
+ // The later ticks are just for visual purposes.
+ locations.add(block.getLocation());
+
// Handle Water electrocution
if (!hitWater && (isWater(block) || (arcOnIce && isIce(block)))) {
hitWater = true;
@@ -636,6 +646,16 @@ public class Lightning extends LightningAbility {
return false;
}
+ @Override
+ public boolean isCollidable() {
+ return arcs.size() > 0;
+ }
+
+ @Override
+ public List getLocations() {
+ return locations;
+ }
+
public boolean isCharged() {
return charged;
}
diff --git a/src/com/projectkorra/projectkorra/firebending/WallOfFire.java b/src/com/projectkorra/projectkorra/firebending/WallOfFire.java
index 3a3f0e6f..95ff386d 100644
--- a/src/com/projectkorra/projectkorra/firebending/WallOfFire.java
+++ b/src/com/projectkorra/projectkorra/firebending/WallOfFire.java
@@ -173,22 +173,22 @@ public class WallOfFire extends FireAbility {
public void progress() {
time = System.currentTimeMillis();
- if (time - startTime > cooldown) {
+ if (time - getStartTime() > cooldown) {
remove();
return;
} else if (!active) {
return;
- } else if (time - startTime > duration) {
+ } else if (time - getStartTime() > duration) {
active = false;
return;
}
- if (time - startTime > intervalTick * interval) {
+ if (time - getStartTime() > intervalTick * interval) {
intervalTick++;
display();
}
- if (time - startTime > damageTick * damageInterval) {
+ if (time - getStartTime() > damageTick * damageInterval) {
damageTick++;
damage();
}
@@ -218,6 +218,15 @@ public class WallOfFire extends FireAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (Block block : blocks) {
+ locations.add(block.getLocation());
+ }
+ return locations;
+ }
public boolean isActive() {
return active;
diff --git a/src/com/projectkorra/projectkorra/waterbending/Bloodbending.java b/src/com/projectkorra/projectkorra/waterbending/Bloodbending.java
index ddf39f29..d70fb42f 100644
--- a/src/com/projectkorra/projectkorra/waterbending/Bloodbending.java
+++ b/src/com/projectkorra/projectkorra/waterbending/Bloodbending.java
@@ -283,7 +283,7 @@ public class Bloodbending extends BloodAbility {
@Override
public void remove() {
if (!bPlayer.isAvatarState() && target != null) {
- if (System.currentTimeMillis() < this.startTime + 1200) {
+ if (System.currentTimeMillis() < getStartTime() + 1200) {
bPlayer.addCooldown(this); //Prevents spamming
}
}
@@ -311,6 +311,9 @@ public class Bloodbending extends BloodAbility {
@Override
public Location getLocation() {
+ if (target != null) {
+ return target.getLocation();
+ }
return player != null ? player.getLocation() : null;
}
@@ -328,6 +331,16 @@ public class Bloodbending extends BloodAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public List getLocations() {
+ // for collision purposes we only care about the player's location
+ ArrayList locations = new ArrayList<>();
+ if (player != null) {
+ locations.add(player.getLocation());
+ }
+ return locations;
+ }
public boolean isCanOnlyBeUsedAtNight() {
return canOnlyBeUsedAtNight;
diff --git a/src/com/projectkorra/projectkorra/waterbending/HealingWaters.java b/src/com/projectkorra/projectkorra/waterbending/HealingWaters.java
index fbc053d2..b21a29a2 100644
--- a/src/com/projectkorra/projectkorra/waterbending/HealingWaters.java
+++ b/src/com/projectkorra/projectkorra/waterbending/HealingWaters.java
@@ -105,7 +105,7 @@ public class HealingWaters extends HealingAbility {
}
// If ability is is charged, set charged = true. If not, play charging particles.
- if (System.currentTimeMillis() >= startTime + chargeTime) {
+ if (System.currentTimeMillis() >= getStartTime() + chargeTime) {
if (!charged) {
this.charged = true;
WaterReturn.emptyWaterBottle(player);
diff --git a/src/com/projectkorra/projectkorra/waterbending/IceBlast.java b/src/com/projectkorra/projectkorra/waterbending/IceBlast.java
index 5960bd02..8a9f14c2 100644
--- a/src/com/projectkorra/projectkorra/waterbending/IceBlast.java
+++ b/src/com/projectkorra/projectkorra/waterbending/IceBlast.java
@@ -338,6 +338,16 @@ public class IceBlast extends IceAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public boolean isCollidable() {
+ return progressing;
+ }
+
+ @Override
+ public double getCollisionRadius() {
+ return collisionRadius;
+ }
public boolean isPrepared() {
return prepared;
@@ -403,10 +413,6 @@ public class IceBlast extends IceAbility {
this.damage = damage;
}
- public double getCollisionRadius() {
- return collisionRadius;
- }
-
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}
diff --git a/src/com/projectkorra/projectkorra/waterbending/IceSpikeBlast.java b/src/com/projectkorra/projectkorra/waterbending/IceSpikeBlast.java
index c68084e0..968650c0 100644
--- a/src/com/projectkorra/projectkorra/waterbending/IceSpikeBlast.java
+++ b/src/com/projectkorra/projectkorra/waterbending/IceSpikeBlast.java
@@ -45,11 +45,11 @@ public class IceSpikeBlast extends IceAbility {
public IceSpikeBlast(Player player) {
super(player);
-
+
if (bPlayer.isOnCooldown("IceSpikeBlast")) {
return;
}
-
+
this.data = 0;
this.interval = getConfig().getLong("Abilities.Water.IceSpike.Blast.Interval");
this.slowCooldown = getConfig().getLong("Abilities.Water.IceSpike.Blast.SlowCooldown");
@@ -60,12 +60,12 @@ public class IceSpikeBlast extends IceAbility {
this.cooldown = getConfig().getLong("Abilities.Water.IceSpike.Blast.Cooldown");
this.slowPower = getConfig().getInt("Abilities.Water.IceSpike.Blast.SlowPower");
this.slowDuration = getConfig().getInt("Abilities.Water.IceSpike.Blast.SlowDuration");
-
+
if (!bPlayer.canBend(this) || !bPlayer.canIcebend()) {
return;
}
- block(player);
+ block(player);
this.range = getNightFactor(range);
this.damage = getNightFactor(damage);
this.slowPower = (int) getNightFactor(slowPower);
@@ -109,7 +109,7 @@ public class IceSpikeBlast extends IceAbility {
iceSpike.remove();
}
}
-
+
sourceBlock = block;
location = sourceBlock.getLocation();
prepared = true;
@@ -232,7 +232,7 @@ public class IceSpikeBlast extends IceAbility {
if (!prepared) {
return;
}
-
+
LivingEntity target = (LivingEntity) GeneralMethods.getTargetedEntity(player, range);
if (target == null) {
destination = GeneralMethods.getTargetedLocation(player, range, getTransparentMaterial());
@@ -247,14 +247,14 @@ public class IceSpikeBlast extends IceAbility {
if (destination.distanceSquared(location) < 1) {
return;
}
-
+
firstDestination = location.clone();
if (destination.getY() - location.getY() > 2) {
firstDestination.setY(destination.getY() - 1);
} else {
firstDestination.add(0, 2, 0);
}
-
+
destination = GeneralMethods.getPointOnLine(firstDestination, destination, range);
progressing = true;
settingUp = true;
@@ -265,22 +265,21 @@ public class IceSpikeBlast extends IceAbility {
sourceBlock.setType(Material.AIR);
}
-
}
public static void activate(Player player) {
redirect(player);
boolean activate = false;
BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
-
+
if (bPlayer == null) {
return;
}
-
+
if (bPlayer.isOnCooldown("IceSpikeBlast")) {
return;
}
-
+
for (IceSpikeBlast ice : getAbilities(player, IceSpikeBlast.class)) {
if (ice.prepared) {
ice.throwIce();
@@ -288,7 +287,7 @@ public class IceSpikeBlast extends IceAbility {
activate = true;
}
}
-
+
if (!activate && !getPlayers(IceSpikeBlast.class).contains(player)) {
IceSpikePillar spike = new IceSpikePillar(player);
if (!spike.isStarted()) {
@@ -305,16 +304,15 @@ public class IceSpikeBlast extends IceAbility {
continue;
} else if (!iceSpike.progressing) {
continue;
- } if (GeneralMethods.isRegionProtectedFromBuild(iceSpike, iceSpike.location)) {
+ }
+ if (GeneralMethods.isRegionProtectedFromBuild(iceSpike, iceSpike.location)) {
continue;
}
Location location = player.getEyeLocation();
Vector vector = location.getDirection();
Location mloc = iceSpike.location;
- if (mloc.distanceSquared(location) <= iceSpike.range * iceSpike.range
- && GeneralMethods.getDistanceFromLine(vector, location, iceSpike.location) < iceSpike.deflectRange
- && mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
+ if (mloc.distanceSquared(location) <= iceSpike.range * iceSpike.range && GeneralMethods.getDistanceFromLine(vector, location, iceSpike.location) < iceSpike.deflectRange && mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
iceSpike.remove();
}
}
@@ -343,12 +341,10 @@ public class IceSpikeBlast extends IceAbility {
Location location = player.getEyeLocation();
Vector vector = location.getDirection();
Location mloc = iceSpike.location;
-
+
if (GeneralMethods.isRegionProtectedFromBuild(iceSpike, mloc)) {
continue;
- } else if (mloc.distanceSquared(location) <= iceSpike.range * iceSpike.range
- && GeneralMethods.getDistanceFromLine(vector, location, iceSpike.location) < iceSpike.deflectRange
- && mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
+ } else if (mloc.distanceSquared(location) <= iceSpike.range * iceSpike.range && GeneralMethods.getDistanceFromLine(vector, location, iceSpike.location) < iceSpike.deflectRange && mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
Location loc;
Entity target = GeneralMethods.getTargetedEntity(player, iceSpike.range);
if (target == null) {
@@ -366,15 +362,15 @@ public class IceSpikeBlast extends IceAbility {
@SuppressWarnings("deprecation")
private static void waterBottle(Player player) {
long range = getConfig().getLong("Abilities.Water.IceSpike.Projectile.Range");
-
+
if (WaterReturn.hasWaterBottle(player)) {
Location eyeLoc = player.getEyeLocation();
Block block = eyeLoc.add(eyeLoc.getDirection().normalize()).getBlock();
-
+
if (isTransparent(player, block) && isTransparent(player, eyeLoc.getBlock())) {
LivingEntity target = (LivingEntity) GeneralMethods.getTargetedEntity(player, range);
Location destination;
-
+
if (target == null) {
destination = GeneralMethods.getTargetedLocation(player, range, getTransparentMaterial());
} else {
@@ -387,17 +383,17 @@ public class IceSpikeBlast extends IceAbility {
MaterialData data = block.getState().getData();
block.setType(Material.WATER);
- block.setData((byte)0);
+ block.setData((byte) 0);
IceSpikeBlast iceSpike = new IceSpikeBlast(player);
iceSpike.throwIce();
iceSpike.sourceBlock = null;
if (iceSpike.progressing) {
WaterReturn.emptyWaterBottle(player);
- }
+ }
block.setType(data.getItemType());
block.setData(data.getData());
-
+
}
}
}
@@ -421,7 +417,7 @@ public class IceSpikeBlast extends IceAbility {
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -432,6 +428,16 @@ public class IceSpikeBlast extends IceAbility {
return false;
}
+ @Override
+ public boolean isCollidable() {
+ return progressing;
+ }
+
+ @Override
+ public double getCollisionRadius() {
+ return collisionRadius;
+ }
+
public boolean isPrepared() {
return prepared;
}
@@ -520,10 +526,6 @@ public class IceSpikeBlast extends IceAbility {
this.damage = damage;
}
- public double getCollisionRadius() {
- return collisionRadius;
- }
-
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}
@@ -575,5 +577,5 @@ public class IceSpikeBlast extends IceAbility {
public void setLocation(Location location) {
this.location = location;
}
-
+
}
diff --git a/src/com/projectkorra/projectkorra/waterbending/OctopusForm.java b/src/com/projectkorra/projectkorra/waterbending/OctopusForm.java
index 8e48d019..e6f9ffd2 100644
--- a/src/com/projectkorra/projectkorra/waterbending/OctopusForm.java
+++ b/src/com/projectkorra/projectkorra/waterbending/OctopusForm.java
@@ -475,6 +475,11 @@ public class OctopusForm extends WaterAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public double getCollisionRadius() {
+ return getRadius();
+ }
public boolean isSourceSelected() {
return sourceSelected;
diff --git a/src/com/projectkorra/projectkorra/waterbending/PlantArmor.java b/src/com/projectkorra/projectkorra/waterbending/PlantArmor.java
index f3dfa534..c7208549 100644
--- a/src/com/projectkorra/projectkorra/waterbending/PlantArmor.java
+++ b/src/com/projectkorra/projectkorra/waterbending/PlantArmor.java
@@ -23,6 +23,7 @@ public class PlantArmor extends PlantAbility {
private int resistance;
private long duration;
private long cooldown;
+ private long tickTime;
private double range;
private Material blockType;
private Block block;
@@ -39,6 +40,7 @@ public class PlantArmor extends PlantAbility {
this.range = getNightFactor(range);
this.duration = (long) getNightFactor(duration);
+ this.tickTime = System.currentTimeMillis();
if (hasAbility(player, PlantArmor.class)) {
return;
@@ -97,7 +99,7 @@ public class PlantArmor extends PlantAbility {
new TempArmor(player, this, new ItemStack[] {boots, leggings, chestplate, helmet});
formed = true;
- startTime = System.currentTimeMillis();
+ tickTime = System.currentTimeMillis();
}
private boolean inPosition() {
@@ -125,7 +127,7 @@ public class PlantArmor extends PlantAbility {
if (formed) {
PassiveHandler.checkArmorPassives(player);
- if (System.currentTimeMillis() > startTime + duration) {
+ if (System.currentTimeMillis() > tickTime + duration) {
remove();
bPlayer.addCooldown(this);
return;
@@ -166,7 +168,7 @@ public class PlantArmor extends PlantAbility {
public static boolean canRemoveArmor(Player player) {
PlantArmor plantArmor = getAbility(player, PlantArmor.class);
if (plantArmor != null) {
- if (System.currentTimeMillis() < plantArmor.startTime + plantArmor.duration) {
+ if (System.currentTimeMillis() < plantArmor.tickTime + plantArmor.duration) {
return false;
}
}
@@ -188,10 +190,8 @@ public class PlantArmor extends PlantAbility {
@Override
public Location getLocation() {
- if (location != null) {
+ if (!formed) {
return location;
- } else if (block != null) {
- return block.getLocation();
}
return player != null ? player.getLocation() : null;
}
diff --git a/src/com/projectkorra/projectkorra/waterbending/SurgeWall.java b/src/com/projectkorra/projectkorra/waterbending/SurgeWall.java
index dec17863..dfe42bb0 100644
--- a/src/com/projectkorra/projectkorra/waterbending/SurgeWall.java
+++ b/src/com/projectkorra/projectkorra/waterbending/SurgeWall.java
@@ -1,5 +1,19 @@
package com.projectkorra.projectkorra.waterbending;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.bukkit.Effect;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
import com.projectkorra.projectkorra.BendingPlayer;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.WaterAbility;
@@ -9,19 +23,6 @@ import com.projectkorra.projectkorra.util.BlockSource;
import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.TempBlock;
-import org.bukkit.Effect;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.block.Block;
-import org.bukkit.entity.Player;
-import org.bukkit.util.Vector;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.ConcurrentHashMap;
-
public class SurgeWall extends WaterAbility {
private static final byte FULL = 0x0;
@@ -42,6 +43,7 @@ public class SurgeWall extends WaterAbility {
private Location location;
private Location firstDestination;
private Location targetDestination;
+ private ArrayList locations;
private Vector firstDirection;
private Vector targetDirection;
@@ -53,6 +55,7 @@ public class SurgeWall extends WaterAbility {
this.cooldown = getConfig().getLong("Abilities.Water.Surge.Wall.Cooldown");
this.range = getConfig().getDouble(RANGE_CONFIG);
this.radius = getConfig().getDouble("Abilities.Water.Surge.Wall.Radius");
+ this.locations = new ArrayList<>();
SurgeWave wave = getAbility(player, SurgeWave.class);
if (wave != null && !wave.isProgressing()) {
@@ -214,7 +217,8 @@ public class SurgeWall extends WaterAbility {
remove();
return;
}
-
+ locations.clear();
+
if (System.currentTimeMillis() - time >= interval) {
time = System.currentTimeMillis();
boolean matchesName = bPlayer.getBoundAbilityName().equalsIgnoreCase(getName());
@@ -258,6 +262,7 @@ public class SurgeWall extends WaterAbility {
WALL_BLOCKS.put(block, player);
addWallBlock(block);
blocks.add(block);
+ locations.add(block.getLocation());
FireBlast.removeFireBlastsAroundPoint(block.getLocation(), 2);
}
}
@@ -483,6 +488,11 @@ public class SurgeWall extends WaterAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public List getLocations() {
+ return locations;
+ }
public boolean isProgressing() {
return progressing;
diff --git a/src/com/projectkorra/projectkorra/waterbending/SurgeWave.java b/src/com/projectkorra/projectkorra/waterbending/SurgeWave.java
index 6004738b..b4931c5b 100644
--- a/src/com/projectkorra/projectkorra/waterbending/SurgeWave.java
+++ b/src/com/projectkorra/projectkorra/waterbending/SurgeWave.java
@@ -1,13 +1,10 @@
package com.projectkorra.projectkorra.waterbending;
-import com.projectkorra.projectkorra.GeneralMethods;
-import com.projectkorra.projectkorra.ability.AirAbility;
-import com.projectkorra.projectkorra.ability.WaterAbility;
-import com.projectkorra.projectkorra.avatar.AvatarState;
-import com.projectkorra.projectkorra.firebending.FireBlast;
-import com.projectkorra.projectkorra.util.BlockSource;
-import com.projectkorra.projectkorra.util.ClickType;
-import com.projectkorra.projectkorra.util.TempBlock;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Effect;
import org.bukkit.Location;
@@ -18,10 +15,14 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.Random;
-import java.util.concurrent.ConcurrentHashMap;
+import com.projectkorra.projectkorra.GeneralMethods;
+import com.projectkorra.projectkorra.ability.AirAbility;
+import com.projectkorra.projectkorra.ability.WaterAbility;
+import com.projectkorra.projectkorra.avatar.AvatarState;
+import com.projectkorra.projectkorra.firebending.FireBlast;
+import com.projectkorra.projectkorra.util.BlockSource;
+import com.projectkorra.projectkorra.util.ClickType;
+import com.projectkorra.projectkorra.util.TempBlock;
public class SurgeWave extends WaterAbility {
@@ -439,6 +440,23 @@ public class SurgeWave extends WaterAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public boolean isCollidable() {
+ return progressing || activateFreeze;
+ }
+
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (Block block : waveBlocks.keySet()) {
+ locations.add(block.getLocation());
+ }
+ for (Block block : frozenBlocks.keySet()) {
+ locations.add(block.getLocation());
+ }
+ return locations;
+ }
public boolean isFreezing() {
return freezing;
diff --git a/src/com/projectkorra/projectkorra/waterbending/Torrent.java b/src/com/projectkorra/projectkorra/waterbending/Torrent.java
index 935a6a87..bb753126 100644
--- a/src/com/projectkorra/projectkorra/waterbending/Torrent.java
+++ b/src/com/projectkorra/projectkorra/waterbending/Torrent.java
@@ -655,6 +655,23 @@ public class Torrent extends WaterAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public boolean isCollidable() {
+ return forming || formed || launch || launching;
+ }
+
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (TempBlock tblock : blocks) {
+ locations.add(tblock.getLocation());
+ }
+ for (TempBlock tblock : launchedBlocks) {
+ locations.add(tblock.getLocation());
+ }
+ return locations;
+ }
public boolean isSourceSelected() {
return sourceSelected;
diff --git a/src/com/projectkorra/projectkorra/waterbending/TorrentWave.java b/src/com/projectkorra/projectkorra/waterbending/TorrentWave.java
index 58c199db..9e3c34ae 100644
--- a/src/com/projectkorra/projectkorra/waterbending/TorrentWave.java
+++ b/src/com/projectkorra/projectkorra/waterbending/TorrentWave.java
@@ -12,6 +12,7 @@ import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
@@ -216,6 +217,15 @@ public class TorrentWave extends WaterAbility {
return false;
}
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (TempBlock tblock : blocks) {
+ locations.add(tblock.getLocation());
+ }
+ return locations;
+ }
+
public long getTime() {
return time;
}
diff --git a/src/com/projectkorra/projectkorra/waterbending/WaterCombo.java b/src/com/projectkorra/projectkorra/waterbending/WaterCombo.java
index 9d0a54db..2db8490c 100644
--- a/src/com/projectkorra/projectkorra/waterbending/WaterCombo.java
+++ b/src/com/projectkorra/projectkorra/waterbending/WaterCombo.java
@@ -1,7 +1,9 @@
package com.projectkorra.projectkorra.waterbending;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Enumeration;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -17,10 +19,11 @@ import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.ComboAbility;
+import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.IceAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation;
import com.projectkorra.projectkorra.avatar.AvatarState;
-import com.projectkorra.projectkorra.firebending.FireCombo;
import com.projectkorra.projectkorra.firebending.FireCombo.FireComboStream;
import com.projectkorra.projectkorra.util.BlockSource;
import com.projectkorra.projectkorra.util.ClickType;
@@ -29,9 +32,9 @@ import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
/*
- * TODO: Combo classes should eventually be rewritten so that each combo is treated
- * as an individual ability. In the mean time, we will just place "fake"
- * classes so that CoreAbility will register each ability.
+ * TODO: Combo classes should eventually be rewritten so that each combo is
+ * treated as an individual ability. In the mean time, we will just place "fake"
+ * classes so that CoreAbility will register each ability.
*/
public class WaterCombo extends IceAbility implements ComboAbility {
@@ -76,12 +79,11 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
if (name.equalsIgnoreCase("IceWave")) {
-
if (bPlayer.isOnCooldown("IceWave") && !bPlayer.isAvatarState()) {
remove();
return;
}
-
+
this.cooldown = getConfig().getLong("Abilities.Water.WaterCombo.IceWave.Cooldown");
} else if (name.equalsIgnoreCase("IceBullet")) {
this.damage = getConfig().getDouble("Abilities.Water.WaterCombo.IceBullet.Damage");
@@ -93,7 +95,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
this.animationSpeed = getConfig().getDouble("Abilities.Water.WaterCombo.IceBullet.AnimationSpeed");
this.speed = 1;
}
-
+
double aug = getNightFactor(player.getWorld());
if (aug > 1) {
aug = 1 + (aug - 1) / 3;
@@ -115,7 +117,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
if (name.equalsIgnoreCase("IceBulletLeftClick") || name.equalsIgnoreCase("IceBulletRightClick")) {
- ArrayList bullets = getWaterCombo(player, "IceBullet");
+ Collection bullets = CoreAbility.getAbilities(player, IceBullet.class);
if (bullets.size() == 0) {
return;
}
@@ -130,7 +132,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
return;
}
-
+
start();
}
@@ -149,13 +151,13 @@ public class WaterCombo extends IceAbility implements ComboAbility {
public void drawWaterCircle(Location loc, double theta, double increment, double radius, Material mat, byte data) {
double rotateSpeed = theta;
direction = GeneralMethods.rotateXZ(direction, rotateSpeed);
-
+
for (double i = 0; i < theta; i += increment) {
Vector dir = GeneralMethods.rotateXZ(direction, i - theta / 2).normalize().multiply(radius);
dir.setY(0);
Block block = loc.clone().add(dir).getBlock();
location = block.getLocation();
-
+
if (block.getType() == Material.AIR && !GeneralMethods.isRegionProtectedFromBuild(player, "WaterManipulation", block.getLocation())) {
createBlock(block, mat, data);
}
@@ -169,7 +171,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
i--;
}
}
-
+
for (int i = 0; i < tasks.size(); i++) {
FireComboStream fstream = (FireComboStream) tasks.get(i);
Location loc = fstream.getLocation();
@@ -197,10 +199,6 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
}
}
-
- if (GeneralMethods.blockAbilities(player, FireCombo.getBlockableAbilities(), loc, 1)) {
- fstream.remove();
- }
}
}
}
@@ -214,7 +212,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
if (origin == null && WaterSpoutWave.containsType(player, WaterSpoutWave.AbilityType.RELEASE)) {
bPlayer.addCooldown("IceWave", cooldown);
origin = player.getLocation();
-
+
WaterSpoutWave wave = WaterSpoutWave.getType(player, WaterSpoutWave.AbilityType.RELEASE).get(0);
wave.setIceWave(true);
} else if (!WaterSpoutWave.containsType(player, WaterSpoutWave.AbilityType.RELEASE)) {
@@ -226,19 +224,19 @@ public class WaterCombo extends IceAbility implements ComboAbility {
remove();
return;
}
-
+
if (origin == null) {
if (bPlayer.isOnCooldown("IceBullet") && !bPlayer.isAvatarState()) {
remove();
return;
}
-
+
Block waterBlock = BlockSource.getWaterSourceBlock(player, range, ClickType.LEFT_CLICK, true, true, bPlayer.canPlantbend());
if (waterBlock == null) {
remove();
return;
}
-
+
time = 0;
origin = waterBlock.getLocation();
location = origin.clone();
@@ -253,7 +251,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
if (this.time == 0) {
this.time = System.currentTimeMillis();
}
-
+
long timeDiff = System.currentTimeMillis() - this.time;
if (this.state == AbilityState.ICE_BULLET_FORMING) {
if (timeDiff < 1000 * animationSpeed) {
@@ -277,7 +275,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
Vector vec = player.getEyeLocation().getDirection().normalize();
Location loc = player.getEyeLocation().add(vec.clone().multiply(radius + 1.3));
FireComboStream fs = new FireComboStream(null, vec, loc, range, speed, "IceBullet");
-
+
fs.setDensity(10);
fs.setSpread(0.1F);
fs.setUseNewParticles(true);
@@ -308,9 +306,9 @@ public class WaterCombo extends IceAbility implements ComboAbility {
if (waterGrabber != null) {
waterGrabber.remove();
}
-
+
bPlayer.addCooldown(this);
-
+
if (name == "IceWave") {
bPlayer.addCooldown("WaterWave", getConfig().getLong("Abilities.Water.WaterSpout.Wave.Cooldown"));
}
@@ -363,12 +361,12 @@ public class WaterCombo extends IceAbility implements ComboAbility {
public long getCooldown() {
return cooldown;
}
-
+
@Override
public boolean isHiddenAbility() {
return true;
}
-
+
@Override
public boolean isSneakAbility() {
return true;
@@ -378,7 +376,13 @@ public class WaterCombo extends IceAbility implements ComboAbility {
public boolean isHarmlessAbility() {
return false;
}
-
+
+ @Override
+ public boolean isCollidable() {
+ // Override in subclasses
+ return false;
+ }
+
@Override
public String getInstructions() {
return null;
@@ -526,6 +530,10 @@ public class WaterCombo extends IceAbility implements ComboAbility {
return tasks;
}
+ public void setTasks(ArrayList tasks) {
+ this.tasks = tasks;
+ }
+
public static Map getFrozenBlocks() {
return FROZEN_BLOCKS;
}
@@ -545,31 +553,99 @@ public class WaterCombo extends IceAbility implements ComboAbility {
public void setLocation(Location location) {
this.location = location;
}
-
- public class IceWave extends WaterCombo {
- public IceWave(Player player, String name) {
+ // Combo subclasses need to be static to be reflectively called in ComboManager
+ public static class IceWave extends WaterCombo {
+
+ public IceWave(Player player) {
super(player, "IceWave");
}
-
+
@Override
public String getName() {
return "IceWave";
}
-
- }
-
- public class IceBullet extends WaterCombo {
- public IceBullet(Player player, String name) {
+ }
+
+ public static class IceBullet extends WaterCombo {
+
+ public IceBullet(Player player) {
super(player, "IceBullet");
}
-
+
@Override
public String getName() {
return "IceBullet";
}
-
+
+ @Override
+ public boolean isCollidable() {
+ return true;
+ }
+
+ @Override
+ public void handleCollision(Collision collision) {
+ if (collision.isRemovingFirst()) {
+ ArrayList newTasks = new ArrayList<>();
+ double collisionDistanceSquared = Math.pow(getCollisionRadius() + collision.getAbilitySecond().getCollisionRadius(), 2);
+ // Remove all of the streams that are by this specific ourLocation.
+ // Don't just do a single stream at a time or this algorithm becomes O(n^2) with
+ // Collision's detection algorithm.
+ for (BukkitRunnable task : getTasks()) {
+ if (task instanceof FireComboStream) {
+ FireComboStream stream = (FireComboStream) task;
+ if (stream.getLocation().distanceSquared(collision.getLocationSecond()) > collisionDistanceSquared) {
+ newTasks.add(stream);
+ } else {
+ stream.cancel();
+ }
+ } else {
+ newTasks.add(task);
+ }
+ }
+ setTasks(newTasks);
+ }
+ }
+
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ for (BukkitRunnable task : getTasks()) {
+ if (task instanceof FireComboStream) {
+ FireComboStream stream = (FireComboStream) task;
+ locations.add(stream.getLocation());
+ }
+ }
+ return locations;
+ }
+
}
-
-}
\ No newline at end of file
+
+ public static class IceBulletLeftClick extends WaterCombo {
+
+ public IceBulletLeftClick(Player player) {
+ super(player, "IceBulletLeftClick");
+ }
+
+ @Override
+ public String getName() {
+ return "IceBullet";
+ }
+
+ }
+
+ public static class IceBulletRightClick extends WaterCombo {
+
+ public IceBulletRightClick(Player player) {
+ super(player, "IceBulletRightClick");
+ }
+
+ @Override
+ public String getName() {
+ return "IceBullet";
+ }
+
+ }
+
+}
diff --git a/src/com/projectkorra/projectkorra/waterbending/WaterManipulation.java b/src/com/projectkorra/projectkorra/waterbending/WaterManipulation.java
index 2f4872c8..7c78df81 100644
--- a/src/com/projectkorra/projectkorra/waterbending/WaterManipulation.java
+++ b/src/com/projectkorra/projectkorra/waterbending/WaterManipulation.java
@@ -18,12 +18,9 @@ import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.BendingPlayer;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.AirAbility;
-import com.projectkorra.projectkorra.ability.EarthAbility;
import com.projectkorra.projectkorra.ability.WaterAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.avatar.AvatarState;
-import com.projectkorra.projectkorra.earthbending.EarthBlast;
-import com.projectkorra.projectkorra.firebending.Combustion;
-import com.projectkorra.projectkorra.firebending.FireBlast;
import com.projectkorra.projectkorra.util.BlockSource;
import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.DamageHandler;
@@ -230,27 +227,9 @@ public class WaterManipulation extends WaterAbility {
}
}
} else {
- WaterAbility.removeWaterSpouts(location, player);
- AirAbility.removeAirSpouts(location, player);
- EarthAbility.removeSandSpouts(location, player);
-
if ((new Random()).nextInt(4) == 0) {
playWaterbendingSound(location);
}
-
- double radius = collisionRadius;
- Player source = player;
- if (!(location == null)) {
- if (EarthBlast.annihilateBlasts(location, radius, source)
- || WaterManipulation.annihilateBlasts(location, radius, source)
- || FireBlast.annihilateBlasts(location, radius, source)) {
- remove();
- new WaterReturn(player, sourceBlock);
- return;
- }
- Combustion.removeAroundPoint(location, radius);
- }
-
location = location.clone().add(direction);
block = location.getBlock();
if (block.getLocation().equals(sourceBlock.getLocation())) {
@@ -386,6 +365,11 @@ public class WaterManipulation extends WaterAbility {
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean annihilateBlasts(Location location, double radius, Player player) {
boolean broke = false;
for (WaterManipulation manip : getAbilities(WaterManipulation.class)) {
@@ -596,6 +580,24 @@ public class WaterManipulation extends WaterAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public boolean isCollidable() {
+ return progressing;
+ }
+
+ @Override
+ public double getCollisionRadius() {
+ return collisionRadius;
+ }
+
+ @Override
+ public void handleCollision(Collision collision) {
+ super.handleCollision(collision);
+ if (collision.isRemovingFirst()) {
+ new WaterReturn(player, sourceBlock);
+ }
+ }
public boolean isProgressing() {
return progressing;
@@ -781,10 +783,6 @@ public class WaterManipulation extends WaterAbility {
this.location = location;
}
- public double getCollisionRadius() {
- return collisionRadius;
- }
-
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}
diff --git a/src/com/projectkorra/projectkorra/waterbending/WaterSpout.java b/src/com/projectkorra/projectkorra/waterbending/WaterSpout.java
index b3318a5f..ef485c7f 100644
--- a/src/com/projectkorra/projectkorra/waterbending/WaterSpout.java
+++ b/src/com/projectkorra/projectkorra/waterbending/WaterSpout.java
@@ -14,6 +14,7 @@ import org.bukkit.potion.PotionEffectType;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.WaterAbility;
+import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.util.Flight;
import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
@@ -289,6 +290,11 @@ public class WaterSpout extends WaterAbility {
return -1;
}
+ /**
+ * This method was used for the old collision detection system. Please see
+ * {@link Collision} for the new system.
+ */
+ @Deprecated
public static boolean removeSpouts(Location loc0, double radius, Player sourcePlayer) {
boolean removed = false;
for (WaterSpout spout : getAbilities(WaterSpout.class)) {
@@ -332,6 +338,24 @@ public class WaterSpout extends WaterAbility {
public boolean isHarmlessAbility() {
return true;
}
+
+ @Override
+ public boolean isCollidable() {
+ return true;
+ }
+
+ @Override
+ public List getLocations() {
+ ArrayList locations = new ArrayList<>();
+ Location top = this.getLocation();
+ Location iterLoc = getBase().getLocation();
+ double ySpacing = 2;
+ while (iterLoc.getY() <= top.getY()) {
+ locations.add(iterLoc.clone());
+ iterLoc.add(0, ySpacing, 0);
+ }
+ return locations;
+ }
public boolean isCanBendOnPackedIce() {
return canBendOnPackedIce;
@@ -416,5 +440,5 @@ public class WaterSpout extends WaterAbility {
public static Map getAffectedBlocks() {
return AFFECTED_BLOCKS;
}
-
+
}
\ No newline at end of file
diff --git a/src/com/projectkorra/projectkorra/waterbending/WaterSpoutWave.java b/src/com/projectkorra/projectkorra/waterbending/WaterSpoutWave.java
index af7698c2..c19e50c3 100644
--- a/src/com/projectkorra/projectkorra/waterbending/WaterSpoutWave.java
+++ b/src/com/projectkorra/projectkorra/waterbending/WaterSpoutWave.java
@@ -42,6 +42,7 @@ public class WaterSpoutWave extends WaterAbility {
private boolean iceOnly;
private boolean moving;
private boolean plant;
+ private boolean collidable;
private int progressCounter;
private long time;
private long cooldown;
@@ -68,6 +69,7 @@ public class WaterSpoutWave extends WaterAbility {
this.charging = false;
this.iceWave = false;
this.iceOnly = false;
+ this.collidable = false;
this.plant = getConfig().getBoolean("Abilities.Water.WaterSpout.Wave.AllowPlantSource");
this.radius = getConfig().getDouble("Abilities.Water.WaterSpout.Wave.Radius");
this.waveRadius = getConfig().getDouble("Abilities.Water.WaterSpout.Wave.WaveRadius");
@@ -241,6 +243,7 @@ public class WaterSpoutWave extends WaterAbility {
}
} else {
moving = true;
+ collidable = true;
if ((System.currentTimeMillis() - time > flightTime && !bPlayer.isAvatarState()) || player.isSneaking()) {
remove();
return;
@@ -473,6 +476,16 @@ public class WaterSpoutWave extends WaterAbility {
public boolean isHarmlessAbility() {
return false;
}
+
+ @Override
+ public boolean isCollidable() {
+ return collidable;
+ }
+
+ @Override
+ public double getCollisionRadius() {
+ return getRadius();
+ }
public double getRadius() {
return radius;