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;
@ -34,6 +37,16 @@ public abstract class AirAbility extends ElementalAbility {
public Element getElement() {
return Element.AIR;
}
@Override
public void handleCollision(Collision collision) {
super.handleCollision(collision);
if (collision.isRemovingFirst()) {
ParticleData particleData = (ParticleEffect.ParticleData) new ParticleEffect.BlockData(Material.WOOL, (byte) 0);
ParticleEffect.BLOCK_CRACK.display(particleData, 1F, 1F, 1F, 0.1F, 10, collision.getLocationFirst(), 50);
}
}
/**
* Breaks a breathbendng hold on an entity or one a player is inflicting on an entity.
@ -77,11 +90,15 @@ public abstract class AirAbility extends ElementalAbility {
}
/**
* This method was used for the old collision detection system. Please see
* {@link Collision} for the new system.
* <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()
@ -51,35 +59,41 @@ import sun.reflect.ReflectionFactory;
* @see #registerPluginAbilities(JavaPlugin, String)
*/
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.
@ -91,13 +105,14 @@ public abstract class CoreAbility implements Ability {
if (player == null) {
return;
}
this.player = player;
this.bPlayer = BendingPlayer.getBendingPlayer(player);
this.startTime = System.currentTimeMillis();
this.started = false;
this.id = CoreAbility.idCounter;
this.startTick = getCurrentTick();
if (idCounter == Integer.MAX_VALUE) {
idCounter = Integer.MIN_VALUE;
} else {
@ -106,9 +121,10 @@ public abstract class CoreAbility implements Ability {
}
/**
* Causes the ability to begin updating every tick by calling {@link #progress()}
* until {@link #remove()} is called. This method cannot be overridden, and any code
* that needs to be performed before start should be handled in the constructor.
* Causes the ability to begin updating every tick by calling
* {@link #progress()} until {@link #remove()} is called. This method cannot
* be overridden, and any code that needs to be performed before start
* should be handled in the constructor.
*
* @see #getStartTime()
* @see #isStarted()
@ -120,7 +136,7 @@ public abstract class CoreAbility implements Ability {
}
AbilityStartEvent event = new AbilityStartEvent(this);
Bukkit.getServer().getPluginManager().callEvent(event);
if(event.isCancelled()) {
if (event.isCancelled()) {
remove();
return;
}
@ -144,11 +160,12 @@ public abstract class CoreAbility implements Ability {
}
/**
* Causes this CoreAbility instance to be removed, and {@link #progress} will no longer
* be called every tick. If this method is overridden then the new method must call
* <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
@ -156,10 +173,10 @@ public abstract class CoreAbility implements Ability {
if (player == null) {
return;
}
Bukkit.getServer().getPluginManager().callEvent(new AbilityEndEvent(this));
removed = true;
Map<UUID, Map<Integer, CoreAbility>> classMap = INSTANCES.get(getClass());
if (classMap != null) {
Map<Integer, CoreAbility> playerMap = classMap.get(player.getUniqueId());
@ -169,7 +186,7 @@ public abstract class CoreAbility implements Ability {
classMap.remove(player.getUniqueId());
}
}
if (classMap.size() == 0) {
INSTANCES.remove(getClass());
}
@ -194,7 +211,8 @@ public abstract class CoreAbility implements Ability {
}
/**
* Removes every CoreAbility instance that has been started but not yet removed.
* Removes every CoreAbility instance that has been started but not yet
* removed.
*/
public static void removeAll() {
for (Set<CoreAbility> setAbils : INSTANCES_BY_CLASS.values()) {
@ -202,7 +220,7 @@ public abstract class CoreAbility implements Ability {
abil.remove();
}
}
for (CoreAbility coreAbility : ABILITIES_BY_NAME.values()) {
if (coreAbility instanceof AddonAbility) {
AddonAbility addon = (AddonAbility) coreAbility;
@ -212,8 +230,8 @@ public abstract class CoreAbility implements Ability {
}
/**
* Returns any T CoreAbility that has been started and not yet removed. May return null if
* no such ability exists.
* Returns any T CoreAbility that has been started and not yet removed. May
* return null if no such ability exists.
*
* @param player the player that created the CoreAbility instance
* @param clazz the class of the type of CoreAbility
@ -226,16 +244,18 @@ public abstract class CoreAbility implements Ability {
}
return null;
}
/**
* Returns a "fake" instance for the CoreAbility represented by abilityName. This method
* does not look into CoreAbility instances that were created by Players, instead this
* method looks at the CoreAbilities that were created via Reflection by {@link #registerAbilities()}
* when the plugin was first loaded.
* Returns a "fake" instance for the CoreAbility represented by abilityName.
* This method does not look into CoreAbility instances that were created by
* Players, instead this method looks at the CoreAbilities that were created
* via Reflection by {@link #registerAbilities()} when the plugin was first
* loaded.
*
* <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>
@ -247,16 +267,28 @@ public abstract class CoreAbility implements Ability {
public static CoreAbility getAbility(String abilityName) {
return abilityName != null ? ABILITIES_BY_NAME.get(abilityName.toLowerCase()) : null;
}
/**
* Returns a list of "fake" instances for each ability that was loaded by {@link #registerAbilities()}
* Returns a "fake" instance for a CoreAbility with the specific class.
*
* @param clazz the class for the type of CoreAbility to be returned
* @return a "fake" CoreAbility instance or null
*/
public static CoreAbility getAbility(Class<? extends CoreAbility> clazz) {
return clazz != null ? ABILITIES_BY_CLASS.get(clazz) : null;
}
/**
* @return a list of "fake" instances for each ability that was loaded by
* {@link #registerAbilities()}
*/
public static ArrayList<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
@ -283,9 +316,10 @@ public abstract class CoreAbility implements Ability {
}
return (Collection<T>) INSTANCES.get(clazz).get(player.getUniqueId()).values();
}
/**
* Returns an List of fake instances that were loaded by {@link #registerAbilities()} filtered by Element.
* Returns an List of fake instances that were loaded by
* {@link #registerAbilities()} filtered by Element.
*
* @param element the Element of the loaded abilities
* @return a list of fake CoreAbility instances
@ -306,7 +340,7 @@ public abstract class CoreAbility implements Ability {
}
return abilities;
}
/**
* Returns true if the player has an active CoreAbility instance of type T.
*
@ -316,9 +350,10 @@ public abstract class CoreAbility implements Ability {
public static <T extends CoreAbility> boolean hasAbility(Player player, Class<T> clazz) {
return getAbility(player, clazz) != null;
}
/**
* Returns a Set of all of the players that currently have an active instance of clazz.
* Returns a Set of all of the players that currently have an active
* instance of clazz.
*
* @param clazz the clazz for the type of CoreAbility
*/
@ -337,10 +372,10 @@ public abstract class CoreAbility implements Ability {
}
return players;
}
/**
* Scans and loads plugin CoreAbilities, and Addon CoreAbilities that are located
* in a Jar file inside of the /ProjectKorra/Abilities/ folder.
* Scans and loads plugin CoreAbilities, and Addon CoreAbilities that are
* located in a Jar file inside of the /ProjectKorra/Abilities/ folder.
*/
public static void registerAbilities() {
ABILITIES_BY_NAME.clear();
@ -350,9 +385,10 @@ public abstract class CoreAbility implements Ability {
/**
* Scans a JavaPlugin and registers CoreAbility class files.
*
*
* @param plugin a JavaPlugin containing CoreAbility class files
* @param packagePrefix a prefix of the package name, used to increase performance
* @param packagePrefix a prefix of the package name, used to increase
* performance
* @see #getAbilities()
* @see #getAbility(String)
*/
@ -361,26 +397,26 @@ public abstract class CoreAbility implements Ability {
if (plugin == null) {
return;
}
Class<?> pluginClass = plugin.getClass();
ClassLoader loader = pluginClass.getClassLoader();
ReflectionFactory rf = ReflectionFactory.getReflectionFactory();
try {
for (final ClassInfo info : ClassPath.from(loader).getAllClasses()) {
if (!info.getPackageName().startsWith(packagePrefix)) {
continue;
}
Class<?> clazz = null;
try {
clazz = info.load();
if (!CoreAbility.class.isAssignableFrom(clazz) || clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) {
continue;
}
Constructor<?> objDef = CoreAbility.class.getDeclaredConstructor();
Constructor<?> intConstr = rf.newConstructorForSerialization(clazz, objDef);;
Constructor<?> intConstr = rf.newConstructorForSerialization(clazz, objDef);
CoreAbility ability = (CoreAbility) clazz.cast(intConstr.newInstance());
if (ability == null || ability.getName() == null) {
@ -393,6 +429,7 @@ public abstract class CoreAbility implements Ability {
String name = ability.getName();
ABILITIES_BY_NAME.put(ability.getName().toLowerCase(), ability);
ABILITIES_BY_CLASS.put(ability.getClass(), ability);
if (ability instanceof ComboAbility) {
ComboAbility combo = (ComboAbility) ability;
@ -407,25 +444,28 @@ public abstract class CoreAbility implements Ability {
ComboManager.getAuthors().put(name, author);
}
}
if (ability instanceof MultiAbility) {
MultiAbility multiAbil = (MultiAbility) ability;
MultiAbilityManager.multiAbilityList.add(new MultiAbilityInfo(name, multiAbil.getMultiAbilities()));
}
if (ability instanceof AddonAbility) {
AddonAbility addon = (AddonAbility) ability;
addon.load();
}
} catch (Exception e) {
} catch (Error e) {
}
catch (Exception e) {
}
catch (Error e) {
}
}
} catch (IOException e) {
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Scans all of the Jar files inside of /ProjectKorra/folder and registers
* all of the CoreAbility class files that were found.
@ -441,10 +481,10 @@ public abstract class CoreAbility implements Ability {
path.mkdir();
return;
}
AbilityLoader<CoreAbility> abilityLoader = new AbilityLoader<CoreAbility>(plugin, path);
List<CoreAbility> loadedAbilities = abilityLoader.load(CoreAbility.class, CoreAbility.class);
for (CoreAbility coreAbil : loadedAbilities) {
if (!(coreAbil instanceof AddonAbility)) {
plugin.getLogger().warning(coreAbil.getName() + " is an addon ability and must implement the AddonAbility interface");
@ -453,14 +493,14 @@ public abstract class CoreAbility implements Ability {
plugin.getLogger().info(coreAbil.getName() + " is disabled");
continue;
}
AddonAbility addon = (AddonAbility) coreAbil;
String name = coreAbil.getName();
try {
addon.load();
ABILITIES_BY_NAME.put(name.toLowerCase(), coreAbil);
if (coreAbil instanceof ComboAbility) {
ComboAbility combo = (ComboAbility) coreAbil;
if (combo.getCombination() != null) {
@ -470,28 +510,37 @@ public abstract class CoreAbility implements Ability {
ComboManager.getAuthors().put(name, addon.getAuthor());
}
}
if (coreAbil instanceof MultiAbility) {
MultiAbility multiAbil = (MultiAbility) coreAbil;
MultiAbilityManager.multiAbilityList.add(new MultiAbilityInfo(name, multiAbil.getMultiAbilities()));
}
} catch (Exception | Error e) {
}
catch (Exception | Error e) {
plugin.getLogger().warning("The ability " + coreAbil.getName() + " was not able to load, if this message shows again please remove it!");
e.printStackTrace();
addon.stop();
ABILITIES_BY_NAME.remove(name.toLowerCase());
ABILITIES_BY_NAME.remove(name.toLowerCase());
}
}
}
public long getStartTime() {
return startTime;
}
public long getStartTick() {
return startTick;
}
public long getCurrentTick() {
return player.getWorld().getFullTime();
}
public boolean isStarted() {
return started;
}
public boolean isRemoved() {
return removed;
}
@ -503,37 +552,37 @@ public abstract class CoreAbility implements Ability {
public int getId() {
return id;
}
@Override
public boolean isHiddenAbility() {
return false;
}
@Override
public boolean isEnabled() {
if (this instanceof AddonAbility) {
return true;
}
String elementName = getElement().getName();
if (getElement() instanceof SubElement) {
elementName = ((SubElement) getElement()).getParentElement().getName();
}
String tag = null;
if (this instanceof ComboAbility) {
tag = "Abilities." + elementName + "." + elementName + "Combo." + getName() + ".Enabled";
tag = "Abilities." + elementName + "." + elementName + "Combo." + getName() + ".Enabled";
} else {
tag = "Abilities." + elementName + "." + getName() + ".Enabled";
}
if (getConfig().isBoolean(tag)) {
return getConfig().getBoolean(tag);
} else {
return true;
}
}
@Override
public String getDescription() {
String elementName = getElement().getName();
@ -547,36 +596,98 @@ public abstract class CoreAbility implements Ability {
public Player getPlayer() {
return player;
}
/**
* Used by the CollisionManager to check if two instances can collide with
* each other. For example, an EarthBlast is not collidable right when the
* person selects a source block, but it is collidable once the block begins
* traveling.
*
* @return true if the instance is currently collidable
* @see CollisionManager
*/
public boolean isCollidable() {
return true;
}
/**
* The radius for collision of the ability instance. Some circular abilities
* are better represented with 1 single Location with a small or large
* radius, such as AirShield, FireShield, EarthSmash, WaterManipulation,
* EarthBlast, etc. Some abilities consist of multiple Locations with small
* radiuses, such as AirSpout, WaterSpout, Torrent, RaiseEarth, AirSwipe,
* FireKick, etc.
*
* @return the radius for a location returned by {@link #getLocations()}
* @see CollisionManager
*/
public double getCollisionRadius() {
return DEFAULT_COLLISION_RADIUS;
}
/**
* Called when this ability instance collides with another. Some abilities
* may want advanced behavior on a Collision; e.g. FireCombos only remove
* the stream that was hit rather than the entire ability.
* <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
*/
public static FileConfiguration getConfig() {
return ConfigManager.getConfig();
}
/**
* @return the language.yml for the plugin
*/
public static FileConfiguration getLanguageConfig() {
return ConfigManager.languageConfig.get();
}
/**
* Returns a String used to debug potential CoreAbility memory that can be caused
* by a developer forgetting to call {@link #remove()}
* Returns a String used to debug potential CoreAbility memory that can be
* caused by a developer forgetting to call {@link #remove()}
*/
public static String getDebugString() {
StringBuilder sb = new StringBuilder();
int playerCounter = 0;
HashMap<String, Integer> classCounter = new HashMap<>();
for (Map<UUID, Map<Integer, CoreAbility>> map1 : INSTANCES.values()) {
playerCounter++;
for (Map<Integer, CoreAbility> map2 : map1.values()) {
for (CoreAbility coreAbil : map2.values()) {
String simpleName = coreAbil.getClass().getSimpleName();
if (classCounter.containsKey(simpleName)) {
classCounter.put(simpleName, classCounter.get(simpleName) + 1);
} else {
@ -585,7 +696,7 @@ public abstract class CoreAbility implements Ability {
}
}
}
for (Set<CoreAbility> set : INSTANCES_BY_CLASS.values()) {
for (CoreAbility coreAbil : set) {
String simpleName = coreAbil.getClass().getSimpleName();
@ -596,7 +707,7 @@ public abstract class CoreAbility implements Ability {
}
}
}
sb.append("Class->UUID's in memory: " + playerCounter + "\n");
sb.append("Abilities in memory:\n");
for (String className : classCounter.keySet()) {
@ -604,4 +715,9 @@ public abstract class CoreAbility implements Ability {
}
return sb.toString();
}
public static double getDefaultCollisionRadius() {
return DEFAULT_COLLISION_RADIUS;
}
}

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 {
@ -60,6 +62,15 @@ public abstract class FireAbility extends ElementalAbility {
public Element getElement() {
return Element.FIRE;
}
@Override
public void handleCollision(Collision collision) {
super.handleCollision(collision);
if (collision.isRemovingFirst()) {
ParticleData particleData = (ParticleEffect.ParticleData) new ParticleEffect.BlockData(Material.FIRE, (byte) 0);
ParticleEffect.BLOCK_CRACK.display(particleData, 1F, 1F, 1F, 0.1F, 10, collision.getLocationFirst(), 50);
}
}
public double getDayFactor(double value) {
return player != null ? getDayFactor(value, player.getWorld()) : 1;
@ -140,11 +151,15 @@ public abstract class FireAbility extends ElementalAbility {
}
/**
* This method was used for the old collision detection system. Please see
* {@link Collision} for the new system.
* <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);
@ -209,10 +217,8 @@ 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;
@ -80,7 +81,7 @@ public class AirBlast extends AirAbility {
if (entity != null) {
this.direction = GeneralMethods.getDirection(origin, entity.getLocation()).normalize();
} else {
this.direction = GeneralMethods.getDirection(origin, GeneralMethods.getTargetedLocation(player, range)) .normalize();
this.direction = GeneralMethods.getDirection(origin, GeneralMethods.getTargetedLocation(player, range)).normalize();
}
} else {
origin = player.getEyeLocation();
@ -126,7 +127,7 @@ public class AirBlast extends AirAbility {
this.canOpenDoors = getConfig().getBoolean("Abilities.Air.AirBlast.CanOpenDoors");
this.canPressButtons = getConfig().getBoolean("Abilities.Air.AirBlast.CanPressButtons");
this.canCoolLava = getConfig().getBoolean("Abilities.Air.AirBlast.CanCoolLava");
this.isFromOtherOrigin = false;
this.showParticles = true;
this.random = new Random();
@ -172,7 +173,7 @@ public class AirBlast extends AirAbility {
}
ORIGINS.put(player, location);
}
private void advanceLocation() {
@ -207,7 +208,7 @@ public class AirBlast extends AirAbility {
push.setY(max);
}
}
if(location.getWorld().equals(origin.getWorld())) {
if (location.getWorld().equals(origin.getWorld())) {
factor *= 1 - location.distance(origin) / (2 * range);
}
@ -291,8 +292,7 @@ public class AirBlast extends AirAbility {
continue;
}
Material doorTypes[] = { Material.WOODEN_DOOR, Material.SPRUCE_DOOR, Material.BIRCH_DOOR, Material.JUNGLE_DOOR,
Material.ACACIA_DOOR, Material.DARK_OAK_DOOR };
Material doorTypes[] = { Material.WOODEN_DOOR, Material.SPRUCE_DOOR, Material.BIRCH_DOOR, Material.JUNGLE_DOOR, Material.ACACIA_DOOR, Material.DARK_OAK_DOOR };
if (Arrays.asList(doorTypes).contains(block.getType()) && canOpenDoors) {
if (block.getData() >= 8) {
block = block.getRelative(BlockFace.DOWN);
@ -400,12 +400,13 @@ public class AirBlast extends AirAbility {
}
/*
* If a player presses shift and AirBlasts straight down then the AirBlast's location gets
* messed up and reading the distance returns Double.NaN. If we don't remove this instance
* then the AirBlast will never be removed.
* If a player presses shift and AirBlasts straight down then the
* AirBlast's location gets messed up and reading the distance returns
* Double.NaN. If we don't remove this instance then the AirBlast will
* never be removed.
*/
double dist = 0;
if(location.getWorld().equals(origin.getWorld())) {
if (location.getWorld().equals(origin.getWorld())) {
dist = location.distance(origin);
}
if (Double.isNaN(dist) || dist > range) {
@ -421,6 +422,11 @@ public class AirBlast extends AirAbility {
return;
}
/**
* This method was used for the old collision detection system. Please see
* {@link Collision} for the new system.
*/
@Deprecated
public static boolean removeAirBlastsAroundPoint(Location location, double radius) {
boolean removed = false;
for (AirBlast airBlast : getAbilities(AirBlast.class)) {
@ -449,7 +455,7 @@ public class AirBlast extends AirAbility {
public long getCooldown() {
return cooldown;
}
@Override
public boolean isSneakAbility() {
return true;
@ -460,6 +466,11 @@ public class AirBlast extends AirAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public Location getOrigin() {
return origin;
}
@ -619,13 +630,13 @@ public class AirBlast extends AirAbility {
public void setParticles(int particles) {
this.particles = particles;
}
public static int getSelectParticles() {
return getConfig().getInt("Abilities.Air.AirBlast.SelectParticles");
}
public static double getSelectRange() {
return getConfig().getInt("Abilities.Air.AirBlast.SelectRange");
}
}

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 {
@ -27,7 +26,7 @@ public class AirBubble extends AirAbility {
public AirBubble(Player player) {
super(player);
this.radius = 0;
this.airRadius = getConfig().getDouble("Abilities.Air.AirBubble.Radius");
this.waterRadius = getConfig().getDouble("Abilities.Water.WaterBubble.Radius");
@ -50,7 +49,7 @@ public class AirBubble extends AirAbility {
if (bPlayer == null) {
continue;
}
String name = bPlayer.getBoundAbilityName();
if (name.equalsIgnoreCase("AirBubble") | name.equalsIgnoreCase("WaterBubble")) {
if (!hasAbility(player, AirBubble.class) && player.isSneaking()) {
@ -94,7 +93,7 @@ public class AirBubble extends AirAbility {
} else {
radius = waterRadius;
}
if (airRadius > radius && bPlayer.hasElement(Element.AIR)) {
radius = airRadius;
}
@ -129,8 +128,6 @@ public class AirBubble extends AirAbility {
}
}
}
WaterAbility.removeWaterSpouts(location, radius, player);
}
@Override
@ -157,7 +154,7 @@ public class AirBubble extends AirAbility {
public long getCooldown() {
return 0;
}
@Override
public boolean isSneakAbility() {
return true;
@ -168,6 +165,11 @@ public class AirBubble extends AirAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public boolean isWaterBubble() {
return waterBubble;
}

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 {
@ -27,7 +28,7 @@ public class AirBurst extends AirAbility {
private double particlePercentage;
private ArrayList<AirBlast> blasts;
private ArrayList<Entity> affectedEntities;
public AirBurst(Player player, boolean isFallBurst) {
super(player);
if (bPlayer.isOnCooldown(this)) {
@ -76,7 +77,7 @@ public class AirBurst extends AirAbility {
return;
}
if (System.currentTimeMillis() > startTime + chargeTime && !isCharged) {
if (System.currentTimeMillis() > getStartTime() + chargeTime && !isCharged) {
isCharged = true;
}
@ -99,7 +100,7 @@ public class AirBurst extends AirAbility {
if (bPlayer.isOnCooldown("AirBurst")) {
return;
}
Location location = player.getLocation();
double x, y, z;
double r = 1;
@ -109,11 +110,11 @@ public class AirBurst extends AirAbility {
for (double phi = 0; phi < 360; phi += dphi) {
double rphi = Math.toRadians(phi);
double rtheta = Math.toRadians(theta);
x = r * Math.cos(rphi) * Math.sin(rtheta);
y = r * Math.sin(rphi) * Math.sin(rtheta);
z = r * Math.cos(rtheta);
Vector direction = new Vector(x, z, y);
AirBlast blast = new AirBlast(player, location, direction.normalize(), pushFactor, this);
blast.setDamage(damage);
@ -136,17 +137,17 @@ public class AirBurst extends AirAbility {
double angle = Math.toRadians(30);
double x, y, z;
double r = 1;
for (double theta = 0; theta <= 180; theta += blastAngleTheta) {
double dphi = blastAnglePhi / Math.sin(Math.toRadians(theta));
for (double phi = 0; phi < 360; phi += dphi) {
double rphi = Math.toRadians(phi);
double rtheta = Math.toRadians(theta);
x = r * Math.cos(rphi) * Math.sin(rtheta);
y = r * Math.sin(rphi) * Math.sin(rtheta);
z = r * Math.cos(rtheta);
Vector direction = new Vector(x, z, y);
if (direction.angle(vector) <= angle) {
AirBlast blast = new AirBlast(player, location, direction.normalize(), pushFactor, this);
@ -185,14 +186,14 @@ public class AirBurst extends AirAbility {
for (double phi = 0; phi < 360; phi += dphi) {
double rphi = Math.toRadians(phi);
double rtheta = Math.toRadians(theta);
x = r * Math.cos(rphi) * Math.sin(rtheta);
y = r * Math.sin(rphi) * Math.sin(rtheta);
z = r * Math.cos(rtheta);
Vector direction = new Vector(x, z, y);
AirBlast blast = new AirBlast(player, location, direction.normalize(), pushFactor, this);
blast.setDamage(damage);
blast.setShowParticles(false);
blasts.add(blast);
@ -216,7 +217,7 @@ public class AirBurst extends AirAbility {
public long getCooldown() {
return 0;
}
@Override
public boolean isSneakAbility() {
return true;
@ -227,6 +228,14 @@ public class AirBurst extends AirAbility {
return false;
}
@Override
public List<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,12 +11,22 @@ import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.ComboAbility;
import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation;
import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.firebending.FireCombo.FireComboStream;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.Flight;
/*
* TODO: Combo classes should eventually be rewritten so that each combo is treated
* as an individual ability. In the mean time, we will just place "fake"
* classes so that CoreAbility will register each ability.
* TODO: Combo classes should eventually be rewritten so that each combo is
* treated as an individual ability. In the mean time, we will just place "fake"
* classes so that CoreAbility will register each ability.
*/
public class AirCombo extends AirAbility implements ComboAbility {
@ -62,7 +60,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
public AirCombo(Player player, String ability) {
super(player);
this.abilityName = ability;
this.affectedEntities = new ArrayList<>();
this.tasks = new ArrayList<>();
@ -71,7 +69,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
if (!bPlayer.canBendIgnoreBindsCooldowns(this)) {
return;
}
if (bPlayer.isOnCooldown(ability)) {
return;
}
@ -98,7 +96,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
this.knockback = getConfig().getDouble("Abilities.Air.AirCombo.AirSweep.Knockback");
this.cooldown = getConfig().getLong("Abilities.Air.AirCombo.AirSweep.Cooldown");
}
if (bPlayer.isAvatarState()) {
this.cooldown = 0;
this.damage = AvatarState.getValue(damage);
@ -201,7 +199,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
direction = GeneralMethods.getDirection(currentLoc, destination).normalize();
currentLoc.add(direction.clone().multiply(speed));
if (player.getWorld() != currentLoc.getWorld()) {
remove();
return;
@ -223,12 +221,6 @@ public class AirCombo extends AirAbility implements ComboAbility {
} else if (GeneralMethods.isRegionProtectedFromBuild(this, currentLoc)) {
remove();
return;
} else if (FireAbility.isWithinFireShield(currentLoc)) {
remove();
return;
} else if (isWithinAirShield(currentLoc)) {
remove();
return;
} else if (!isTransparent(currentLoc.getBlock())) {
currentLoc.subtract(direction.clone().multiply(speed));
}
@ -280,8 +272,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
destination = player.getLocation().add(player.getEyeLocation().getDirection().normalize().multiply(10));
Vector origToDest = GeneralMethods.getDirection(origin, destination);
for (double i = 0; i < 30; i++) {
Vector vec = GeneralMethods.getDirection(player.getLocation(),
origin.clone().add(origToDest.clone().multiply(i / 30)));
Vector vec = GeneralMethods.getDirection(player.getLocation(), origin.clone().add(origToDest.clone().multiply(i / 30)));
FireComboStream fs = new FireComboStream(null, vec, player.getLocation(), range, speed, "AirSweep");
fs.setDensity(1);
@ -316,7 +307,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
fstream.remove();
return;
}
if (!isTransparent(loc.getBlock())) {
if (!isTransparent(loc.clone().add(0, 0.2, 0).getBlock())) {
fstream.remove();
@ -346,12 +337,6 @@ public class AirCombo extends AirAbility implements ComboAbility {
}
}
}
if (GeneralMethods.blockAbilities(player, FireCombo.getBlockableAbilities(), loc, 1)) {
fstream.remove();
} else AirAbility.removeAirSpouts(loc, player);
WaterAbility.removeWaterSpouts(loc, player);
EarthAbility.removeSandSpouts(loc, player);
}
}
}
@ -368,6 +353,11 @@ public class AirCombo extends AirAbility implements ComboAbility {
}
}
/**
* This method was used for the old collision detection system. Please see
* {@link Collision} for the new system.
*/
@Deprecated
public static boolean removeAroundPoint(Player player, String ability, Location loc, double radius) {
boolean removed = false;
for (AirCombo combo : getAbilities(AirCombo.class)) {
@ -386,8 +376,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
} else if (ability.equalsIgnoreCase("AirSweep") && combo.abilityName.equalsIgnoreCase("AirSweep")) {
for (int j = 0; j < combo.tasks.size(); j++) {
FireComboStream fs = (FireComboStream) combo.tasks.get(j);
if (fs.getLocation() != null && fs.getLocation().getWorld().equals(loc.getWorld())
&& Math.abs(fs.getLocation().distance(loc)) <= radius) {
if (fs.getLocation() != null && fs.getLocation().getWorld().equals(loc.getWorld()) && Math.abs(fs.getLocation().distance(loc)) <= radius) {
fs.remove();
removed = true;
}
@ -423,7 +412,7 @@ public class AirCombo extends AirAbility implements ComboAbility {
public boolean isHiddenAbility() {
return true;
}
@Override
public boolean isSneakAbility() {
return true;
@ -433,7 +422,13 @@ public class AirCombo extends AirAbility implements ComboAbility {
public boolean isHarmlessAbility() {
return false;
}
@Override
public boolean isCollidable() {
// Override in subclasses
return false;
}
@Override
public String getInstructions() {
return null;
@ -449,7 +444,6 @@ public class AirCombo extends AirAbility implements ComboAbility {
return null;
}
public String getAbilityName() {
return abilityName;
}
@ -609,6 +603,10 @@ public class AirCombo extends AirAbility implements ComboAbility {
public ArrayList<BukkitRunnable> getTasks() {
return tasks;
}
public void setTasks(ArrayList<BukkitRunnable> tasks) {
this.tasks = tasks;
}
public ArrayList<Flight> getFlights() {
return flights;
@ -617,44 +615,91 @@ public class AirCombo extends AirAbility implements ComboAbility {
public void setCooldown(long cooldown) {
this.cooldown = cooldown;
}
public class AirStream extends AirCombo {
public AirStream(Player player, String name) {
// Combo subclasses need to be static to be reflectively called in ComboManager
public static class AirStream extends AirCombo {
public AirStream(Player player) {
super(player, "AirStream");
}
@Override
public String getName() {
return "AirStream";
}
}
public class AirSweep extends AirCombo {
public AirSweep(Player player, String name) {
@Override
public boolean isCollidable() {
return true;
}
}
public static class AirSweep extends AirCombo {
public AirSweep(Player player) {
super(player, "AirSweep");
}
@Override
public String getName() {
return "AirSweep";
}
}
public class Twister extends AirCombo {
public Twister(Player player, String name) {
super(player, "Twister");
@Override
public boolean isCollidable() {
return true;
}
@Override
public void handleCollision(Collision collision) {
if (collision.isRemovingFirst()) {
ArrayList<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 Twister extends AirCombo {
public Twister(Player player) {
super(player, "Twister");
}
@Override
public String getName() {
return "Twister";
}
}
}

View file

@ -25,18 +25,17 @@ public class AirScooter extends AirAbility {
private Block floorblock;
private Random random;
private ArrayList<Double> angles;
private boolean canFly;
private boolean hadFly;
private double phi = 0;
public AirScooter(Player player) {
super(player);
if (check(player))
if (check(player))
return;
else if (!player.isSprinting() || GeneralMethods.isSolid(player.getEyeLocation().getBlock())
|| player.getEyeLocation().getBlock().isLiquid())
else if (!player.isSprinting() || GeneralMethods.isSolid(player.getEyeLocation().getBlock()) || player.getEyeLocation().getBlock().isLiquid())
return;
else if (GeneralMethods.isSolid(player.getLocation().add(0, -.5, 0).getBlock()))
return;
@ -52,7 +51,7 @@ public class AirScooter extends AirAbility {
this.angles = new ArrayList<>();
canFly = player.getAllowFlight();
hadFly = player.isFlying();
new Flight(player);
player.setAllowFlight(true);
player.setFlying(true);
@ -82,8 +81,8 @@ public class AirScooter extends AirAbility {
}
/*
* Looks for a block under the player and sets "floorBlock" to a block
* under the player if it within the maximum height
* Looks for a block under the player and sets "floorBlock" to a block under
* the player if it within the maximum height
*/
private void getFloor() {
floorblock = null;
@ -102,7 +101,7 @@ public class AirScooter extends AirAbility {
remove();
return;
}
getFloor();
if (floorblock == null) {
remove();
@ -114,7 +113,7 @@ public class AirScooter extends AirAbility {
/*
* checks the players speed and ends the move if they are going too slow
*/
if (System.currentTimeMillis() > startTime + interval) {
if (System.currentTimeMillis() > getStartTime() + interval) {
if (player.getVelocity().length() < speed * 0.3) {
remove();
return;
@ -122,8 +121,8 @@ public class AirScooter extends AirAbility {
spinScooter();
}
/*
* Checks for how far the ground is away from the player
* it elevates or lowers the player based on their distance from the ground.
* Checks for how far the ground is away from the player it elevates or
* lowers the player based on their distance from the ground.
*/
double distance = player.getLocation().getY() - (double) floorblock.getY();
double dx = Math.abs(distance - 2.4);
@ -141,7 +140,7 @@ public class AirScooter extends AirAbility {
} else {
return;
}
player.setSprinting(false);
player.removePotionEffect(PotionEffectType.SPEED);
player.setVelocity(velocity);
@ -163,36 +162,33 @@ public class AirScooter extends AirAbility {
}
/*
* The particles used for AirScooter
* phi = how many rings of particles the sphere has.
* theta = how dense the rings are.
* r = Radius of the sphere
* The particles used for AirScooter phi = how many rings of particles the
* sphere has. theta = how dense the rings are. r = Radius of the sphere
*/
private void spinScooter() {
Location origin = player.getLocation();
Location origin2 = player.getLocation();
phi += Math.PI/10*4;
for(double theta = 0; theta <= 2*Math.PI; theta += Math.PI/10) {
phi += Math.PI / 10 * 4;
for (double theta = 0; theta <= 2 * Math.PI; theta += Math.PI / 10) {
double r = 0.6;
double x = r*Math.cos(theta)*Math.sin(phi);
double y = r*Math.cos(phi);
double z = r*Math.sin(theta)*Math.sin(phi);
double x = r * Math.cos(theta) * Math.sin(phi);
double y = r * Math.cos(phi);
double z = r * Math.sin(theta) * Math.sin(phi);
origin.add(x, y, z);
playAirbendingParticles(origin, 1, 0F, 0F, 0F);
origin.subtract(x, y, z);
}
for(double theta = 0; theta <= 2*Math.PI; theta += Math.PI/10) {
for (double theta = 0; theta <= 2 * Math.PI; theta += Math.PI / 10) {
double r = 0.6;
double x = r*Math.cos(theta)*Math.sin(phi);
double y = r*Math.cos(phi);
double z = r*Math.sin(theta)*Math.sin(phi);
double x = r * Math.cos(theta) * Math.sin(phi);
double y = r * Math.cos(phi);
double z = r * Math.sin(theta) * Math.sin(phi);
origin2.subtract(x, y, z);
playAirbendingParticles(origin2, 1, 0F, 0F, 0F);
origin2.add(x, y, z);
}
}
@Override
public String getName() {
return "AirScooter";
@ -207,7 +203,7 @@ public class AirScooter extends AirAbility {
public long getCooldown() {
return cooldown;
}
@Override
public boolean isSneakAbility() {
return false;
@ -218,6 +214,10 @@ public class AirScooter extends AirAbility {
return true;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public double getSpeed() {
return speed;
@ -258,7 +258,7 @@ public class AirScooter extends AirAbility {
public void setFloorblock(Block floorblock) {
this.floorblock = floorblock;
}
public void setCooldown(long cooldown) {
this.cooldown = cooldown;
}

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 {
@ -34,16 +28,16 @@ public class AirShield extends AirAbility {
private int particles;
private Random random;
private HashMap<Integer, Integer> angles;
public AirShield(Player player) {
super(player);
this.maxRadius = getConfig().getDouble("Abilities.Air.AirShield.Radius");
this.isToggledByAvatarState = getConfig().getBoolean("Abilities.Air.AirShield.IsAvatarStateToggle");
this.radius = this.maxRadius;
this.speed = getConfig().getDouble("Abilities.Air.AirShield.Speed");
this.speed = getConfig().getDouble("Abilities.Air.AirShield.Speed");
this.streams = getConfig().getInt("Abilities.Air.AirShield.Streams");
this.particles = getConfig().getInt("Abilities.Air.AirShield.Particles");
this.particles = getConfig().getInt("Abilities.Air.AirShield.Particles");
this.random = new Random();
this.angles = new HashMap<>();
@ -61,10 +55,15 @@ public class AirShield extends AirAbility {
angle = 0;
}
}
start();
}
/**
* This method was used for the old collision detection system. Please see
* {@link Collision} for the new system.
*/
@Deprecated
public static boolean isWithinShield(Location loc) {
for (AirShield ashield : getAbilities(AirShield.class)) {
if (!ashield.player.getWorld().equals(loc.getWorld())) {
@ -96,16 +95,6 @@ public class AirShield extends AirAbility {
private void rotateShield() {
Location origin = player.getLocation();
FireBlast.removeFireBlastsAroundPoint(origin, radius);
Combustion.removeAroundPoint(origin, radius);
BlazeArc.removeAroundPoint(origin, radius);
AirBlast.removeAirBlastsAroundPoint(origin, radius);
AirSuction.removeAirSuctionsAroundPoint(origin, radius);
EarthBlast.removeAroundPoint(origin, radius);
SandSpout.removeSpouts(origin, radius, player);
WaterSpout.removeSpouts(origin, radius, player);
WaterManipulation.removeAroundPoint(origin, radius);
for (Entity entity : GeneralMethods.getEntitiesAroundPoint(origin, radius)) {
if (GeneralMethods.isRegionProtectedFromBuild(player, "AirShield", entity.getLocation())) {
continue;
@ -181,7 +170,7 @@ public class AirShield extends AirAbility {
radius = maxRadius;
}
}
@Override
public String getName() {
return "AirShield";
@ -196,7 +185,7 @@ public class AirShield extends AirAbility {
public long getCooldown() {
return 0;
}
@Override
public boolean isSneakAbility() {
return true;
@ -207,6 +196,11 @@ public class AirShield extends AirAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public boolean isToggledByAvatarState() {
return isToggledByAvatarState;
}

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,26 +11,28 @@ import org.bukkit.entity.Player;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.util.Flight;
public class AirSpout extends AirAbility {
private static final Integer[] DIRECTIONS = {0, 1, 2, 3, 5, 6, 7, 8};
private static final Integer[] DIRECTIONS = { 0, 1, 2, 3, 5, 6, 7, 8 };
private int angle;
private long animTime;
private long interval;
private long cooldown;
private double height;
public AirSpout(Player player) {
super(player);
AirSpout spout = getAbility(player, AirSpout.class);
if (spout != null) {
spout.remove();
return;
}
if (!bPlayer.canBend(this)) {
remove();
return;
@ -36,6 +40,7 @@ public class AirSpout extends AirAbility {
this.angle = 0;
this.cooldown = 0;
this.animTime = System.currentTimeMillis();
this.interval = getConfig().getLong("Abilities.Air.AirSpout.Interval");
this.height = getConfig().getDouble("Abilities.Air.AirSpout.Height");
@ -43,12 +48,17 @@ public class AirSpout extends AirAbility {
if (!isWithinMaxSpoutHeight(heightRemoveThreshold)) {
return;
}
new Flight(player);
start();
bPlayer.addCooldown(this);
}
/**
* This method was used for the old collision detection system. Please see
* {@link Collision} for the new system.
*/
@Deprecated
public static boolean removeSpouts(Location loc0, double radius, Player sourceplayer) {
boolean removed = false;
for (AirSpout spout : getAbilities(AirSpout.class)) {
@ -74,7 +84,7 @@ public class AirSpout extends AirAbility {
player.setAllowFlight(true);
player.setFlying(true);
}
private boolean isWithinMaxSpoutHeight(double threshold) {
Block ground = getGround();
if (ground == null) {
@ -100,21 +110,18 @@ public class AirSpout extends AirAbility {
@Override
public void progress() {
if (player.isDead()
|| !player.isOnline()
|| !bPlayer.canBendIgnoreBindsCooldowns(this)
|| !bPlayer.canBind(this)) {
if (player.isDead() || !player.isOnline() || !bPlayer.canBendIgnoreBindsCooldowns(this) || !bPlayer.canBind(this)) {
remove();
return;
}
double heightRemoveThreshold = 2;
if (!isWithinMaxSpoutHeight(heightRemoveThreshold)) {
remove();
return;
}
if(!bPlayer.canBind(this)) {
if (!bPlayer.canBind(this)) {
remove();
return;
}
@ -159,8 +166,8 @@ public class AirSpout extends AirAbility {
if (!player.getWorld().equals(block.getWorld())) {
return;
}
if (System.currentTimeMillis() >= startTime + interval) {
startTime = System.currentTimeMillis();
if (System.currentTimeMillis() >= animTime + interval) {
animTime = System.currentTimeMillis();
Location location = block.getLocation();
Location playerloc = player.getLocation();
location = new Location(location.getWorld(), playerloc.getX(), location.getY(), playerloc.getZ());
@ -191,7 +198,7 @@ public class AirSpout extends AirAbility {
public long getCooldown() {
return cooldown;
}
@Override
public boolean isSneakAbility() {
return false;
@ -202,6 +209,22 @@ public class AirSpout extends AirAbility {
return true;
}
@Override
public boolean isCollidable() {
return true;
}
@Override
public List<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;
}
@ -229,5 +260,5 @@ public class AirSpout extends AirAbility {
public void setCooldown(long cooldown) {
this.cooldown = cooldown;
}
}

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;
@ -24,7 +25,7 @@ public class AirSuction extends AirAbility {
private static final int MAX_TICKS = 10000;
private static final Map<Player, Location> ORIGINS = new ConcurrentHashMap<>();
private boolean hasOtherOrigin;
private int ticks;
private int particleCount;
@ -37,10 +38,10 @@ public class AirSuction extends AirAbility {
private Location location;
private Location origin;
private Vector direction;
public AirSuction(Player player) {
super(player);
if (bPlayer.isOnCooldown(this)) {
return;
} else if (player.getEyeLocation().getBlock().isLiquid()) {
@ -133,8 +134,7 @@ public class AirSuction extends AirAbility {
Location location = origin.clone();
for (double i = 1; i <= range; i++) {
location = origin.clone().add(direction.clone().multiply(i));
if (!isTransparent(location.getBlock())
|| GeneralMethods.isRegionProtectedFromBuild(this, location)) {
if (!isTransparent(location.getBlock()) || GeneralMethods.isRegionProtectedFromBuild(this, location)) {
return origin.clone().add(direction.clone().multiply(i - 1));
}
}
@ -178,7 +178,7 @@ public class AirSuction extends AirAbility {
push.setY(max);
}
}
if(location.getWorld().equals(origin.getWorld())) {
if (location.getWorld().equals(origin.getWorld())) {
factor *= 1 - location.distance(origin) / (2 * range);
}
@ -216,6 +216,11 @@ public class AirSuction extends AirAbility {
advanceLocation();
}
/**
* This method was used for the old collision detection system. Please see
* {@link Collision} for the new system.
*/
@Deprecated
public static boolean removeAirSuctionsAroundPoint(Location location, double radius) {
boolean removed = false;
for (AirSuction airSuction : getAbilities(AirSuction.class)) {
@ -244,7 +249,7 @@ public class AirSuction extends AirAbility {
public long getCooldown() {
return cooldown;
}
@Override
public boolean isSneakAbility() {
return true;
@ -255,6 +260,11 @@ public class AirSuction extends AirAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public Location getOrigin() {
return origin;
}
@ -346,5 +356,5 @@ public class AirSuction extends AirAbility {
public static double getSelectRange() {
return getConfig().getDouble("Abilities.Air.AirSuction.SelectRange");
}
}

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,19 +16,24 @@ import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.EarthAbility;
import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.firebending.Illumination;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.Flight;
public class AirSwipe extends AirAbility {
// Limiting the entities reduces the risk of crashing
private static final int MAX_AFFECTABLE_ENTITIES = 10;
private static final Integer[] BREAKABLES = {6, 31, 32, 37, 38, 39, 40, 59, 81, 83, 106, 175};
private static final Integer[] BREAKABLES = { 6, 31, 32, 37, 38, 39, 40, 59, 81, 83, 106, 175 };
private boolean charging;
private int arc;
private int particles;
@ -54,14 +50,14 @@ public class AirSwipe extends AirAbility {
private Random random;
private Map<Vector, Location> elements;
private ArrayList<Entity> affectedEntities;
public AirSwipe(Player player) {
this(player, false);
}
public AirSwipe(Player player, boolean charging) {
super(player);
if (CoreAbility.hasAbility(player, AirSwipe.class)) {
for (AirSwipe ability : CoreAbility.getAbilities(player, AirSwipe.class)) {
if (ability.charging) {
@ -71,7 +67,7 @@ public class AirSwipe extends AirAbility {
}
}
}
this.charging = charging;
this.origin = player.getEyeLocation();
this.particles = getConfig().getInt("Abilities.Air.AirSwipe.Particles");
@ -88,23 +84,28 @@ public class AirSwipe extends AirAbility {
this.random = new Random();
this.elements = new ConcurrentHashMap<>();
this.affectedEntities = new ArrayList<>();
if (bPlayer.isOnCooldown(this) || player.getEyeLocation().getBlock().isLiquid()) {
remove();
return;
}
if (!bPlayer.canBend(this)) {
remove();
return;
}
if (!charging) {
launch();
}
start();
}
/**
* This method was used for the old collision detection system. Please see
* {@link Collision} for the new system.
*/
@Deprecated
public static boolean removeSwipesAroundPoint(Location loc, double radius) {
boolean removed = false;
for (AirSwipe aswipe : getAbilities(AirSwipe.class)) {
@ -130,31 +131,15 @@ public class AirSwipe extends AirAbility {
location = location.clone().add(direction.clone().multiply(speed));
elements.put(direction, location);
if (location.distanceSquared(origin) > range * range
|| GeneralMethods.isRegionProtectedFromBuild(this, location)) {
if (location.distanceSquared(origin) > range * range || GeneralMethods.isRegionProtectedFromBuild(this, location)) {
elements.remove(direction);
} else {
removeAirSpouts(location, player);
WaterAbility.removeWaterSpouts(location, player);
EarthAbility.removeSandSpouts(location, player);
if (EarthBlast.annihilateBlasts(location, radius, player)
|| WaterManipulation.annihilateBlasts(location, radius, player)
|| FireBlast.annihilateBlasts(location, radius, player)
|| Combustion.removeAroundPoint(location, radius)) {
elements.remove(direction);
damage = 0;
remove();
continue;
}
Block block = location.getBlock();
if (!EarthAbility.isTransparent(player, block)) {
remove();
return;
}
for (Block testblock : GeneralMethods.getBlocksAroundPoint(location, radius)) {
if (testblock.getType() == Material.FIRE) {
testblock.setType(Material.AIR);
@ -193,9 +178,6 @@ public class AirSwipe extends AirAbility {
}
private void affectPeople(Location location, Vector direction) {
WaterAbility.removeWaterSpouts(location, player);
removeAirSpouts(location, player);
removeAirSpouts(location, player);
final List<Entity> entities = GeneralMethods.getEntitiesAroundPoint(location, radius);
final Vector fDirection = direction;
@ -280,12 +262,12 @@ public class AirSwipe extends AirAbility {
remove();
return;
}
if (player.isDead() || !player.isOnline()) {
remove();
return;
}
if (!charging) {
if (elements.isEmpty()) {
remove();
@ -295,12 +277,12 @@ public class AirSwipe extends AirAbility {
} else {
if (!player.isSneaking()) {
double factor = 1;
if (System.currentTimeMillis() >= startTime + maxChargeTime) {
if (System.currentTimeMillis() >= getStartTime() + maxChargeTime) {
factor = maxChargeFactor;
} else if (bPlayer.isAvatarState()) {
factor = AvatarState.getValue(factor);
} else {
factor = maxChargeFactor * (double) (System.currentTimeMillis() - startTime) / (double) maxChargeTime;
factor = maxChargeFactor * (double) (System.currentTimeMillis() - getStartTime()) / (double) maxChargeTime;
}
charging = false;
@ -308,7 +290,7 @@ public class AirSwipe extends AirAbility {
factor = Math.max(1, factor);
damage *= factor;
pushFactor *= factor;
} else if (System.currentTimeMillis() >= startTime + maxChargeTime) {
} else if (System.currentTimeMillis() >= getStartTime() + maxChargeTime) {
playAirbendingParticles(player.getEyeLocation(), particles);
}
}
@ -328,7 +310,7 @@ public class AirSwipe extends AirAbility {
public long getCooldown() {
return cooldown;
}
@Override
public boolean isSneakAbility() {
return true;
@ -339,6 +321,25 @@ public class AirSwipe extends AirAbility {
return false;
}
@Override
public boolean isCollidable() {
return origin != null;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (Location swipeLoc : elements.values()) {
locations.add(swipeLoc);
}
return locations;
}
public Location getOrigin() {
return origin;
}
@ -454,5 +455,5 @@ public class AirSwipe extends AirAbility {
public void setStepSize(int stepSize) {
this.stepSize = stepSize;
}
}

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 {
@ -54,7 +55,7 @@ public class Suffocate extends AirAbility {
private Suffocate ability;
private ArrayList<BukkitRunnable> tasks;
private ArrayList<LivingEntity> targets;
public Suffocate(Player player) {
super(player);
ability = this;
@ -131,7 +132,7 @@ public class Suffocate extends AirAbility {
targets.add((LivingEntity) target);
}
}
if (!canSuffocateUndead) {
for (int i = 0; i < targets.size(); i++) {
LivingEntity target = targets.get(i);
@ -150,10 +151,7 @@ public class Suffocate extends AirAbility {
public void progress() {
for (int i = 0; i < targets.size(); i++) {
LivingEntity target = targets.get(i);
if (target.isDead()
|| !target.getWorld().equals(player.getWorld())
|| target.getLocation().distanceSquared(player.getEyeLocation()) > range * range
|| GeneralMethods.isRegionProtectedFromBuild(this, target.getLocation())) {
if (target.isDead() || !target.getWorld().equals(player.getWorld()) || target.getLocation().distanceSquared(player.getEyeLocation()) > range * range || GeneralMethods.isRegionProtectedFromBuild(this, target.getLocation())) {
breakSuffocateLocal(target);
i--;
} else if (target instanceof Player) {
@ -171,11 +169,10 @@ public class Suffocate extends AirAbility {
if (requireConstantAim) {
double dist = 0;
if(player.getWorld().equals(targets.get(0).getWorld())) {
if (player.getWorld().equals(targets.get(0).getWorld())) {
dist = player.getEyeLocation().distance(targets.get(0).getEyeLocation());
}
Location targetLoc = player.getEyeLocation().clone()
.add(player.getEyeLocation().getDirection().normalize().multiply(dist));
Location targetLoc = player.getEyeLocation().clone().add(player.getEyeLocation().getDirection().normalize().multiply(dist));
List<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;
@ -483,7 +472,7 @@ public class Suffocate extends AirAbility {
public long getCooldown() {
return cooldown;
}
@Override
public boolean isSneakAbility() {
return true;
@ -494,6 +483,13 @@ public class Suffocate extends AirAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
locations.add(player.getLocation());
return locations;
}
public boolean isStarted() {
return started;
}

View file

@ -36,7 +36,7 @@ public class Tornado extends AirAbility {
public Tornado(Player player) {
super(player);
this.range = getConfig().getDouble("Abilities.Air.Tornado.Range");
this.origin = player.getTargetBlock((HashSet<Material>) null, (int) range).getLocation();
this.origin.setY(origin.getY() - 1.0 / 10.0 * currentHeight);
@ -77,7 +77,7 @@ public class Tornado extends AirAbility {
}
rotateTornado();
}
@Override
public void remove() {
super.remove();
@ -199,7 +199,7 @@ public class Tornado extends AirAbility {
public long getCooldown() {
return 0;
}
@Override
public boolean isSneakAbility() {
return true;
@ -210,6 +210,11 @@ public class Tornado extends AirAbility {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public Location getOrigin() {
return origin;
}

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;
@ -25,15 +27,15 @@ public class Collapse extends EarthAbility {
private Vector direction;
private Block block;
private Map<Block, Block> affectedBlocks;
public Collapse(Player player) {
super(player);
setFields();
if (!bPlayer.canBend(this) || bPlayer.isOnCooldown("CollapsePillar")) {
return;
}
block = BlockSource.getEarthSourceBlock(player, selectRange, ClickType.LEFT_CLICK);
if (block == null) {
return;
@ -83,7 +85,7 @@ public class Collapse extends EarthAbility {
private void loadAffectedBlocks() {
affectedBlocks.clear();
Block thisBlock;
for (int i = 0; i <= distance; i++) {
thisBlock = block.getWorld().getBlockAt(location.clone().add(direction.clone().multiply(-i)));
affectedBlocks.put(thisBlock, thisBlock);
@ -125,7 +127,7 @@ public class Collapse extends EarthAbility {
if (distance == 0) {
return false;
}
moveEarth(block, direction, distance);
loadAffectedBlocks();
return location.distanceSquared(origin) < distance * distance;
@ -156,6 +158,15 @@ public class Collapse extends EarthAbility {
return false;
}
@Override
public List<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 {
@ -47,7 +44,7 @@ public class EarthBlast extends EarthAbility {
public EarthBlast(Player player) {
super(player);
this.isProgressing = false;
this.isAtDestination = false;
this.isSettingUp = true;
@ -59,10 +56,10 @@ public class EarthBlast extends EarthAbility {
this.damage = getConfig().getDouble("Abilities.Earth.EarthBlast.Damage");
this.speed = getConfig().getDouble("Abilities.Earth.EarthBlast.Speed");
this.pushFactor = getConfig().getDouble("Abilities.Earth.EarthBlast.Push");
this.selectRange = getConfig().getDouble("Abilities.Earth.EarthBlast.SelectRange");
this.selectRange = getConfig().getDouble("Abilities.Earth.EarthBlast.SelectRange");
this.time = System.currentTimeMillis();
this.interval = (long) (1000.0 / speed);
if (prepare()) {
start();
time = System.currentTimeMillis();
@ -84,9 +81,7 @@ public class EarthBlast extends EarthAbility {
Location location = player.getEyeLocation();
Vector vector = location.getDirection();
Location mloc = blast.location;
if (mloc.distanceSquared(location) <= range * range
&& GeneralMethods.getDistanceFromLine(vector, location, blast.location) < deflectRange
&& mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
if (mloc.distanceSquared(location) <= range * range && GeneralMethods.getDistanceFromLine(vector, location, blast.location) < deflectRange && mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
blast.remove();
remove();
return;
@ -99,7 +94,7 @@ public class EarthBlast extends EarthAbility {
if (EarthPassive.isPassiveSand(sourceBlock)) {
EarthPassive.revertSand(sourceBlock);
}
sourceData = sourceBlock.getData();
if (sourceBlock.getType() == Material.SAND) {
sourceType = Material.SAND;
@ -107,7 +102,7 @@ public class EarthBlast extends EarthAbility {
sourceBlock.setType(Material.RED_SANDSTONE);
} else {
sourceBlock.setType(Material.SANDSTONE);
}
}
} else if (sourceBlock.getType() == Material.STEP) {
sourceBlock.setType(Material.STEP);
sourceType = Material.STEP;
@ -125,7 +120,7 @@ public class EarthBlast extends EarthAbility {
private Location getTargetLocation() {
Entity target = GeneralMethods.getTargetedEntity(player, range, new ArrayList<Entity>());
Location location;
if (target == null) {
location = GeneralMethods.getTargetedLocation(player, range);
} else {
@ -139,7 +134,7 @@ public class EarthBlast extends EarthAbility {
if (block == null || !isEarthbendable(block)) {
return false;
}
boolean selectedABlockInUse = false;
for (EarthBlast blast : getAbilities(player, EarthBlast.class)) {
if (!blast.isProgressing) {
@ -148,11 +143,11 @@ public class EarthBlast extends EarthAbility {
selectedABlockInUse = true;
}
}
if (selectedABlockInUse) {
return false;
}
checkForCollision();
if (block.getLocation().distanceSquared(player.getLocation()) > selectRange * selectRange) {
return false;
@ -169,7 +164,7 @@ public class EarthBlast extends EarthAbility {
remove();
return;
}
if (System.currentTimeMillis() - time >= interval) {
time = System.currentTimeMillis();
@ -213,8 +208,8 @@ public class EarthBlast extends EarthAbility {
}
location = location.clone().add(direction);
Block block = location.getBlock();
Block block = location.getBlock();
if (block.getLocation().equals(sourceBlock.getLocation())) {
location = location.clone().add(direction);
block = location.getBlock();
@ -229,19 +224,6 @@ public class EarthBlast extends EarthAbility {
location = location.clone().subtract(direction);
direction = GeneralMethods.getDirection(location, destination).normalize();
location = location.clone().add(direction);
WaterAbility.removeWaterSpouts(location, player);
AirAbility.removeAirSpouts(location, player);
EarthAbility.removeSandSpouts(location, player);
if (EarthBlast.annihilateBlasts(location, collisionRadius, player)
|| WaterManipulation.annihilateBlasts(location, collisionRadius, player)
|| FireBlast.annihilateBlasts(location, collisionRadius, player)) {
remove();
return;
}
Combustion.removeAroundPoint(location, collisionRadius);
Block block2 = location.getBlock();
if (block2.getLocation().equals(sourceBlock.getLocation())) {
@ -263,12 +245,12 @@ public class EarthBlast extends EarthAbility {
}
if (entity instanceof LivingEntity && (entity.getEntityId() != player.getEntityId() || canHitSelf)) {
AirAbility.breakBreathbendingHold(entity);
Location location = player.getEyeLocation();
Vector vector = location.getDirection();
entity.setVelocity(vector.normalize().multiply(pushFactor));
double damage = this.damage;
double damage = this.damage;
if (isMetal(sourceBlock) && bPlayer.canMetalbend()) {
damage = getMetalAugment(damage);
}
@ -290,7 +272,7 @@ public class EarthBlast extends EarthAbility {
}
moveEarthBlock(sourceBlock, block);
if (block.getType() == Material.SAND) {
block.setType(Material.SANDSTONE);
}
@ -311,8 +293,7 @@ public class EarthBlast extends EarthAbility {
sourceType = Material.SAND;
sourceBlock.setType(sourceType);
sourceBlock.setData((byte) 0x1);
}
else {
} else {
sourceBlock.setType(sourceType);
}
}
@ -338,7 +319,7 @@ public class EarthBlast extends EarthAbility {
@Override
public void remove() {
super.remove();
if(destination != null && sourceBlock != null) {
if (destination != null && sourceBlock != null) {
sourceBlock.setType(Material.AIR);
} else if (sourceBlock != null) {
if (sourceBlock.getType() == Material.SAND) {
@ -360,13 +341,13 @@ public class EarthBlast extends EarthAbility {
if (sourceBlock == null || !sourceBlock.getWorld().equals(player.getWorld())) {
return;
}
if (getMovedEarth().containsKey(sourceBlock)) {
if (!isEarthRevertOn()) {
removeRevertIndex(sourceBlock);
}
}
Entity target = GeneralMethods.getTargetedEntity(player, range, new ArrayList<Entity>());
if (target == null) {
destination = getTargetEarthBlock((int) range).getLocation();
@ -378,12 +359,12 @@ public class EarthBlast extends EarthAbility {
firstDestination.setY(destination.getY());
destination = GeneralMethods.getPointOnLine(firstDestination, destination, range);
}
if (destination.distanceSquared(location) <= 1) {
isProgressing = false;
destination = null;
} else {
isProgressing = true;
isProgressing = true;
playEarthbendingSound(sourceBlock.getLocation());
Material currentType = sourceBlock.getType();
@ -393,11 +374,16 @@ public class EarthBlast extends EarthAbility {
addTempAirBlock(sourceBlock);
} else {
sourceBlock.breakNaturally();
}
}
sourceBlock.setType(currentType);
}
}
/**
* This method was used for the old collision detection system. Please see
* {@link Collision} for the new system.
*/
@Deprecated
public static boolean annihilateBlasts(Location location, double radius, Player source) {
boolean broke = false;
for (EarthBlast blast : getAbilities(EarthBlast.class)) {
@ -409,7 +395,7 @@ public class EarthBlast extends EarthAbility {
}
}
return broke;
}
}
public static ArrayList<EarthBlast> getAroundPoint(Location location, double radius) {
ArrayList<EarthBlast> list = new ArrayList<EarthBlast>();
@ -447,11 +433,8 @@ public class EarthBlast extends EarthAbility {
Location location = player.getEyeLocation();
Vector vector = location.getDirection();
Location mloc = blast.location;
if (mloc.distanceSquared(location) <= blast.range * blast.range
&& GeneralMethods.getDistanceFromLine(vector, location, blast.location) < blast.deflectRange
&& mloc.distanceSquared(location.clone().add(vector))
< mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
if (mloc.distanceSquared(location) <= blast.range * blast.range && GeneralMethods.getDistanceFromLine(vector, location, blast.location) < blast.deflectRange && mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
blast.redirect(player, blast.getTargetLocation());
}
@ -472,11 +455,11 @@ public class EarthBlast extends EarthAbility {
ArrayList<EarthBlast> ignore = new ArrayList<EarthBlast>();
BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
EarthBlast earthBlast = null;
if (bPlayer == null) {
return;
}
for (EarthBlast blast : getAbilities(player, EarthBlast.class)) {
if (!blast.isProgressing && bPlayer.canBend(blast)) {
blast.throwEarth();
@ -505,7 +488,7 @@ public class EarthBlast extends EarthAbility {
public long getCooldown() {
return cooldown;
}
@Override
public boolean isSneakAbility() {
return true;
@ -516,6 +499,16 @@ public class EarthBlast extends EarthAbility {
return false;
}
@Override
public boolean isCollidable() {
return isProgressing;
}
@Override
public double getCollisionRadius() {
return collisionRadius;
}
public boolean isProgressing() {
return isProgressing;
}
@ -612,10 +605,6 @@ public class EarthBlast extends EarthAbility {
this.deflectRange = deflectRange;
}
public double getCollisionRadius() {
return collisionRadius;
}
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}
@ -660,4 +649,4 @@ public class EarthBlast extends EarthAbility {
this.location = location;
}
}
}

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,12 +13,16 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.EarthAbility;
import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
public class EarthSmash extends EarthAbility {
public static enum State {
START, LIFTING, LIFTED, GRABBED, SHOT, FLYING, REMOVED
}
@ -64,7 +62,7 @@ public class EarthSmash extends EarthAbility {
public EarthSmash(Player player, ClickType type) {
super(player);
this.state = State.START;
this.requiredBendableBlocks = getConfig().getInt("Abilities.Earth.EarthSmash.RequiredBendableBlocks");
this.maxBlocksToPassThrough = getConfig().getInt("Abilities.Earth.EarthSmash.MaxBlocksToPassThrough");
@ -89,7 +87,7 @@ public class EarthSmash extends EarthAbility {
this.affectedEntities = new ArrayList<>();
this.currentBlocks = new ArrayList<>();
this.affectedBlocks = new ArrayList<>();
if (type == ClickType.SHIFT_DOWN || type == ClickType.SHIFT_UP && !player.isSneaking()) {
if (bPlayer.isAvatarState()) {
selectRange = AvatarState.getValue(selectRange);
@ -119,17 +117,17 @@ public class EarthSmash extends EarthAbility {
}
grabbedSmash = aimingAtSmashCheck(player, State.SHOT);
}
if (grabbedSmash != null) {
grabbedSmash.state = State.GRABBED;
grabbedSmash.grabbedDistance = 0;
if(grabbedSmash.location.getWorld().equals(player.getWorld())) {
if (grabbedSmash.location.getWorld().equals(player.getWorld())) {
grabbedSmash.grabbedDistance = grabbedSmash.location.distance(player.getEyeLocation());
}
grabbedSmash.player = player;
return;
}
start();
} else if (type == ClickType.LEFT_CLICK && player.isSneaking()) {
for (EarthSmash smash : getAbilities(EarthSmash.class)) {
@ -155,11 +153,11 @@ public class EarthSmash extends EarthAbility {
@Override
public void progress() {
progressCounter++;
if (state == State.LIFTED && removeTimer > 0 && System.currentTimeMillis() - startTime > removeTimer) {
if (state == State.LIFTED && removeTimer > 0 && System.currentTimeMillis() - getStartTime() > removeTimer) {
remove();
return;
}
if (state == State.START) {
if (!bPlayer.canBend(this)) {
remove();
@ -174,7 +172,7 @@ public class EarthSmash extends EarthAbility {
if (state == State.START && progressCounter > 1) {
if (!player.isSneaking()) {
if (System.currentTimeMillis() - startTime >= chargeTime) {
if (System.currentTimeMillis() - getStartTime() >= chargeTime) {
origin = getEarthSourceBlock(selectRange);
if (origin == null) {
remove();
@ -187,7 +185,7 @@ public class EarthSmash extends EarthAbility {
remove();
return;
}
} else if (System.currentTimeMillis() - startTime > chargeTime) {
} else if (System.currentTimeMillis() - getStartTime() > chargeTime) {
Location tempLoc = player.getEyeLocation().add(player.getEyeLocation().getDirection().normalize().multiply(1.2));
tempLoc.add(0, 0.3, 0);
ParticleEffect.SMOKE.display(tempLoc, 0.3F, 0.1F, 0.3F, 0, 4);
@ -210,10 +208,7 @@ public class EarthSmash extends EarthAbility {
break;
}
}
WaterAbility.removeWaterSpouts(location, 2, player);
AirAbility.removeAirSpouts(location, 2, player);
EarthAbility.removeSandSpouts(location, player);
draw();
return;
} else {
@ -227,20 +222,18 @@ public class EarthSmash extends EarthAbility {
remove();
return;
}
revert();
location.add(GeneralMethods.getDirection(location, destination).normalize().multiply(1));
if (location.distanceSquared(destination) < 4) {
remove();
return;
}
// If an earthsmash runs into too many blocks we should remove it
int badBlocksFound = 0;
for (Block block : getBlocks()) {
if (block.getType() != Material.AIR && (!isTransparent(block)
|| block.getType() == Material.WATER
|| block.getType() == Material.STATIONARY_WATER)) {
if (block.getType() != Material.AIR && (!isTransparent(block) || block.getType() == Material.WATER || block.getType() == Material.STATIONARY_WATER)) {
badBlocksFound++;
}
}
@ -249,8 +242,6 @@ public class EarthSmash extends EarthAbility {
remove();
return;
}
WaterAbility.removeWaterSpouts(location, 2, player);
AirAbility.removeAirSpouts(location, 2, player);
shootingCollisionDetection();
draw();
smashToSmashCollisionDetection();
@ -298,10 +289,10 @@ public class EarthSmash extends EarthAbility {
/**
* Begins animating the EarthSmash from the ground. The lift animation
* consists of 3 steps, and each one has to design the shape in the
* ground that removes the Earthbendable material. We also need to make
* sure that there is a clear path for the EarthSmash to rise, and that
* there is enough Earthbendable material for it to be created.
* consists of 3 steps, and each one has to design the shape in the ground
* that removes the Earthbendable material. We also need to make sure that
* there is a clear path for the EarthSmash to rise, and that there is
* enough Earthbendable material for it to be created.
*/
@SuppressWarnings("deprecation")
public void animateLift() {
@ -368,7 +359,7 @@ public class EarthSmash extends EarthAbility {
}
}
}
/*
* We needed to calculate all of the blocks based on the
* location being 1 above the initial bending block, however we
@ -424,14 +415,13 @@ public class EarthSmash extends EarthAbility {
}
/**
* Checks to see which of the blocks are still attached to the
* EarthSmash, remember that blocks can be broken or used in other
* abilities so we need to double check and remove any that are not
* still attached.
* Checks to see which of the blocks are still attached to the EarthSmash,
* remember that blocks can be broken or used in other abilities so we need
* to double check and remove any that are not still attached.
*
* Also when we remove the blocks from instances, movedearth, or tempair
* we should do it on a delay because tempair takes a couple seconds
* before the block shows up in that map.
* Also when we remove the blocks from instances, movedearth, or tempair we
* should do it on a delay because tempair takes a couple seconds before the
* block shows up in that map.
*/
public void checkRemainingBlocks() {
for (int i = 0; i < currentBlocks.size(); i++) {
@ -452,9 +442,8 @@ public class EarthSmash extends EarthAbility {
}
/**
* Gets the blocks surrounding the EarthSmash's loc. This method ignores
* the blocks that should be Air, and only returns the ones that are
* dirt.
* Gets the blocks surrounding the EarthSmash's loc. This method ignores the
* blocks that should be Air, and only returns the ones that are dirt.
*/
public List<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>();
@ -489,7 +478,7 @@ public class EarthSmash extends EarthAbility {
}
return blocks;
}
/**
* Switches the Sand Material and Gravel to SandStone and stone
* respectively, since gravel and sand cannot be bent due to gravity.
@ -516,17 +505,16 @@ public class EarthSmash extends EarthAbility {
}
return tempMat;
}
/**
* Determines if a player is trying to grab an EarthSmash. A player is
* trying to grab an EarthSmash if they are staring at it and holding
* shift.
* trying to grab an EarthSmash if they are staring at it and holding shift.
*/
private EarthSmash aimingAtSmashCheck(Player player, State reqState) {
if (!allowGrab) {
return null;
}
List<Block> blocks = GeneralMethods.getBlocksAroundPoint(GeneralMethods.getTargetedLocation(player, grabRange, GeneralMethods.NON_OPAQUE), 1);
for (EarthSmash smash : getAbilities(EarthSmash.class)) {
if (reqState == null || smash.state == reqState) {
@ -534,8 +522,7 @@ public class EarthSmash extends EarthAbility {
if (block == null || smash.getLocation() == null) {
continue;
}
if (block.getLocation().getWorld() == smash.location.getWorld()
&& block.getLocation().distanceSquared(smash.location) <= Math.pow(grabDetectionRadius, 2)) {
if (block.getLocation().getWorld() == smash.location.getWorld() && block.getLocation().distanceSquared(smash.location) <= Math.pow(grabDetectionRadius, 2)) {
return smash;
}
}
@ -546,8 +533,8 @@ public class EarthSmash extends EarthAbility {
/**
* This method handles any collision between an EarthSmash and the
* surrounding entities, the method only applies to earthsmashes that
* have already been shot.
* surrounding entities, the method only applies to earthsmashes that have
* already been shot.
*/
public void shootingCollisionDetection() {
List<Entity> entities = GeneralMethods.getEntitiesAroundPoint(location, flightDetectionRadius);
@ -561,28 +548,27 @@ public class EarthSmash extends EarthAbility {
}
}
}
/**
* EarthSmash to EarthSmash collision can only happen when one of the
* Smashes have been shot by a player. If we find out that one of them
* have collided then we want to return since a smash can only remove 1
* at a time.
* Smashes have been shot by a player. If we find out that one of them have
* collided then we want to return since a smash can only remove 1 at a
* time.
*/
public void smashToSmashCollisionDetection() {
for (EarthSmash smash : getAbilities(EarthSmash.class)) {
if (smash.location != null && smash != this && smash.location.getWorld() == location.getWorld()
&& smash.location.distanceSquared(location) < Math.pow(flightDetectionRadius, 2)) {
if (smash.location != null && smash != this && smash.location.getWorld() == location.getWorld() && smash.location.distanceSquared(location) < Math.pow(flightDetectionRadius, 2)) {
smash.remove();
remove();
return;
}
}
}
/**
* Determines whether or not a player is trying to fly ontop of an
* EarthSmash. A player is considered "flying" if they are standing
* ontop of the earthsmash and holding shift.
* EarthSmash. A player is considered "flying" if they are standing ontop of
* the earthsmash and holding shift.
*/
private static EarthSmash flyingInSmashCheck(Player player) {
for (EarthSmash smash : getAbilities(EarthSmash.class)) {
@ -591,8 +577,7 @@ public class EarthSmash extends EarthAbility {
}
//Check to see if the player is standing on top of the smash.
if (smash.state == State.LIFTED) {
if (smash.location.getWorld().equals(player.getWorld())
&& smash.location.clone().add(0, 2, 0).distanceSquared(player.getLocation()) <= Math.pow(smash.flightDetectionRadius, 2)) {
if (smash.location.getWorld().equals(player.getWorld()) && smash.location.clone().add(0, 2, 0).distanceSquared(player.getLocation()) <= Math.pow(smash.flightDetectionRadius, 2)) {
return smash;
}
}
@ -601,12 +586,11 @@ public class EarthSmash extends EarthAbility {
}
/**
* A BlockRepresenter is used to keep track of each of the individual
* types of blocks that are attached to an EarthSmash. Without the
* representer then an EarthSmash can only be made up of 1 material at a
* time. For example, an ESmash that is entirely dirt, coalore, or
* sandstone. Using the representer will allow all the materials to be
* mixed together.
* A BlockRepresenter is used to keep track of each of the individual types
* of blocks that are attached to an EarthSmash. Without the representer
* then an EarthSmash can only be made up of 1 material at a time. For
* example, an ESmash that is entirely dirt, coalore, or sandstone. Using
* the representer will allow all the materials to be mixed together.
*/
public class BlockRepresenter {
private int x, y, z;
@ -706,7 +690,7 @@ public class EarthSmash extends EarthAbility {
public long getCooldown() {
return cooldown;
}
@Override
public boolean isSneakAbility() {
return true;
@ -717,6 +701,15 @@ public class EarthSmash extends EarthAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (TempBlock tblock : affectedBlocks) {
locations.add(tblock.getLocation());
}
return locations;
}
public boolean isAllowGrab() {
return allowGrab;
}
@ -836,7 +829,7 @@ public class EarthSmash extends EarthAbility {
public void setGrabRange(double grabRange) {
this.grabRange = grabRange;
}
public double getSelectRange() {
return selectRange;
}

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;
@ -16,7 +18,7 @@ import com.projectkorra.projectkorra.configuration.ConfigManager;
import com.projectkorra.projectkorra.util.TempBlock;
public class EarthTunnel extends EarthAbility {
private long interval;
private long time;
private double depth;
@ -32,10 +34,10 @@ public class EarthTunnel extends EarthAbility {
private Vector direction;
public static Map<TempBlock, Long> airBlocks = new ConcurrentHashMap<TempBlock, Long>();
public EarthTunnel(Player player) {
super(player);
this.maxRadius = getConfig().getDouble("Abilities.Earth.EarthTunnel.MaxRadius");
this.range = getConfig().getDouble("Abilities.Earth.EarthTunnel.Range");
this.radius = getConfig().getDouble("Abilities.Earth.EarthTunnel.Radius");
@ -43,21 +45,21 @@ public class EarthTunnel extends EarthAbility {
this.revert = getConfig().getBoolean("Abilities.Earth.EarthTunnel.Revert");
this.radiusIncrement = radius;
this.time = System.currentTimeMillis();
this.location = player.getEyeLocation().clone();
this.origin = player.getTargetBlock((HashSet<Material>) null, (int) range).getLocation();
this.block = origin.getBlock();
this.direction = location.getDirection().clone().normalize();
this.depth = 0;
if(origin.getWorld().equals(location.getWorld())) {
this.depth = Math.max(0, origin.distance(location) - 1);
if (origin.getWorld().equals(location.getWorld())) {
this.depth = Math.max(0, origin.distance(location) - 1);
}
this.angle = 0;
if (!bPlayer.canBend(this)) {
return;
}
start();
}
@ -67,7 +69,7 @@ public class EarthTunnel extends EarthAbility {
remove();
return;
}
if (System.currentTimeMillis() - time >= interval) {
time = System.currentTimeMillis();
if (Math.abs(Math.toDegrees(player.getEyeLocation().getDirection().angle(direction))) > 20 || !player.isSneaking()) {
@ -79,7 +81,7 @@ public class EarthTunnel extends EarthAbility {
remove();
return;
}
if (angle >= 360) {
angle = 0;
if (radius >= maxRadius) {
@ -96,11 +98,11 @@ public class EarthTunnel extends EarthAbility {
} else {
angle += 20;
}
Vector vec = GeneralMethods.getOrthogonalVector(direction, angle, radius);
block = location.clone().add(direction.clone().normalize().multiply(depth)).add(vec).getBlock();
}
if (revert) {
if (getMovedEarth().containsKey(block)) {
block.setType(Material.AIR);
@ -128,7 +130,7 @@ public class EarthTunnel extends EarthAbility {
public long getCooldown() {
return 0;
}
@Override
public boolean isSneakAbility() {
return true;
@ -139,6 +141,15 @@ public class EarthTunnel extends EarthAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (TempBlock tblock : airBlocks.keySet()) {
locations.add(tblock.getLocation());
}
return locations;
}
public long getInterval() {
return interval;
}
@ -230,7 +241,7 @@ public class EarthTunnel extends EarthAbility {
public void setLocation(Location location) {
this.location = location;
}
public static void revertAirBlocks() {
if (ConfigManager.defaultConfig.get().getBoolean("Abilities.Earth.EarthTunnel.Revert")) {
for (TempBlock tempBlock : EarthTunnel.airBlocks.keySet()) {
@ -241,5 +252,5 @@ public class EarthTunnel extends EarthAbility {
}
}
}
}

View file

@ -18,12 +18,13 @@ import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
public class LavaFlow extends LavaAbility {
public static enum AbilityType {
SHIFT, CLICK
}
@ -31,7 +32,7 @@ public class LavaFlow extends LavaAbility {
private static final Map<Block, TempBlock> TEMP_LAVA_BLOCKS = new ConcurrentHashMap<>();
private static final Map<Block, TempBlock> TEMP_LAND_BLOCKS = new ConcurrentHashMap<>();
private static final Map<Block, TempBlock> TEMP_AIR_BLOCKS = new ConcurrentHashMap<>();
private boolean removing;
private boolean makeLava;
private boolean clickIsFinished;
@ -66,7 +67,7 @@ public class LavaFlow extends LavaAbility {
private ArrayList<TempBlock> affectedBlocks;
private ArrayList<BukkitRunnable> tasks;
private Material revertMaterial;
/**
* Creates a new LavaFlow ability and initializes all of the variables and
* cooldowns. The ability is not guaranteed to continue, it may be the case
@ -155,7 +156,7 @@ public class LavaFlow extends LavaAbility {
remove();
return;
}
long cooldown = makeLava ? clickLavaCooldown : clickLandCooldown;
origin = sourceBlock.getLocation();
makeLava = !isLava(sourceBlock);
@ -187,7 +188,7 @@ public class LavaFlow extends LavaAbility {
}
Random random = new Random();
if (type == AbilityType.SHIFT) {
if (System.currentTimeMillis() - time > shiftRemoveDelay) {
remove();
@ -249,23 +250,20 @@ public class LavaFlow extends LavaAbility {
createLava(block);
}
}
}
} else if (Math.random() < particleDensity
&& dSquared < Math.pow(currentRadius + particleDensity, 2)
&& currentRadius + particleDensity < shiftMaxRadius
&& random.nextInt(3) == 0) {
} else if (Math.random() < particleDensity && dSquared < Math.pow(currentRadius + particleDensity, 2) && currentRadius + particleDensity < shiftMaxRadius && random.nextInt(3) == 0) {
ParticleEffect.LAVA.display(loc, (float) Math.random(), (float) Math.random(), (float) Math.random(), 0, 1);
}
}
}
if(!shiftIsFinished) {
if (!shiftIsFinished) {
if (random.nextInt(10) == 0) {
ParticleEffect.LAVA.display(player.getLocation(), (float) Math.random(), (float) Math.random(), (float) Math.random(), 0, 1);
}
}
currentRadius += shiftFlowSpeed;
if (currentRadius > shiftMaxRadius) {
currentRadius = shiftMaxRadius;
@ -274,16 +272,17 @@ public class LavaFlow extends LavaAbility {
}
} else if (type == AbilityType.CLICK) {
/*
* The variable makeLava refers to whether or not the ability is trying
* to remove land in place of lava or if makeLava = false then lava is
* being replaced with land.
* The variable makeLava refers to whether or not the ability is
* trying to remove land in place of lava or if makeLava = false
* then lava is being replaced with land.
*
* Notice we have separate variables between both versions, because most
* of the time making lava will have longer delays and longer cooldowns.
* Notice we have separate variables between both versions, because
* most of the time making lava will have longer delays and longer
* cooldowns.
*/
long curTime = System.currentTimeMillis() - time;
double delay = makeLava ? clickLavaDelay : clickLandDelay;
if (makeLava && curTime > clickLavaCleanupDelay) {
remove();
return;
@ -297,9 +296,8 @@ public class LavaFlow extends LavaAbility {
for (double z = -clickLavaRadius; z <= clickLavaRadius; z++) {
Location loc = origin.clone().add(x, 0, z);
Block tempBlock = GeneralMethods.getTopBlock(loc, upwardFlow, downwardFlow);
if (tempBlock != null && !isLava(tempBlock) && Math.random() < particleDensity
&& tempBlock.getLocation().distanceSquared(origin) <= Math.pow(clickLavaRadius, 2)) {
if (tempBlock != null && !isLava(tempBlock) && Math.random() < particleDensity && tempBlock.getLocation().distanceSquared(origin) <= Math.pow(clickLavaRadius, 2)) {
if (random.nextInt(3) == 0) {
ParticleEffect.LAVA.display(loc, (float) Math.random(), (float) Math.random(), (float) Math.random(), 0, 1);
}
@ -317,7 +315,7 @@ public class LavaFlow extends LavaAbility {
if (!clickIsFinished) {
clickIsFinished = true;
double radius = makeLava ? clickLavaRadius : clickLandRadius;
for (double x = -radius; x <= radius; x++) {
for (double z = -radius; z <= radius; z++) {
Location loc = origin.clone().add(x, 0, z);
@ -398,14 +396,15 @@ public class LavaFlow extends LavaAbility {
TempBlock tb = new TempBlock(above, Material.AIR, (byte) 0);
TEMP_AIR_BLOCKS.put(above, tb);
affectedBlocks.add(tb);
} else return;
}
} else
return;
}
TempBlock tblock = new TempBlock(block, Material.LAVA, (byte) 0);
TEMP_LAVA_BLOCKS.put(block, tblock);
affectedBlocks.add(tblock);
if (allowNaturalFlow) {
// ProjectKorra.plugin.getLogger().info("Flow free!");
// ProjectKorra.plugin.getLogger().info("Flow free!");
TempBlock.removeBlock(block);
}
}
@ -469,7 +468,7 @@ public class LavaFlow extends LavaAbility {
tblock.getBlock().getRelative(BlockFace.UP).setType(Material.DOUBLE_PLANT);
tblock.getBlock().getRelative(BlockFace.UP).setData((byte) (tblock.getState().getRawData() + 8));
}
}
}.runTaskLater(ProjectKorra.plugin, (long) (i / shiftRemoveSpeed));
@ -515,7 +514,6 @@ public class LavaFlow extends LavaAbility {
task.cancel();
}
}
/**
* Returns a list of all the Lava blocks that are adjacent to the block at
@ -546,7 +544,7 @@ public class LavaFlow extends LavaAbility {
public static ArrayList<Block> getAdjacentBlocks(Location loc) {
ArrayList<Block> list = new ArrayList<Block>();
Block block = loc.getBlock();
for (int x = -1; x <= 1; x++) {
for (int y = -2; y <= 1; y++) {
for (int z = -1; z <= 1; z++) {
@ -594,18 +592,18 @@ public class LavaFlow extends LavaAbility {
}
return list;
}
public static Material getRevertMaterial() {
Material m = Material.STONE;
LavaFlow lf = (LavaFlow) CoreAbility.getAbility("LavaFlow");
m = lf.revertMaterial;
return m;
}
public static Map<Block, TempBlock> getTempLandBlocks() {
return TEMP_LAND_BLOCKS;
}
public static Map<Block, TempBlock> getTempLavaBlocks() {
return TEMP_LAVA_BLOCKS;
}
@ -629,7 +627,7 @@ public class LavaFlow extends LavaAbility {
public long getCooldown() {
return type == AbilityType.CLICK ? clickLandCooldown : shiftCooldown;
}
@Override
public boolean isSneakAbility() {
return true;
@ -640,6 +638,15 @@ public class LavaFlow extends LavaAbility {
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (TempBlock tblock : affectedBlocks) {
locations.add(tblock.getLocation());
}
return locations;
}
public boolean isRemoving() {
return removing;
}
@ -895,5 +902,5 @@ public class LavaFlow extends LavaAbility {
public ArrayList<BukkitRunnable> getTasks() {
return tasks;
}
}

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;
@ -178,6 +180,15 @@ public class RaiseEarth extends EarthAbility {
public boolean isHarmlessAbility() {
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 {
@ -259,6 +261,20 @@ public class SandSpout extends SandAbility {
public boolean isHarmlessAbility() {
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())) {
@ -176,6 +182,11 @@ public class Combustion extends CombustionAbility {
public boolean isHarmlessAbility() {
return false;
}
@Override
public double getCollisionRadius() {
return getRadius();
}
public boolean isBreakBlocks() {
return breakBlocks;

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)) {
@ -284,6 +274,11 @@ public class FireBlast extends FireAbility {
public boolean isHarmlessAbility() {
return false;
}
@Override
public double getCollisionRadius() {
return collisionRadius;
}
public boolean isPowerFurnace() {
return powerFurnace;
@ -349,10 +344,6 @@ public class FireBlast extends FireAbility {
this.speed = speed;
}
public double getCollisionRadius() {
return collisionRadius;
}
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}

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) {
@ -320,6 +320,16 @@ public class FireBlastCharged extends FireAbility {
public boolean isHarmlessAbility() {
return false;
}
@Override
public boolean isCollidable() {
return this.launched;
}
@Override
public double getCollisionRadius() {
return collisionRadius;
}
public boolean isCharged() {
return charged;
@ -393,10 +403,6 @@ public class FireBlastCharged extends FireAbility {
this.range = range;
}
public double getCollisionRadius() {
return collisionRadius;
}
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}

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,26 +30,11 @@ import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect;
/*
* TODO: Combo classes should eventually be rewritten so that each combo is treated
* as an individual ability. In the mean time, we will just place "fake"
* classes so that CoreAbility will register each ability.
* TODO: Combo classes should eventually be rewritten so that each combo is
* treated as an individual ability. In the mean time, we will just place "fake"
* classes so that CoreAbility will register each ability.
*/
public class FireCombo extends FireAbility implements ComboAbility {
private static final ArrayList<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;
@ -70,20 +55,20 @@ public class FireCombo extends FireAbility implements ComboAbility {
private Vector direction;
private ArrayList<LivingEntity> affectedEntities;
private ArrayList<FireComboStream> tasks;
public FireCombo(Player player, String ability) {
super(player);
this.ability = ability;
if (!bPlayer.canBendIgnoreBindsCooldowns(this)) {
return;
}
this.firstTime = true;
this.time = System.currentTimeMillis();
this.affectedEntities = new ArrayList<>();
this.tasks = new ArrayList<>();
if (ability.equalsIgnoreCase("FireKick")) {
this.damage = getConfig().getDouble("Abilities.Fire.FireCombo.FireKick.Damage");
this.range = getConfig().getDouble("Abilities.Fire.FireCombo.FireKick.Range");
@ -112,7 +97,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
this.cooldown = getConfig().getLong("Abilities.Fire.FireCombo.JetBlaze.Cooldown");
this.fireTicks = getConfig().getDouble("Abilities.Fire.FireCombo.JetBlaze.FireTicks");
}
if (bPlayer.isAvatarState()) {
this.cooldown = 0;
this.damage = AvatarState.getValue(damage);
@ -121,10 +106,9 @@ public class FireCombo extends FireAbility implements ComboAbility {
start();
}
/**
* Returns all of the FireCombos created by a specific player but filters the abilities based on
* shift or click.
* Returns all of the FireCombos created by a specific player but filters
* the abilities based on shift or click.
*/
public static ArrayList<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;
@ -227,7 +213,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
}
}
}
if (!bPlayer.canBendIgnoreBindsCooldowns(this)) {
remove();
return;
@ -239,7 +225,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
remove();
return;
}
bPlayer.addCooldown("FireKick", cooldown);
Vector eyeDir = player.getEyeLocation().getDirection().normalize().multiply(range);
destination = player.getEyeLocation().add(eyeDir);
@ -262,17 +248,10 @@ public class FireCombo extends FireAbility implements ComboAbility {
player.getWorld().playSound(player.getLocation(), Sound.ITEM_FLINTANDSTEEL_USE, 0.5f, 1f);
}
location = tasks.get(0).getLocation();
for (FireComboStream stream : tasks) {
if (GeneralMethods.blockAbilities(player, BLOCKABLE_ABILITIES, stream.location, 2)) {
stream.remove();
}
}
} else if (tasks.size() == 0) {
remove();
return;
} AirAbility.removeAirSpouts(location, player);
WaterAbility.removeWaterSpouts(location, player);
EarthAbility.removeSandSpouts(location, player);
}
} else if (ability.equalsIgnoreCase("FireSpin")) {
if (destination == null) {
if (bPlayer.isOnCooldown("FireSpin") && !bPlayer.isAvatarState()) {
@ -299,20 +278,11 @@ public class FireCombo extends FireAbility implements ComboAbility {
tasks.add(fs);
}
}
if (tasks.size() == 0) {
remove();
return;
}
for (FireComboStream stream : tasks) {
if (isWithinFireShield(stream.getLocation())) {
stream.remove();
}
if (AirAbility.isWithinAirShield(stream.getLocation())) {
stream.remove();
}
}
} else if (ability.equalsIgnoreCase("JetBlast")) {
if (System.currentTimeMillis() - time > 5000) {
remove();
@ -323,7 +293,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
remove();
return;
}
bPlayer.addCooldown("JetBlast", cooldown);
firstTime = false;
float spread = 0F;
@ -332,9 +302,8 @@ public class FireCombo extends FireAbility implements ComboAbility {
}
FireJet fj = getAbility(player, FireJet.class);
fj.setSpeed(speed);
FireComboStream fs = new FireComboStream(this,
player.getVelocity().clone().multiply(-1), player.getLocation(), 3, 0.5, "JetBlast");
FireComboStream fs = new FireComboStream(this, player.getVelocity().clone().multiply(-1), player.getLocation(), 3, 0.5, "JetBlast");
fs.setDensity(1);
fs.setSpread(0.9F);
fs.setUseNewParticles(true);
@ -404,7 +373,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
}
location.setY(topBlock.getY() + height);
FireComboStream fs = new FireComboStream(this, direction, location.clone().add(0, -1, 0), 5, 1, "FireWheel");
fs.setDensity(0);
fs.setSinglePoint(true);
fs.setCollisionRadius(1.5);
@ -422,16 +391,12 @@ public class FireCombo extends FireAbility implements ComboAbility {
location = location.add(direction.clone().multiply(speed));
location.getWorld().playSound(location, Sound.BLOCK_FIRE_AMBIENT, 1, 1);
if (GeneralMethods.blockAbilities(player, BLOCKABLE_ABILITIES, location, 2)) {
remove();
return;
}
}
}
/**
* Removes this instance of FireCombo, cleans up any blocks that are remaining in totalBlocks,
* and cancels any remaining tasks.
* Removes this instance of FireCombo, cleans up any blocks that are
* remaining in totalBlocks, and cancels any remaining tasks.
*/
@Override
public void remove() {
@ -470,7 +435,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
this.checkCollisionCounter = 0;
this.spread = 0;
this.collisionRadius = 2;
this.particleEffect = ParticleEffect.FLAME;
this.particleEffect = ParticleEffect.FLAME;
this.fireCombo = fireCombo;
this.direction = direction;
this.speed = speed;
@ -479,7 +444,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
this.distance = distance;
this.ability = ability;
}
@Override
public void run() {
Block block = location.getBlock();
@ -506,7 +471,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
}
}
}
checkCollisionCounter++;
if (singlePoint) {
remove();
@ -586,7 +551,7 @@ public class FireCombo extends FireAbility implements ComboAbility {
public long getCooldown() {
return cooldown;
}
@Override
public boolean isSneakAbility() {
return true;
@ -596,7 +561,22 @@ public class FireCombo extends FireAbility implements ComboAbility {
public boolean isHarmlessAbility() {
return false;
}
@Override
public boolean isCollidable() {
// Override in subclasses
return false;
}
@Override
public List<Location> getLocations() {
ArrayList<Location> locations = new ArrayList<>();
for (FireComboStream stream : tasks) {
locations.add(stream.getLocation());
}
return locations;
}
@Override
public String getInstructions() {
return null;
@ -611,7 +591,25 @@ public class FireCombo extends FireAbility implements ComboAbility {
public ArrayList<AbilityInformation> getCombination() {
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;
}
@ -755,65 +753,91 @@ public class FireCombo extends FireAbility implements ComboAbility {
public void setLocation(Location location) {
this.location = location;
}
public class FireKick extends FireCombo {
public FireKick(Player player, String name) {
// Combo subclasses need to be static to be reflectively called in ComboManager
public static class FireKick extends FireCombo {
public FireKick(Player player) {
super(player, "FireKick");
}
@Override
public String getName() {
return "FireKick";
}
}
public class FireSpin extends FireCombo {
public FireSpin(Player player, String name) {
@Override
public boolean isCollidable() {
return true;
}
@Override
public void handleCollision(Collision collision) {
handleCollisionFireStreams(collision);
}
}
public static class FireSpin extends FireCombo {
public FireSpin(Player player) {
super(player, "FireSpin");
}
@Override
public String getName() {
return "FireSpin";
}
}
public class FireWheel extends FireCombo {
public FireWheel(Player player, String name) {
@Override
public boolean isCollidable() {
return true;
}
@Override
public void handleCollision(Collision collision) {
handleCollisionFireStreams(collision);
}
}
public static class FireWheel extends FireCombo {
public FireWheel(Player player) {
super(player, "FireWheel");
}
@Override
public String getName() {
return "FireWheel";
}
}
public class JetBlast extends FireCombo {
public JetBlast(Player player, String name) {
@Override
public boolean isCollidable() {
return true;
}
}
public static class JetBlast extends FireCombo {
public JetBlast(Player player) {
super(player, "JetBlast");
}
@Override
public String getName() {
return "JetBlast";
}
}
public class JetBlaze extends FireCombo {
public JetBlaze(Player player, String name) {
}
public static class JetBlaze extends FireCombo {
public JetBlaze(Player player) {
super(player, "JetBlaze");
}
@Override
public String getName() {
return "JetBlaze";

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,11 +13,13 @@ import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Random;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.util.ParticleEffect;
public class FireShield extends FireAbility {
private boolean shield;
private boolean ignite;
private long time;
@ -30,6 +29,7 @@ public class FireShield extends FireAbility {
private double radius;
private double discRadius;
private double fireTicks;
private Location location;
private Random random;
public FireShield(Player player) {
@ -38,7 +38,7 @@ public class FireShield extends FireAbility {
public FireShield(Player player, boolean shield) {
super(player);
this.shield = shield;
this.ignite = true;
this.interval = getConfig().getLong("Abilities.Fire.FireShield.Interval");
@ -48,7 +48,7 @@ public class FireShield extends FireAbility {
this.discRadius = getConfig().getDouble("Abilities.Fire.FireShield.DiscRadius");
this.fireTicks = getConfig().getDouble("Abilities.Fire.FireShield.FireTicks");
this.random = new Random();
if (hasAbility(player, FireShield.class) || bPlayer.isOnCooldown("FireShield")) {
return;
} else if (!player.getEyeLocation().getBlock().isLiquid()) {
@ -60,6 +60,11 @@ public class FireShield extends FireAbility {
}
}
/**
* This method was used for the old collision detection system. Please see
* {@link Collision} for the new system.
*/
@Deprecated
public static boolean isWithinShield(Location loc) {
for (FireShield fshield : getAbilities(FireShield.class)) {
Location playerLoc = fshield.player.getLocation();
@ -74,7 +79,8 @@ public class FireShield extends FireAbility {
Location tempLoc = playerLoc.clone().add(playerLoc.multiply(fshield.discRadius));
if (!tempLoc.getWorld().equals(loc.getWorld())) {
return false;
} else if (tempLoc.getWorld().equals(loc.getWorld()) && tempLoc.distance(loc) <= fshield.discRadius * fshield.discRadius) {
} else if (tempLoc.getWorld().equals(loc.getWorld())
&& tempLoc.distance(loc) <= fshield.discRadius * fshield.discRadius) {
return true;
}
}
@ -90,7 +96,7 @@ public class FireShield extends FireAbility {
} else if (!player.isSneaking() && shield) {
remove();
return;
} else if (System.currentTimeMillis() > startTime + duration && !shield) {
} else if (System.currentTimeMillis() > getStartTime() + duration && !shield) {
remove();
return;
}
@ -100,15 +106,15 @@ public class FireShield extends FireAbility {
if (shield) {
ArrayList<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) {
double rphi = Math.toRadians(phi);
double rtheta = Math.toRadians(theta);
Block block = location .clone() .add(radius * Math.cos(rphi) * Math.sin(rtheta), radius * Math.cos(rtheta),
radius * Math.sin(rphi) * Math.sin(rtheta)).getBlock();
Block block = location.clone().add(radius * Math.cos(rphi) * Math.sin(rtheta), radius * Math.cos(rtheta),
radius * Math.sin(rphi) * Math.sin(rtheta)).getBlock();
if (!blocks.contains(block) && !GeneralMethods.isSolid(block) && !block.isLiquid()) {
blocks.add(block);
}
@ -142,13 +148,9 @@ public class FireShield extends FireAbility {
new FireDamageTimer(entity, player);
}
}
FireBlast.removeFireBlastsAroundPoint(location, radius + 1);
BlazeArc.removeAroundPoint(location, radius + 1);
Combustion.removeAroundPoint(location, radius + 1);
} else {
ArrayList<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,14 +202,14 @@ public class FireShield extends FireAbility {
@Override
public Location getLocation() {
return player != null ? player.getLocation() : null;
return location;
}
@Override
public long getCooldown() {
return cooldown;
}
@Override
public boolean isSneakAbility() {
return true;
@ -222,6 +219,11 @@ public class FireShield extends FireAbility {
public boolean isHarmlessAbility() {
return false;
}
@Override
public double getCollisionRadius() {
return shield ? radius : discRadius;
}
public boolean isShield() {
return shield;
@ -290,5 +292,5 @@ public class FireShield extends FireAbility {
public void setCooldown(long cooldown) {
this.cooldown = cooldown;
}
}

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();
}
@ -218,6 +218,15 @@ public class WallOfFire extends FireAbility {
public boolean isHarmlessAbility() {
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;
}
@ -328,6 +331,16 @@ public class Bloodbending extends BloodAbility {
public boolean isHarmlessAbility() {
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

@ -338,6 +338,16 @@ public class IceBlast extends IceAbility {
public boolean isHarmlessAbility() {
return false;
}
@Override
public boolean isCollidable() {
return progressing;
}
@Override
public double getCollisionRadius() {
return collisionRadius;
}
public boolean isPrepared() {
return prepared;
@ -403,10 +413,6 @@ public class IceBlast extends IceAbility {
this.damage = damage;
}
public double getCollisionRadius() {
return collisionRadius;
}
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}

View file

@ -45,11 +45,11 @@ public class IceSpikeBlast extends IceAbility {
public IceSpikeBlast(Player player) {
super(player);
if (bPlayer.isOnCooldown("IceSpikeBlast")) {
return;
}
this.data = 0;
this.interval = getConfig().getLong("Abilities.Water.IceSpike.Blast.Interval");
this.slowCooldown = getConfig().getLong("Abilities.Water.IceSpike.Blast.SlowCooldown");
@ -60,12 +60,12 @@ public class IceSpikeBlast extends IceAbility {
this.cooldown = getConfig().getLong("Abilities.Water.IceSpike.Blast.Cooldown");
this.slowPower = getConfig().getInt("Abilities.Water.IceSpike.Blast.SlowPower");
this.slowDuration = getConfig().getInt("Abilities.Water.IceSpike.Blast.SlowDuration");
if (!bPlayer.canBend(this) || !bPlayer.canIcebend()) {
return;
}
block(player);
block(player);
this.range = getNightFactor(range);
this.damage = getNightFactor(damage);
this.slowPower = (int) getNightFactor(slowPower);
@ -109,7 +109,7 @@ public class IceSpikeBlast extends IceAbility {
iceSpike.remove();
}
}
sourceBlock = block;
location = sourceBlock.getLocation();
prepared = true;
@ -232,7 +232,7 @@ public class IceSpikeBlast extends IceAbility {
if (!prepared) {
return;
}
LivingEntity target = (LivingEntity) GeneralMethods.getTargetedEntity(player, range);
if (target == null) {
destination = GeneralMethods.getTargetedLocation(player, range, getTransparentMaterial());
@ -247,14 +247,14 @@ public class IceSpikeBlast extends IceAbility {
if (destination.distanceSquared(location) < 1) {
return;
}
firstDestination = location.clone();
if (destination.getY() - location.getY() > 2) {
firstDestination.setY(destination.getY() - 1);
} else {
firstDestination.add(0, 2, 0);
}
destination = GeneralMethods.getPointOnLine(firstDestination, destination, range);
progressing = true;
settingUp = true;
@ -265,22 +265,21 @@ public class IceSpikeBlast extends IceAbility {
sourceBlock.setType(Material.AIR);
}
}
public static void activate(Player player) {
redirect(player);
boolean activate = false;
BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
if (bPlayer == null) {
return;
}
if (bPlayer.isOnCooldown("IceSpikeBlast")) {
return;
}
for (IceSpikeBlast ice : getAbilities(player, IceSpikeBlast.class)) {
if (ice.prepared) {
ice.throwIce();
@ -288,7 +287,7 @@ public class IceSpikeBlast extends IceAbility {
activate = true;
}
}
if (!activate && !getPlayers(IceSpikeBlast.class).contains(player)) {
IceSpikePillar spike = new IceSpikePillar(player);
if (!spike.isStarted()) {
@ -305,16 +304,15 @@ public class IceSpikeBlast extends IceAbility {
continue;
} else if (!iceSpike.progressing) {
continue;
} if (GeneralMethods.isRegionProtectedFromBuild(iceSpike, iceSpike.location)) {
}
if (GeneralMethods.isRegionProtectedFromBuild(iceSpike, iceSpike.location)) {
continue;
}
Location location = player.getEyeLocation();
Vector vector = location.getDirection();
Location mloc = iceSpike.location;
if (mloc.distanceSquared(location) <= iceSpike.range * iceSpike.range
&& GeneralMethods.getDistanceFromLine(vector, location, iceSpike.location) < iceSpike.deflectRange
&& mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
if (mloc.distanceSquared(location) <= iceSpike.range * iceSpike.range && GeneralMethods.getDistanceFromLine(vector, location, iceSpike.location) < iceSpike.deflectRange && mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
iceSpike.remove();
}
}
@ -343,12 +341,10 @@ public class IceSpikeBlast extends IceAbility {
Location location = player.getEyeLocation();
Vector vector = location.getDirection();
Location mloc = iceSpike.location;
if (GeneralMethods.isRegionProtectedFromBuild(iceSpike, mloc)) {
continue;
} else if (mloc.distanceSquared(location) <= iceSpike.range * iceSpike.range
&& GeneralMethods.getDistanceFromLine(vector, location, iceSpike.location) < iceSpike.deflectRange
&& mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
} else if (mloc.distanceSquared(location) <= iceSpike.range * iceSpike.range && GeneralMethods.getDistanceFromLine(vector, location, iceSpike.location) < iceSpike.deflectRange && mloc.distanceSquared(location.clone().add(vector)) < mloc.distanceSquared(location.clone().add(vector.clone().multiply(-1)))) {
Location loc;
Entity target = GeneralMethods.getTargetedEntity(player, iceSpike.range);
if (target == null) {
@ -366,15 +362,15 @@ public class IceSpikeBlast extends IceAbility {
@SuppressWarnings("deprecation")
private static void waterBottle(Player player) {
long range = getConfig().getLong("Abilities.Water.IceSpike.Projectile.Range");
if (WaterReturn.hasWaterBottle(player)) {
Location eyeLoc = player.getEyeLocation();
Block block = eyeLoc.add(eyeLoc.getDirection().normalize()).getBlock();
if (isTransparent(player, block) && isTransparent(player, eyeLoc.getBlock())) {
LivingEntity target = (LivingEntity) GeneralMethods.getTargetedEntity(player, range);
Location destination;
if (target == null) {
destination = GeneralMethods.getTargetedLocation(player, range, getTransparentMaterial());
} else {
@ -387,17 +383,17 @@ public class IceSpikeBlast extends IceAbility {
MaterialData data = block.getState().getData();
block.setType(Material.WATER);
block.setData((byte)0);
block.setData((byte) 0);
IceSpikeBlast iceSpike = new IceSpikeBlast(player);
iceSpike.throwIce();
iceSpike.sourceBlock = null;
if (iceSpike.progressing) {
WaterReturn.emptyWaterBottle(player);
}
}
block.setType(data.getItemType());
block.setData(data.getData());
}
}
}
@ -421,7 +417,7 @@ public class IceSpikeBlast extends IceAbility {
public long getCooldown() {
return cooldown;
}
@Override
public boolean isSneakAbility() {
return true;
@ -432,6 +428,16 @@ public class IceSpikeBlast extends IceAbility {
return false;
}
@Override
public boolean isCollidable() {
return progressing;
}
@Override
public double getCollisionRadius() {
return collisionRadius;
}
public boolean isPrepared() {
return prepared;
}
@ -520,10 +526,6 @@ public class IceSpikeBlast extends IceAbility {
this.damage = damage;
}
public double getCollisionRadius() {
return collisionRadius;
}
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}
@ -575,5 +577,5 @@ public class IceSpikeBlast extends IceAbility {
public void setLocation(Location location) {
this.location = location;
}
}

View file

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

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,7 +217,8 @@ public class SurgeWall extends WaterAbility {
remove();
return;
}
locations.clear();
if (System.currentTimeMillis() - time >= interval) {
time = System.currentTimeMillis();
boolean matchesName = bPlayer.getBoundAbilityName().equalsIgnoreCase(getName());
@ -258,6 +262,7 @@ public class SurgeWall extends WaterAbility {
WALL_BLOCKS.put(block, player);
addWallBlock(block);
blocks.add(block);
locations.add(block.getLocation());
FireBlast.removeFireBlastsAroundPoint(block.getLocation(), 2);
}
}
@ -483,6 +488,11 @@ public class SurgeWall extends WaterAbility {
public boolean isHarmlessAbility() {
return false;
}
@Override
public List<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 {
@ -439,6 +440,23 @@ public class SurgeWave extends WaterAbility {
public boolean isHarmlessAbility() {
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

@ -655,6 +655,23 @@ public class Torrent extends WaterAbility {
public boolean isHarmlessAbility() {
return false;
}
@Override
public boolean isCollidable() {
return forming || formed || launch || launching;
}
@Override
public List<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,9 +32,9 @@ import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
/*
* TODO: Combo classes should eventually be rewritten so that each combo is treated
* as an individual ability. In the mean time, we will just place "fake"
* classes so that CoreAbility will register each ability.
* TODO: Combo classes should eventually be rewritten so that each combo is
* treated as an individual ability. In the mean time, we will just place "fake"
* classes so that CoreAbility will register each ability.
*/
public class WaterCombo extends IceAbility implements ComboAbility {
@ -76,12 +79,11 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
if (name.equalsIgnoreCase("IceWave")) {
if (bPlayer.isOnCooldown("IceWave") && !bPlayer.isAvatarState()) {
remove();
return;
}
this.cooldown = getConfig().getLong("Abilities.Water.WaterCombo.IceWave.Cooldown");
} else if (name.equalsIgnoreCase("IceBullet")) {
this.damage = getConfig().getDouble("Abilities.Water.WaterCombo.IceBullet.Damage");
@ -93,7 +95,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
this.animationSpeed = getConfig().getDouble("Abilities.Water.WaterCombo.IceBullet.AnimationSpeed");
this.speed = 1;
}
double aug = getNightFactor(player.getWorld());
if (aug > 1) {
aug = 1 + (aug - 1) / 3;
@ -115,7 +117,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
if (name.equalsIgnoreCase("IceBulletLeftClick") || name.equalsIgnoreCase("IceBulletRightClick")) {
ArrayList<WaterCombo> bullets = getWaterCombo(player, "IceBullet");
Collection<IceBullet> bullets = CoreAbility.getAbilities(player, IceBullet.class);
if (bullets.size() == 0) {
return;
}
@ -130,7 +132,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
return;
}
start();
}
@ -149,13 +151,13 @@ public class WaterCombo extends IceAbility implements ComboAbility {
public void drawWaterCircle(Location loc, double theta, double increment, double radius, Material mat, byte data) {
double rotateSpeed = theta;
direction = GeneralMethods.rotateXZ(direction, rotateSpeed);
for (double i = 0; i < theta; i += increment) {
Vector dir = GeneralMethods.rotateXZ(direction, i - theta / 2).normalize().multiply(radius);
dir.setY(0);
Block block = loc.clone().add(dir).getBlock();
location = block.getLocation();
if (block.getType() == Material.AIR && !GeneralMethods.isRegionProtectedFromBuild(player, "WaterManipulation", block.getLocation())) {
createBlock(block, mat, data);
}
@ -169,7 +171,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
i--;
}
}
for (int i = 0; i < tasks.size(); i++) {
FireComboStream fstream = (FireComboStream) tasks.get(i);
Location loc = fstream.getLocation();
@ -197,10 +199,6 @@ public class WaterCombo extends IceAbility implements ComboAbility {
}
}
}
if (GeneralMethods.blockAbilities(player, FireCombo.getBlockableAbilities(), loc, 1)) {
fstream.remove();
}
}
}
}
@ -214,7 +212,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
if (origin == null && WaterSpoutWave.containsType(player, WaterSpoutWave.AbilityType.RELEASE)) {
bPlayer.addCooldown("IceWave", cooldown);
origin = player.getLocation();
WaterSpoutWave wave = WaterSpoutWave.getType(player, WaterSpoutWave.AbilityType.RELEASE).get(0);
wave.setIceWave(true);
} else if (!WaterSpoutWave.containsType(player, WaterSpoutWave.AbilityType.RELEASE)) {
@ -226,19 +224,19 @@ public class WaterCombo extends IceAbility implements ComboAbility {
remove();
return;
}
if (origin == null) {
if (bPlayer.isOnCooldown("IceBullet") && !bPlayer.isAvatarState()) {
remove();
return;
}
Block waterBlock = BlockSource.getWaterSourceBlock(player, range, ClickType.LEFT_CLICK, true, true, bPlayer.canPlantbend());
if (waterBlock == null) {
remove();
return;
}
time = 0;
origin = waterBlock.getLocation();
location = origin.clone();
@ -253,7 +251,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
if (this.time == 0) {
this.time = System.currentTimeMillis();
}
long timeDiff = System.currentTimeMillis() - this.time;
if (this.state == AbilityState.ICE_BULLET_FORMING) {
if (timeDiff < 1000 * animationSpeed) {
@ -277,7 +275,7 @@ public class WaterCombo extends IceAbility implements ComboAbility {
Vector vec = player.getEyeLocation().getDirection().normalize();
Location loc = player.getEyeLocation().add(vec.clone().multiply(radius + 1.3));
FireComboStream fs = new FireComboStream(null, vec, loc, range, speed, "IceBullet");
fs.setDensity(10);
fs.setSpread(0.1F);
fs.setUseNewParticles(true);
@ -308,9 +306,9 @@ public class WaterCombo extends IceAbility implements ComboAbility {
if (waterGrabber != null) {
waterGrabber.remove();
}
bPlayer.addCooldown(this);
if (name == "IceWave") {
bPlayer.addCooldown("WaterWave", getConfig().getLong("Abilities.Water.WaterSpout.Wave.Cooldown"));
}
@ -363,12 +361,12 @@ public class WaterCombo extends IceAbility implements ComboAbility {
public long getCooldown() {
return cooldown;
}
@Override
public boolean isHiddenAbility() {
return true;
}
@Override
public boolean isSneakAbility() {
return true;
@ -378,7 +376,13 @@ public class WaterCombo extends IceAbility implements ComboAbility {
public boolean isHarmlessAbility() {
return false;
}
@Override
public boolean isCollidable() {
// Override in subclasses
return false;
}
@Override
public String getInstructions() {
return null;
@ -526,6 +530,10 @@ public class WaterCombo extends IceAbility implements ComboAbility {
return tasks;
}
public void setTasks(ArrayList<BukkitRunnable> tasks) {
this.tasks = tasks;
}
public static Map<Block, TempBlock> getFrozenBlocks() {
return FROZEN_BLOCKS;
}
@ -545,31 +553,99 @@ public class WaterCombo extends IceAbility implements ComboAbility {
public void setLocation(Location location) {
this.location = location;
}
public class IceWave extends WaterCombo {
public IceWave(Player player, String name) {
// Combo subclasses need to be static to be reflectively called in ComboManager
public static class IceWave extends WaterCombo {
public IceWave(Player player) {
super(player, "IceWave");
}
@Override
public String getName() {
return "IceWave";
}
}
public class IceBullet extends WaterCombo {
public IceBullet(Player player, String name) {
}
public static class IceBullet extends WaterCombo {
public IceBullet(Player player) {
super(player, "IceBullet");
}
@Override
public String getName() {
return "IceBullet";
}
@Override
public boolean isCollidable() {
return true;
}
@Override
public void handleCollision(Collision collision) {
if (collision.isRemovingFirst()) {
ArrayList<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)) {
@ -596,6 +580,24 @@ public class WaterManipulation extends WaterAbility {
public boolean isHarmlessAbility() {
return false;
}
@Override
public boolean isCollidable() {
return progressing;
}
@Override
public double getCollisionRadius() {
return collisionRadius;
}
@Override
public void handleCollision(Collision collision) {
super.handleCollision(collision);
if (collision.isRemovingFirst()) {
new WaterReturn(player, sourceBlock);
}
}
public boolean isProgressing() {
return progressing;
@ -781,10 +783,6 @@ public class WaterManipulation extends WaterAbility {
this.location = location;
}
public double getCollisionRadius() {
return collisionRadius;
}
public void setCollisionRadius(double collisionRadius) {
this.collisionRadius = collisionRadius;
}

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)) {
@ -332,6 +338,24 @@ public class WaterSpout extends WaterAbility {
public boolean isHarmlessAbility() {
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;
@ -416,5 +440,5 @@ public class WaterSpout extends WaterAbility {
public static Map<Block, Block> getAffectedBlocks() {
return AFFECTED_BLOCKS;
}
}

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