Implemented new collision detection system (#636)

This commit is contained in:
Nathan Braun 2016-10-23 23:23:02 -07:00 committed by Christopher Martin
parent ca40454356
commit 5096d3d399
56 changed files with 2098 additions and 948 deletions

View file

@ -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.
* <p>
* 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<String> abilitiesToBlock, Location loc, double radius) {
boolean hasBlocked = false;
for (String ability : abilitiesToBlock) {

View file

@ -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();

View file

@ -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;
@ -35,6 +38,16 @@ public abstract class AirAbility extends ElementalAbility {
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.
* <p>
* 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<String> list = new ArrayList<String>();
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.
* <p>
* 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.
* <p>
* 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);
}

View file

@ -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}.
* <p>
* 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()
@ -54,32 +62,38 @@ public abstract class CoreAbility implements Ability {
private static final Map<Class<? extends CoreAbility>, Map<UUID, Map<Integer, CoreAbility>>> INSTANCES = new ConcurrentHashMap<>();
private static final Map<Class<? extends CoreAbility>, Set<CoreAbility>> INSTANCES_BY_CLASS = new ConcurrentHashMap<>();
private static final Map<String, CoreAbility> ABILITIES_BY_NAME = new ConcurrentSkipListMap<>();
private static final Map<String, CoreAbility> ABILITIES_BY_NAME = new ConcurrentSkipListMap<>(); // preserves ordering
private static final Map<Class<? extends CoreAbility>, 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.
@ -97,6 +111,7 @@ public abstract class CoreAbility implements Ability {
this.startTime = System.currentTimeMillis();
this.started = false;
this.id = CoreAbility.idCounter;
this.startTick = getCurrentTick();
if (idCounter == Integer.MAX_VALUE) {
idCounter = Integer.MIN_VALUE;
@ -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()
@ -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
* <b>super.remove()</b>.
* 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 <b>super.remove()</b>.
*
* {@inheritDoc}
*
* @see #isRemoved()
*/
@Override
@ -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<CoreAbility> setAbils : INSTANCES_BY_CLASS.values()) {
@ -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
@ -228,14 +246,16 @@ public abstract class CoreAbility implements Ability {
}
/**
* 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.
*
* <p>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.
* <p>
* 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.
*
* <p>
* CoreAbility coreAbil = getAbility(someString); <br>
@ -249,14 +269,26 @@ public abstract class CoreAbility implements Ability {
}
/**
* 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<CoreAbility> getAbilities() {
return new ArrayList<CoreAbility>(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
@ -285,7 +318,8 @@ public abstract class CoreAbility implements Ability {
}
/**
* 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
@ -318,7 +352,8 @@ public abstract class CoreAbility implements Ability {
}
/**
* 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
*/
@ -339,8 +374,8 @@ public abstract class CoreAbility implements Ability {
}
/**
* 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();
@ -352,7 +387,8 @@ 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)
*/
@ -380,7 +416,7 @@ public abstract class CoreAbility implements Ability {
}
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;
@ -417,11 +454,14 @@ public abstract class CoreAbility implements Ability {
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();
}
}
@ -475,7 +515,8 @@ public abstract class CoreAbility implements Ability {
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();
@ -488,6 +529,14 @@ public abstract class CoreAbility implements Ability {
return startTime;
}
public long getStartTick() {
return startTick;
}
public long getCurrentTick() {
return player.getWorld().getFullTime();
}
public boolean isStarted() {
return started;
}
@ -548,6 +597,68 @@ public abstract class CoreAbility implements Ability {
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.
* <p>
* collision.getAbilitySecond() - the ability that we are colliding with
* collision.isRemovingFirst() - if this ability should be removed
* <p>
* 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<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
locations.add(getLocation());
return locations;
}
/**
* @return the current FileConfiguration for the plugin
*/
@ -563,8 +674,8 @@ public abstract class CoreAbility implements Ability {
}
/**
* 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();
@ -604,4 +715,9 @@ public abstract class CoreAbility implements Ability {
}
return sb.toString();
}
public static double getDefaultCollisionRadius() {
return DEFAULT_COLLISION_RADIUS;
}
}

View file

@ -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);
}

View file

@ -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 {
@ -61,6 +63,15 @@ public abstract class FireAbility extends ElementalAbility {
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.
* <p>
* 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<String> list = new ArrayList<String>();
list.add("FireShield");

View file

@ -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.
* <p>
* 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.
* <p>
* 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);
}

View file

@ -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;
}
}

View file

@ -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));
}
}

View file

@ -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}.
* <p>
* 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.
* <p>
* 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<Collision> 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<CoreAbility, List<Location>> 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<CoreAbility> alreadyCollided = new HashSet<CoreAbility>();
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<Location> 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<Location> 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<Collision> getCollisions() {
return collisions;
}
public void setCollisions(ArrayList<Collision> collisions) {
this.collisions = collisions;
}
public BukkitRunnable getDetectionRunnable() {
return detectionRunnable;
}
public void setDetectionRunnable(BukkitRunnable detectionRunnable) {
this.detectionRunnable = detectionRunnable;
}
}

View file

@ -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<AbilityInformation> 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<AbilityInformation> 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<AbilityInformation> 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);
@ -211,8 +219,6 @@ public class ComboManager {
}
}.runTaskLater(ProjectKorra.plugin, 1L);
}
/**

View file

@ -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;
@ -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,9 +400,10 @@ 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())) {
@ -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)) {
@ -460,6 +466,11 @@ public class AirBlast extends AirAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public Location getOrigin() {
return origin;
}

View file

@ -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 {
@ -129,8 +128,6 @@ public class AirBubble extends AirAbility {
}
}
}
WaterAbility.removeWaterSpouts(location, radius, player);
}
@Override
@ -168,6 +165,11 @@ public class AirBubble extends AirAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public boolean isWaterBubble() {
return waterBubble;
}

View file

@ -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 {
@ -76,7 +77,7 @@ public class AirBurst extends AirAbility {
return;
}
if (System.currentTimeMillis() > startTime + chargeTime && !isCharged) {
if (System.currentTimeMillis() > getStartTime() + chargeTime && !isCharged) {
isCharged = true;
}
@ -227,6 +228,14 @@ public class AirBurst extends AirAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (AirBlast blast : blasts) {
locations.add(blast.getLocation());
}
return locations;
}
public void addAffectedEntity(Entity entity) {
affectedEntities.add(entity);

View file

@ -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,11 +11,21 @@ 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"
* 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 {
@ -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);
@ -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;
}
@ -434,6 +423,12 @@ public class AirCombo extends AirAbility implements ComboAbility {
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;
}
@ -610,6 +604,10 @@ public class AirCombo extends AirAbility implements ComboAbility {
return tasks;
}
public void setTasks(ArrayList<BukkitRunnable> tasks) {
this.tasks = tasks;
}
public ArrayList<Flight> getFlights() {
return flights;
}
@ -618,9 +616,10 @@ public class AirCombo extends AirAbility implements ComboAbility {
this.cooldown = cooldown;
}
public class AirStream extends AirCombo {
// Combo subclasses need to be static to be reflectively called in ComboManager
public static class AirStream extends AirCombo {
public AirStream(Player player, String name) {
public AirStream(Player player) {
super(player, "AirStream");
}
@ -629,11 +628,16 @@ public class AirCombo extends AirAbility implements ComboAbility {
return "AirStream";
}
@Override
public boolean isCollidable() {
return true;
}
public class AirSweep extends AirCombo {
}
public AirSweep(Player player, String name) {
public static class AirSweep extends AirCombo {
public AirSweep(Player player) {
super(player, "AirSweep");
}
@ -642,11 +646,52 @@ public class AirCombo extends AirAbility implements ComboAbility {
return "AirSweep";
}
@Override
public boolean isCollidable() {
return true;
}
public class Twister extends AirCombo {
@Override
public void handleCollision(Collision collision) {
if (collision.isRemovingFirst()) {
ArrayList<BukkitRunnable> 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);
}
}
public Twister(Player player, String name) {
@Override
public List<Location> getLocations() {
ArrayList<Location> 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");
}

View file

@ -35,8 +35,7 @@ public class AirScooter extends AirAbility {
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;
@ -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;
@ -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);
@ -163,10 +162,8 @@ 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();
@ -192,7 +189,6 @@ public class AirScooter extends AirAbility {
}
}
@Override
public String getName() {
return "AirScooter";
@ -218,6 +214,10 @@ public class AirScooter extends AirAbility {
return true;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public double getSpeed() {
return speed;

View file

@ -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 {
@ -65,6 +59,11 @@ public class AirShield extends AirAbility {
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;
@ -207,6 +196,11 @@ public class AirShield extends AirAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public boolean isToggledByAvatarState() {
return isToggledByAvatarState;
}

View file

@ -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,6 +11,7 @@ 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 {
@ -16,6 +19,7 @@ public class AirSpout extends AirAbility {
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;
@ -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");
@ -49,6 +54,11 @@ public class AirSpout extends AirAbility {
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)) {
@ -100,10 +110,7 @@ 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;
}
@ -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());
@ -202,6 +209,22 @@ public class AirSpout extends AirAbility {
return true;
}
@Override
public boolean isCollidable() {
return true;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> 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;
}

View file

@ -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;
@ -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));
}
}
@ -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)) {
@ -255,6 +260,11 @@ public class AirSuction extends AirAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public Location getOrigin() {
return origin;
}

View file

@ -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,12 +16,17 @@ 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 {
@ -105,6 +101,11 @@ public class AirSwipe extends AirAbility {
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,25 +131,9 @@ 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();
@ -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<Entity> entities = GeneralMethods.getEntitiesAroundPoint(location, radius);
final Vector fDirection = direction;
@ -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);
}
}
@ -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<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (Location swipeLoc : elements.values()) {
locations.add(swipeLoc);
}
return locations;
}
public Location getOrigin() {
return origin;
}

View file

@ -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 {
@ -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) {
@ -174,8 +172,7 @@ public class Suffocate extends AirAbility {
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<Entity> 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;
@ -494,6 +483,13 @@ public class Suffocate extends AirAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
locations.add(player.getLocation());
return locations;
}
public boolean isStarted() {
return started;
}

View file

@ -210,6 +210,11 @@ public class Tornado extends AirAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public Location getOrigin() {
return origin;
}

View file

@ -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");
}

View file

@ -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);

View file

@ -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;
@ -156,6 +158,15 @@ public class Collapse extends EarthAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (Block block : affectedBlocks.values()) {
locations.add(block.getLocation());
}
return locations;
}
public Location getOrigin() {
return origin;
}

View file

@ -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 {
@ -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;
@ -230,19 +225,6 @@ public class EarthBlast extends EarthAbility {
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())) {
location = location.clone().add(direction);
@ -311,8 +293,7 @@ public class EarthBlast extends EarthAbility {
sourceType = Material.SAND;
sourceBlock.setType(sourceType);
sourceBlock.setData((byte) 0x1);
}
else {
} else {
sourceBlock.setType(sourceType);
}
}
@ -398,6 +379,11 @@ public class EarthBlast extends EarthAbility {
}
}
/**
* 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)) {
@ -448,10 +434,7 @@ public class EarthBlast extends EarthAbility {
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());
}
@ -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;
}

View file

@ -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,9 +13,13 @@ 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 {
@ -155,7 +153,7 @@ 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;
}
@ -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);
@ -211,9 +209,6 @@ public class EarthSmash extends EarthAbility {
}
}
WaterAbility.removeWaterSpouts(location, 2, player);
AirAbility.removeAirSpouts(location, 2, player);
EarthAbility.removeSandSpouts(location, player);
draw();
return;
} else {
@ -238,9 +233,7 @@ public class EarthSmash extends EarthAbility {
// 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() {
@ -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<Block> getBlocks() {
List<Block> blocks = new ArrayList<Block>();
@ -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<Block> getBlocksIncludingInner() {
List<Block> blocks = new ArrayList<Block>();
@ -519,8 +508,7 @@ public class EarthSmash extends EarthAbility {
/**
* 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) {
@ -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<Entity> entities = GeneralMethods.getEntitiesAroundPoint(location, flightDetectionRadius);
@ -564,14 +551,13 @@ 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;
@ -581,8 +567,8 @@ public class EarthSmash extends EarthAbility {
/**
* 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;
@ -717,6 +701,15 @@ public class EarthSmash extends EarthAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (TempBlock tblock : affectedBlocks) {
locations.add(tblock.getLocation());
}
return locations;
}
public boolean isAllowGrab() {
return allowGrab;
}

View file

@ -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;
@ -139,6 +141,15 @@ public class EarthTunnel extends EarthAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (TempBlock tblock : airBlocks.keySet()) {
locations.add(tblock.getLocation());
}
return locations;
}
public long getInterval() {
return interval;
}

View file

@ -18,6 +18,7 @@ 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;
@ -251,10 +252,7 @@ public class LavaFlow extends LavaAbility {
}
}
} 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);
}
}
@ -274,12 +272,13 @@ 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;
@ -298,8 +297,7 @@ public class LavaFlow extends LavaAbility {
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);
}
@ -398,7 +396,8 @@ 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);
@ -516,7 +515,6 @@ public class LavaFlow extends LavaAbility {
}
}
/**
* Returns a list of all the Lava blocks that are adjacent to the block at
* loc.
@ -640,6 +638,15 @@ public class LavaFlow extends LavaAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (TempBlock tblock : affectedBlocks) {
locations.add(tblock.getLocation());
}
return locations;
}
public boolean isRemoving() {
return removing;
}

View file

@ -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;
@ -179,6 +181,15 @@ public class RaiseEarth extends EarthAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (Block block : affectedBlocks.values()) {
locations.add(block.getLocation());
}
return locations;
}
public int getDistance() {
return distance;
}

View file

@ -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<Location> getLocations() {
return locations;
}
public int getStep() {
return step;
}
@ -416,10 +421,6 @@ public class Ripple extends EarthAbility {
this.block4 = block4;
}
public ArrayList<Location> getLocations() {
return locations;
}
public ArrayList<Entity> getEntities() {
return entities;
}

View file

@ -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 {
@ -260,6 +262,20 @@ public class SandSpout extends SandAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> 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;
}

View file

@ -64,7 +64,7 @@ public class Shockwave extends EarthAbility {
return;
}
if (System.currentTimeMillis() > startTime + chargeTime && !charged) {
if (System.currentTimeMillis() > getStartTime() + chargeTime && !charged) {
charged = true;
}

View file

@ -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;
}
}

View file

@ -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())) {
@ -177,6 +183,11 @@ public class Combustion extends CombustionAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public boolean isBreakBlocks() {
return breakBlocks;
}

View file

@ -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)) {
@ -285,6 +275,11 @@ public class FireBlast extends FireAbility {
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;
}

View file

@ -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) {
@ -321,6 +321,16 @@ public class FireBlastCharged extends FireAbility {
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;
}

View file

@ -117,7 +117,7 @@ public class FireBurst extends FireAbility {
return;
}
if (System.currentTimeMillis() > startTime + chargeTime && !charged) {
if (System.currentTimeMillis() > getStartTime() + chargeTime && !charged) {
charged = true;
}

View file

@ -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,27 +30,12 @@ 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"
* 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<String> BLOCKABLE_ABILITIES = new ArrayList<String>() {
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;
private long time;
@ -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<FireCombo> getFireCombo(Player player, ClickType type) {
ArrayList<FireCombo> list = new ArrayList<FireCombo>();
@ -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;
@ -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()) {
@ -304,15 +283,6 @@ public class FireCombo extends FireAbility implements ComboAbility {
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();
@ -332,8 +302,7 @@ 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);
@ -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() {
@ -597,6 +562,21 @@ public class FireCombo extends FireAbility implements ComboAbility {
return false;
}
@Override
public boolean isCollidable() {
// Override in subclasses
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (FireComboStream stream : tasks) {
locations.add(stream.getLocation());
}
return locations;
}
@Override
public String getInstructions() {
return null;
@ -612,6 +592,24 @@ public class FireCombo extends FireAbility implements ComboAbility {
return null;
}
public void handleCollisionFireStreams(Collision collision) {
if (collision.isRemovingFirst()) {
ArrayList<FireComboStream> 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<String> getBlockableAbilities() {
return BLOCKABLE_ABILITIES;
}
public ArrayList<LivingEntity> getAffectedEntities() {
return affectedEntities;
}
@ -748,6 +742,10 @@ public class FireCombo extends FireAbility implements ComboAbility {
return tasks;
}
public void setTasks(ArrayList<FireComboStream> tasks) {
this.tasks = tasks;
}
public void setCooldown(long cooldown) {
this.cooldown = cooldown;
}
@ -756,9 +754,10 @@ public class FireCombo extends FireAbility implements ComboAbility {
this.location = location;
}
public class FireKick extends FireCombo {
// Combo subclasses need to be static to be reflectively called in ComboManager
public static class FireKick extends FireCombo {
public FireKick(Player player, String name) {
public FireKick(Player player) {
super(player, "FireKick");
}
@ -767,11 +766,21 @@ public class FireCombo extends FireAbility implements ComboAbility {
return "FireKick";
}
@Override
public boolean isCollidable() {
return true;
}
public class FireSpin extends FireCombo {
@Override
public void handleCollision(Collision collision) {
handleCollisionFireStreams(collision);
}
public FireSpin(Player player, String name) {
}
public static class FireSpin extends FireCombo {
public FireSpin(Player player) {
super(player, "FireSpin");
}
@ -780,11 +789,21 @@ public class FireCombo extends FireAbility implements ComboAbility {
return "FireSpin";
}
@Override
public boolean isCollidable() {
return true;
}
public class FireWheel extends FireCombo {
@Override
public void handleCollision(Collision collision) {
handleCollisionFireStreams(collision);
}
public FireWheel(Player player, String name) {
}
public static class FireWheel extends FireCombo {
public FireWheel(Player player) {
super(player, "FireWheel");
}
@ -793,11 +812,16 @@ public class FireCombo extends FireAbility implements ComboAbility {
return "FireWheel";
}
@Override
public boolean isCollidable() {
return true;
}
public class JetBlast extends FireCombo {
}
public JetBlast(Player player, String name) {
public static class JetBlast extends FireCombo {
public JetBlast(Player player) {
super(player, "JetBlast");
}
@ -808,9 +832,9 @@ public class FireCombo extends FireAbility implements ComboAbility {
}
public class JetBlaze extends FireCombo {
public static class JetBlaze extends FireCombo {
public JetBlaze(Player player, String name) {
public JetBlaze(Player player) {
super(player, "JetBlaze");
}

View file

@ -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,8 +13,10 @@ 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 {
@ -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) {
@ -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,7 +106,7 @@ public class FireShield extends FireAbility {
if (shield) {
ArrayList<Block> 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) {
@ -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<Block> 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,7 +202,7 @@ public class FireShield extends FireAbility {
@Override
public Location getLocation() {
return player != null ? player.getLocation() : null;
return location;
}
@Override
@ -223,6 +220,11 @@ public class FireShield extends FireAbility {
return false;
}
@Override
public double getCollisionRadius() {
return shield ? radius : discRadius;
}
public boolean isShield() {
return shield;
}

View file

@ -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<Entity> affectedEntities;
private ArrayList<Arc> arcs;
private ArrayList<BukkitRunnable> tasks;
private ArrayList<Location> 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<Location> getLocations() {
return locations;
}
public boolean isCharged() {
return charged;
}

View file

@ -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();
}
@ -219,6 +219,15 @@ public class WallOfFire extends FireAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (Block block : blocks) {
locations.add(block.getLocation());
}
return locations;
}
public boolean isActive() {
return active;
}

View file

@ -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;
}
@ -329,6 +332,16 @@ public class Bloodbending extends BloodAbility {
return false;
}
@Override
public List<Location> getLocations() {
// for collision purposes we only care about the player's location
ArrayList<Location> locations = new ArrayList<>();
if (player != null) {
locations.add(player.getLocation());
}
return locations;
}
public boolean isCanOnlyBeUsedAtNight() {
return canOnlyBeUsedAtNight;
}

View file

@ -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);

View file

@ -339,6 +339,16 @@ public class IceBlast extends IceAbility {
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;
}

View file

@ -265,7 +265,6 @@ public class IceSpikeBlast extends IceAbility {
sourceBlock.setType(Material.AIR);
}
}
public static void activate(Player player) {
@ -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();
}
}
@ -346,9 +344,7 @@ public class IceSpikeBlast extends IceAbility {
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) {
@ -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;
}

View file

@ -476,6 +476,11 @@ public class OctopusForm extends WaterAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public boolean isSourceSelected() {
return sourceSelected;
}

View file

@ -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;
}

View file

@ -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<Location> 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,6 +217,7 @@ public class SurgeWall extends WaterAbility {
remove();
return;
}
locations.clear();
if (System.currentTimeMillis() - time >= interval) {
time = System.currentTimeMillis();
@ -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);
}
}
@ -484,6 +489,11 @@ public class SurgeWall extends WaterAbility {
return false;
}
@Override
public List<Location> getLocations() {
return locations;
}
public boolean isProgressing() {
return progressing;
}

View file

@ -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 {
@ -440,6 +441,23 @@ public class SurgeWave extends WaterAbility {
return false;
}
@Override
public boolean isCollidable() {
return progressing || activateFreeze;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> 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;
}

View file

@ -656,6 +656,23 @@ public class Torrent extends WaterAbility {
return false;
}
@Override
public boolean isCollidable() {
return forming || formed || launch || launching;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> 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;
}

View file

@ -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<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (TempBlock tblock : blocks) {
locations.add(tblock.getLocation());
}
return locations;
}
public long getTime() {
return time;
}

View file

@ -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,8 +32,8 @@ 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"
* 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,7 +79,6 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
if (name.equalsIgnoreCase("IceWave")) {
if (bPlayer.isOnCooldown("IceWave") && !bPlayer.isAvatarState()) {
remove();
return;
@ -115,7 +117,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
if (name.equalsIgnoreCase("IceBulletLeftClick") || name.equalsIgnoreCase("IceBulletRightClick")) {
ArrayList<WaterCombo> bullets = getWaterCombo(player, "IceBullet");
Collection<IceBullet> bullets = CoreAbility.getAbilities(player, IceBullet.class);
if (bullets.size() == 0) {
return;
}
@ -197,10 +199,6 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
}
}
if (GeneralMethods.blockAbilities(player, FireCombo.getBlockableAbilities(), loc, 1)) {
fstream.remove();
}
}
}
}
@ -379,6 +377,12 @@ public class WaterCombo extends IceAbility implements ComboAbility {
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<BukkitRunnable> tasks) {
this.tasks = tasks;
}
public static Map<Block, TempBlock> getFrozenBlocks() {
return FROZEN_BLOCKS;
}
@ -546,9 +554,10 @@ public class WaterCombo extends IceAbility implements ComboAbility {
this.location = location;
}
public class IceWave extends WaterCombo {
// Combo subclasses need to be static to be reflectively called in ComboManager
public static class IceWave extends WaterCombo {
public IceWave(Player player, String name) {
public IceWave(Player player) {
super(player, "IceWave");
}
@ -559,9 +568,9 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
public class IceBullet extends WaterCombo {
public static class IceBullet extends WaterCombo {
public IceBullet(Player player, String name) {
public IceBullet(Player player) {
super(player, "IceBullet");
}
@ -570,6 +579,73 @@ public class WaterCombo extends IceAbility implements ComboAbility {
return "IceBullet";
}
@Override
public boolean isCollidable() {
return true;
}
@Override
public void handleCollision(Collision collision) {
if (collision.isRemovingFirst()) {
ArrayList<BukkitRunnable> 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<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (BukkitRunnable task : getTasks()) {
if (task instanceof FireComboStream) {
FireComboStream stream = (FireComboStream) task;
locations.add(stream.getLocation());
}
}
return locations;
}
}
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";
}
}
}

View file

@ -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)) {
@ -597,6 +581,24 @@ public class WaterManipulation extends WaterAbility {
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;
}

View file

@ -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)) {
@ -333,6 +339,24 @@ public class WaterSpout extends WaterAbility {
return true;
}
@Override
public boolean isCollidable() {
return true;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> 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;
}

View file

@ -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;
@ -474,6 +477,16 @@ public class WaterSpoutWave extends WaterAbility {
return false;
}
@Override
public boolean isCollidable() {
return collidable;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public double getRadius() {
return radius;
}