lots of changes

This commit is contained in:
Simp 2020-06-25 16:54:10 -04:00
parent 1d509259fb
commit e9d663c456
59 changed files with 1092 additions and 1099 deletions

View file

@ -65,7 +65,7 @@
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version> <version>1.16.1-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- lang3 --> <!-- lang3 -->
@ -136,7 +136,7 @@
<dependency> <dependency>
<groupId>com.sk89q.worldguard</groupId> <groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-core</artifactId> <artifactId>worldguard-core</artifactId>
<version>7.0.0-SNAPSHOT</version> <version>7.0.2-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>

View file

@ -3,8 +3,6 @@ package com.projectkorra.projectkorra;
import java.util.HashMap; import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
import co.aikar.timings.lib.MCTiming;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.World; import org.bukkit.World;
@ -14,13 +12,14 @@ import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.ability.ElementalAbility;
import com.projectkorra.projectkorra.configuration.ConfigManager; import com.projectkorra.projectkorra.configuration.ConfigManager;
import com.projectkorra.projectkorra.earthbending.metal.MetalClips; import com.projectkorra.projectkorra.earthbending.metal.MetalClips;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
import com.projectkorra.projectkorra.util.ActionBar; import com.projectkorra.projectkorra.util.ActionBar;
import com.projectkorra.projectkorra.util.RevertChecker; import com.projectkorra.projectkorra.util.RevertChecker;
import com.projectkorra.projectkorra.util.TempArmor; import com.projectkorra.projectkorra.util.TempArmor;
import com.projectkorra.projectkorra.util.TempPotionEffect; import com.projectkorra.projectkorra.util.TempPotionEffect;
import com.projectkorra.projectkorra.waterbending.blood.Bloodbending; import com.projectkorra.projectkorra.waterbending.blood.Bloodbending;
import co.aikar.timings.lib.MCTiming;
public class BendingManager implements Runnable { public class BendingManager implements Runnable {
private static BendingManager instance; private static BendingManager instance;
@ -30,7 +29,7 @@ public class BendingManager implements Runnable {
long interval; long interval;
private final HashMap<World, Boolean> times = new HashMap<World, Boolean>(); // true if day time private final HashMap<World, Boolean> times = new HashMap<World, Boolean>(); // true if day time
private final MCTiming CORE_ABILITY_TIMING, TEMP_POTION_TIMING, DAY_NIGHT_TIMING, HORIZONTAL_VELOCITY_TRACKER_TIMING, COOLDOWN_TIMING, TEMP_ARMOR_TIMING, ACTIONBAR_STATUS_TIMING; private final MCTiming CORE_ABILITY_TIMING, TEMP_POTION_TIMING, DAY_NIGHT_TIMING, COOLDOWN_TIMING, TEMP_ARMOR_TIMING, ACTIONBAR_STATUS_TIMING;
public BendingManager() { public BendingManager() {
instance = this; instance = this;
@ -39,7 +38,6 @@ public class BendingManager implements Runnable {
this.CORE_ABILITY_TIMING = ProjectKorra.timing("CoreAbility#ProgressAll"); this.CORE_ABILITY_TIMING = ProjectKorra.timing("CoreAbility#ProgressAll");
this.TEMP_POTION_TIMING = ProjectKorra.timing("TempPotion#ProgressAll"); this.TEMP_POTION_TIMING = ProjectKorra.timing("TempPotion#ProgressAll");
this.DAY_NIGHT_TIMING = ProjectKorra.timing("HandleDayNight"); this.DAY_NIGHT_TIMING = ProjectKorra.timing("HandleDayNight");
this.HORIZONTAL_VELOCITY_TRACKER_TIMING = ProjectKorra.timing("HorizontalVelocityTracker#UpdateAll");
this.COOLDOWN_TIMING = ProjectKorra.timing("HandleCooldowns"); this.COOLDOWN_TIMING = ProjectKorra.timing("HandleCooldowns");
this.TEMP_ARMOR_TIMING = ProjectKorra.timing("TempArmor#Cleanup"); this.TEMP_ARMOR_TIMING = ProjectKorra.timing("TempArmor#Cleanup");
this.ACTIONBAR_STATUS_TIMING = ProjectKorra.timing("ActionBarCheck"); this.ACTIONBAR_STATUS_TIMING = ProjectKorra.timing("ActionBarCheck");
@ -127,10 +125,6 @@ public class BendingManager implements Runnable {
RevertChecker.revertAirBlocks(); RevertChecker.revertAirBlocks();
try (MCTiming timing = this.HORIZONTAL_VELOCITY_TRACKER_TIMING.startTiming()) {
HorizontalVelocityTracker.updateAll();
}
try (MCTiming timing = this.COOLDOWN_TIMING.startTiming()) { try (MCTiming timing = this.COOLDOWN_TIMING.startTiming()) {
this.handleCooldowns(); this.handleCooldowns();
} }

View file

@ -57,10 +57,11 @@ public class Element {
public static final SubElement SAND = new SubElement("Sand", EARTH); public static final SubElement SAND = new SubElement("Sand", EARTH);
public static final SubElement LIGHTNING = new SubElement("Lightning", FIRE); public static final SubElement LIGHTNING = new SubElement("Lightning", FIRE);
public static final SubElement COMBUSTION = new SubElement("Combustion", FIRE); public static final SubElement COMBUSTION = new SubElement("Combustion", FIRE);
public static final SubElement BLUE_FIRE = new SubElement("Blue Fire", FIRE);
private static final Element[] ELEMENTS = { AIR, WATER, EARTH, FIRE, CHI, FLIGHT, SPIRITUAL, BLOOD, HEALING, ICE, PLANT, LAVA, METAL, SAND, LIGHTNING, COMBUSTION }; private static final Element[] ELEMENTS = { AIR, WATER, EARTH, FIRE, CHI, FLIGHT, SPIRITUAL, BLOOD, HEALING, ICE, PLANT, LAVA, METAL, SAND, LIGHTNING, COMBUSTION };
private static final Element[] MAIN_ELEMENTS = { AIR, WATER, EARTH, FIRE, CHI }; private static final Element[] MAIN_ELEMENTS = { AIR, WATER, EARTH, FIRE, CHI };
private static final SubElement[] SUB_ELEMENTS = { FLIGHT, SPIRITUAL, BLOOD, HEALING, ICE, PLANT, LAVA, METAL, SAND, LIGHTNING, COMBUSTION }; private static final SubElement[] SUB_ELEMENTS = { FLIGHT, SPIRITUAL, BLOOD, HEALING, ICE, PLANT, LAVA, METAL, SAND, LIGHTNING, COMBUSTION, BLUE_FIRE };
private final String name; private final String name;
private final ElementType type; private final ElementType type;
@ -101,7 +102,7 @@ public class Element {
this.name = name; this.name = name;
this.type = type; this.type = type;
this.plugin = plugin; this.plugin = plugin;
ALL_ELEMENTS.put(name.toLowerCase(), this); ALL_ELEMENTS.put(name.toLowerCase().replace(" ", ""), this);
} }
public String getPrefix() { public String getPrefix() {
@ -146,7 +147,7 @@ public class Element {
if (name == null) { if (name == null) {
return null; return null;
} }
return ALL_ELEMENTS.get(name.toLowerCase()); return ALL_ELEMENTS.get(name.toLowerCase().replace(" ", ""));
} }
/** /**

View file

@ -119,6 +119,7 @@ import com.projectkorra.projectkorra.firebending.FireBlast;
import com.projectkorra.projectkorra.firebending.FireShield; import com.projectkorra.projectkorra.firebending.FireShield;
import com.projectkorra.projectkorra.firebending.combustion.Combustion; import com.projectkorra.projectkorra.firebending.combustion.Combustion;
import com.projectkorra.projectkorra.object.Preset; import com.projectkorra.projectkorra.object.Preset;
import com.projectkorra.projectkorra.object.VelocityTracker;
import com.projectkorra.projectkorra.storage.DBConnection; import com.projectkorra.projectkorra.storage.DBConnection;
import com.projectkorra.projectkorra.util.ActionBar; import com.projectkorra.projectkorra.util.ActionBar;
import com.projectkorra.projectkorra.util.BlockCacheElement; import com.projectkorra.projectkorra.util.BlockCacheElement;
@ -157,6 +158,7 @@ public class GeneralMethods {
private static Method getAbsorption; private static Method getAbsorption;
private static Method setAbsorption; private static Method setAbsorption;
private static Method getHandle;
public GeneralMethods(final ProjectKorra plugin) { public GeneralMethods(final ProjectKorra plugin) {
GeneralMethods.plugin = plugin; GeneralMethods.plugin = plugin;
@ -164,6 +166,7 @@ public class GeneralMethods {
try { try {
getAbsorption = ReflectionHandler.getMethod("EntityHuman", PackageType.MINECRAFT_SERVER, "getAbsorptionHearts"); getAbsorption = ReflectionHandler.getMethod("EntityHuman", PackageType.MINECRAFT_SERVER, "getAbsorptionHearts");
setAbsorption = ReflectionHandler.getMethod("EntityHuman", PackageType.MINECRAFT_SERVER, "setAbsorptionHearts", Float.class); setAbsorption = ReflectionHandler.getMethod("EntityHuman", PackageType.MINECRAFT_SERVER, "setAbsorptionHearts", Float.class);
getHandle = ReflectionHandler.getMethod("CraftPlayer", PackageType.CRAFTBUKKIT_ENTITY, "getHandle");
} catch (final Exception e) { } catch (final Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -464,6 +467,9 @@ public class GeneralMethods {
if (split[0].contains("p")) { if (split[0].contains("p")) {
subelements.add(Element.PLANT); subelements.add(Element.PLANT);
} }
if (split[0].contains("r")) {
subelements.add(Element.BLUE_FIRE);
}
if (hasAddon) { if (hasAddon) {
final CopyOnWriteArrayList<String> addonClone = new CopyOnWriteArrayList<String>(Arrays.asList(split[split.length - 1].split(","))); final CopyOnWriteArrayList<String> addonClone = new CopyOnWriteArrayList<String>(Arrays.asList(split[split.length - 1].split(",")));
final long startTime = System.currentTimeMillis(); final long startTime = System.currentTimeMillis();
@ -574,6 +580,10 @@ public class GeneralMethods {
@Deprecated @Deprecated
public static void displayColoredParticle(final Location loc, ParticleEffect type, final String hexVal, final float xOffset, final float yOffset, final float zOffset) { public static void displayColoredParticle(final Location loc, ParticleEffect type, final String hexVal, final float xOffset, final float yOffset, final float zOffset) {
if (type != ParticleEffect.REDSTONE && type != ParticleEffect.SPELL_MOB && type != ParticleEffect.SPELL_MOB_AMBIENT) {
type = ParticleEffect.REDSTONE;
}
int r = 0; int r = 0;
int g = 0; int g = 0;
int b = 0; int b = 0;
@ -596,22 +606,9 @@ public class GeneralMethods {
loc.setY(loc.getY() + (Math.random() * 2 - 1) * yOffset); loc.setY(loc.getY() + (Math.random() * 2 - 1) * yOffset);
loc.setZ(loc.getZ() + (Math.random() * 2 - 1) * zOffset); loc.setZ(loc.getZ() + (Math.random() * 2 - 1) * zOffset);
if (type != ParticleEffect.RED_DUST && type != ParticleEffect.REDSTONE && type != ParticleEffect.SPELL_MOB && type != ParticleEffect.MOB_SPELL && type != ParticleEffect.SPELL_MOB_AMBIENT && type != ParticleEffect.MOB_SPELL_AMBIENT) {
type = ParticleEffect.RED_DUST;
}
type.display(loc, 0, red, green, blue); type.display(loc, 0, red, green, blue);
} }
@Deprecated
public static void displayColoredParticle(final Location loc, final String hexVal) {
displayColoredParticle(loc, ParticleEffect.RED_DUST, hexVal, 0, 0, 0);
}
@Deprecated
public static void displayColoredParticle(final Location loc, final String hexVal, final float xOffset, final float yOffset, final float zOffset) {
displayColoredParticle(loc, ParticleEffect.RED_DUST, hexVal, xOffset, yOffset, zOffset);
}
public static void displayColoredParticle(String hexVal, final Location loc, final int amount, final double offsetX, final double offsetY, final double offsetZ) { public static void displayColoredParticle(String hexVal, final Location loc, final int amount, final double offsetX, final double offsetY, final double offsetZ) {
int r = 0; int r = 0;
int g = 0; int g = 0;
@ -674,7 +671,7 @@ public class GeneralMethods {
public static float getAbsorbationHealth(final Player player) { public static float getAbsorbationHealth(final Player player) {
try { try {
final Object entityplayer = ActionBar.getHandle.invoke(player); final Object entityplayer = getHandle.invoke(player);
final Object hearts = getAbsorption.invoke(entityplayer); final Object hearts = getAbsorption.invoke(entityplayer);
return (float) hearts; return (float) hearts;
} catch (final Exception e) { } catch (final Exception e) {
@ -686,7 +683,7 @@ public class GeneralMethods {
public static void setAbsorbationHealth(final Player player, final float hearts) { public static void setAbsorbationHealth(final Player player, final float hearts) {
try { try {
final Object entityplayer = ActionBar.getHandle.invoke(player); final Object entityplayer = getHandle.invoke(player);
setAbsorption.invoke(entityplayer, hearts); setAbsorption.invoke(entityplayer, hearts);
} catch (final Exception e) { } catch (final Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -1660,15 +1657,16 @@ public class GeneralMethods {
case SKELETON: case SKELETON:
case STRAY: case STRAY:
case WITHER_SKELETON: case WITHER_SKELETON:
case WITHER:
case ZOMBIE: case ZOMBIE:
case HUSK:
case ZOMBIE_VILLAGER:
case PIG_ZOMBIE:
case DROWNED: case DROWNED:
case ZOMBIE_HORSE: case HUSK:
case SKELETON_HORSE: case ZOMBIFIED_PIGLIN:
case ZOMBIE_VILLAGER:
case PHANTOM: case PHANTOM:
case WITHER:
case SKELETON_HORSE:
case ZOMBIE_HORSE:
case ZOGLIN:
return true; return true;
default: default:
return false; return false;
@ -1739,9 +1737,15 @@ public class GeneralMethods {
sender.sendMessage(ChatColor.RED + "Reload event cancelled"); sender.sendMessage(ChatColor.RED + "Reload event cancelled");
return; return;
} }
for (BendingPlayer bPlayer : BendingPlayer.getPlayers().values()) {
savePlayer(bPlayer);
}
if (DBConnection.isOpen()) { if (DBConnection.isOpen()) {
DBConnection.sql.close(); DBConnection.sql.close();
} }
GeneralMethods.stopBending(); GeneralMethods.stopBending();
ConfigManager.defaultConfig.reload(); ConfigManager.defaultConfig.reload();
ConfigManager.languageConfig.reload(); ConfigManager.languageConfig.reload();
@ -1764,11 +1768,13 @@ public class GeneralMethods {
ProjectKorra.log.severe("Unable to enable ProjectKorra due to the database not being open"); ProjectKorra.log.severe("Unable to enable ProjectKorra due to the database not being open");
stopPlugin(); stopPlugin();
} }
for (final Player player : Bukkit.getOnlinePlayers()) { for (final Player player : Bukkit.getOnlinePlayers()) {
Preset.unloadPreset(player); Preset.unloadPreset(player);
GeneralMethods.createBendingPlayer(player.getUniqueId(), player.getName()); GeneralMethods.createBendingPlayer(player.getUniqueId(), player.getName());
PassiveManager.registerPassives(player); PassiveManager.registerPassives(player);
} }
plugin.updater.checkUpdate(); plugin.updater.checkUpdate();
ProjectKorra.log.info("Reload complete"); ProjectKorra.log.info("Reload complete");
} }
@ -2115,6 +2121,9 @@ public class GeneralMethods {
if (bPlayer.hasSubElement(Element.PLANT)) { if (bPlayer.hasSubElement(Element.PLANT)) {
subs.append("p"); subs.append("p");
} }
if (bPlayer.hasSubElement(Element.BLUE_FIRE)) {
subs.append("r");
}
boolean hasAddon = false; boolean hasAddon = false;
for (final Element element : bPlayer.getSubElements()) { for (final Element element : bPlayer.getSubElements()) {
if (Arrays.asList(Element.getAddonSubElements()).contains(element)) { if (Arrays.asList(Element.getAddonSubElements()).contains(element)) {
@ -2297,8 +2306,8 @@ public class GeneralMethods {
CoreAbility.removeAll(); CoreAbility.removeAll();
EarthAbility.stopBending(); EarthAbility.stopBending();
WaterAbility.stopBending(); WaterAbility.stopBending();
FireAbility.stopBending();
VelocityTracker.cancelAll();
TempBlock.removeAll(); TempBlock.removeAll();
TempArmor.revertAll(); TempArmor.revertAll();
TempArmorStand.removeAll(); TempArmorStand.removeAll();

View file

@ -34,7 +34,6 @@ import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.FluidLevelChangeEvent; import org.bukkit.event.block.FluidLevelChangeEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityDamageByBlockEvent; import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent;
@ -65,7 +64,6 @@ import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.event.player.PlayerItemDamageEvent;
import org.bukkit.event.player.PlayerItemHeldEvent; import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerSwapHandItemsEvent; import org.bukkit.event.player.PlayerSwapHandItemsEvent;
@ -76,7 +74,6 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.Element.SubElement;
import com.projectkorra.projectkorra.ability.Ability; import com.projectkorra.projectkorra.ability.Ability;
import com.projectkorra.projectkorra.ability.AddonAbility; import com.projectkorra.projectkorra.ability.AddonAbility;
import com.projectkorra.projectkorra.ability.AirAbility; import com.projectkorra.projectkorra.ability.AirAbility;
@ -101,6 +98,8 @@ import com.projectkorra.projectkorra.airbending.Suffocate;
import com.projectkorra.projectkorra.airbending.Tornado; import com.projectkorra.projectkorra.airbending.Tornado;
import com.projectkorra.projectkorra.airbending.flight.FlightMultiAbility; import com.projectkorra.projectkorra.airbending.flight.FlightMultiAbility;
import com.projectkorra.projectkorra.airbending.passive.GracefulDescent; import com.projectkorra.projectkorra.airbending.passive.GracefulDescent;
import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.attribute.AttributeModifier;
import com.projectkorra.projectkorra.avatar.AvatarState; import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.chiblocking.AcrobatStance; import com.projectkorra.projectkorra.chiblocking.AcrobatStance;
import com.projectkorra.projectkorra.chiblocking.HighJump; import com.projectkorra.projectkorra.chiblocking.HighJump;
@ -136,12 +135,11 @@ import com.projectkorra.projectkorra.earthbending.metal.MetalClips;
import com.projectkorra.projectkorra.earthbending.passive.DensityShift; import com.projectkorra.projectkorra.earthbending.passive.DensityShift;
import com.projectkorra.projectkorra.earthbending.passive.EarthPassive; import com.projectkorra.projectkorra.earthbending.passive.EarthPassive;
import com.projectkorra.projectkorra.earthbending.passive.FerroControl; import com.projectkorra.projectkorra.earthbending.passive.FerroControl;
import com.projectkorra.projectkorra.event.AbilityStartEvent;
import com.projectkorra.projectkorra.event.EntityBendingDeathEvent; import com.projectkorra.projectkorra.event.EntityBendingDeathEvent;
import com.projectkorra.projectkorra.event.HorizontalVelocityChangeEvent;
import com.projectkorra.projectkorra.event.PlayerChangeElementEvent; import com.projectkorra.projectkorra.event.PlayerChangeElementEvent;
import com.projectkorra.projectkorra.event.PlayerJumpEvent; import com.projectkorra.projectkorra.event.PlayerJumpEvent;
import com.projectkorra.projectkorra.firebending.Blaze; import com.projectkorra.projectkorra.firebending.Blaze;
import com.projectkorra.projectkorra.firebending.BlazeArc;
import com.projectkorra.projectkorra.firebending.BlazeRing; import com.projectkorra.projectkorra.firebending.BlazeRing;
import com.projectkorra.projectkorra.firebending.FireBlast; import com.projectkorra.projectkorra.firebending.FireBlast;
import com.projectkorra.projectkorra.firebending.FireBlastCharged; import com.projectkorra.projectkorra.firebending.FireBlastCharged;
@ -154,15 +152,15 @@ import com.projectkorra.projectkorra.firebending.HeatControl;
import com.projectkorra.projectkorra.firebending.HeatControl.HeatControlType; import com.projectkorra.projectkorra.firebending.HeatControl.HeatControlType;
import com.projectkorra.projectkorra.firebending.Illumination; import com.projectkorra.projectkorra.firebending.Illumination;
import com.projectkorra.projectkorra.firebending.WallOfFire; import com.projectkorra.projectkorra.firebending.WallOfFire;
import com.projectkorra.projectkorra.firebending.bluefire.BlueFlames;
import com.projectkorra.projectkorra.firebending.combustion.Combustion; import com.projectkorra.projectkorra.firebending.combustion.Combustion;
import com.projectkorra.projectkorra.firebending.lightning.Lightning; import com.projectkorra.projectkorra.firebending.lightning.Lightning;
import com.projectkorra.projectkorra.firebending.passive.FirePassive; import com.projectkorra.projectkorra.firebending.passive.FirePassive;
import com.projectkorra.projectkorra.firebending.util.FireDamageTimer;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
import com.projectkorra.projectkorra.object.Preset; import com.projectkorra.projectkorra.object.Preset;
import com.projectkorra.projectkorra.object.VelocityTracker;
import com.projectkorra.projectkorra.util.AbilityDamageTimestamp;
import com.projectkorra.projectkorra.util.BlockSource; import com.projectkorra.projectkorra.util.BlockSource;
import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.FlightHandler; import com.projectkorra.projectkorra.util.FlightHandler;
import com.projectkorra.projectkorra.util.FlightHandler.Flight; import com.projectkorra.projectkorra.util.FlightHandler.Flight;
import com.projectkorra.projectkorra.util.MovementHandler; import com.projectkorra.projectkorra.util.MovementHandler;
@ -194,8 +192,6 @@ import co.aikar.timings.lib.MCTiming;
public class PKListener implements Listener { public class PKListener implements Listener {
ProjectKorra plugin; ProjectKorra plugin;
private static final HashMap<Entity, Ability> BENDING_ENTITY_DEATH = new HashMap<>(); // Entities killed by Bending.
private static final HashMap<Player, String> BENDING_PLAYER_DEATH = new HashMap<>(); // Player killed by Bending.
private static final List<UUID> RIGHT_CLICK_INTERACT = new ArrayList<UUID>(); // Player right click block. private static final List<UUID> RIGHT_CLICK_INTERACT = new ArrayList<UUID>(); // Player right click block.
private static final ArrayList<UUID> TOGGLED_OUT = new ArrayList<>(); // Stands for toggled = false while logging out. private static final ArrayList<UUID> TOGGLED_OUT = new ArrayList<>(); // Stands for toggled = false while logging out.
private static final Map<Player, Integer> JUMPS = new HashMap<>(); private static final Map<Player, Integer> JUMPS = new HashMap<>();
@ -221,6 +217,25 @@ public class PKListener implements Listener {
TimingPlayerMoveJumpCheck = ProjectKorra.timing("PlayerMoveJumpCheck"); TimingPlayerMoveJumpCheck = ProjectKorra.timing("PlayerMoveJumpCheck");
} }
@EventHandler
public void onAbilityStart(final AbilityStartEvent event) {
if (!(event.getAbility() instanceof CoreAbility)) {
return;
}
CoreAbility ability = (CoreAbility) event.getAbility();
BendingPlayer bPlayer = ability.getBendingPlayer();
if (bPlayer == null) {
return;
}
CoreAbility bf = CoreAbility.getAbility(BlueFlames.class);
if (bf != null && bPlayer.canBendPassive(bf) && bPlayer.canUsePassive(bf) && ability instanceof FireAbility && ability.hasAttribute(Attribute.DAMAGE)) {
ability.addAttributeModifier(Attribute.DAMAGE, ConfigManager.getConfig().getDouble("Abilities.Fire.Passives.BlueFlames.DamageMultiplier"), AttributeModifier.MULTIPLICATION);
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onBlockBreak(final BlockBreakEvent event) { public void onBlockBreak(final BlockBreakEvent event) {
final Block block = event.getBlock(); final Block block = event.getBlock();
@ -372,10 +387,6 @@ public class PKListener implements Listener {
if (!event.isCancelled()) { if (!event.isCancelled()) {
event.setCancelled(!Torrent.canThaw(block)); event.setCancelled(!Torrent.canThaw(block));
} }
if (BlazeArc.getIgnitedBlocks().containsKey(block)) {
BlazeArc.removeBlock(block);
}
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
@ -473,15 +484,6 @@ public class PKListener implements Listener {
} }
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onEntityCombust(final EntityCombustEvent event) {
final Entity entity = event.getEntity();
final Block block = entity.getLocation().getBlock();
if (BlazeArc.getIgnitedBlocks().containsKey(block) && entity instanceof LivingEntity) {
new FireDamageTimer(entity, BlazeArc.getIgnitedBlocks().get(block));
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onEntityDamageBlock(final EntityDamageByBlockEvent event) {} public void onEntityDamageBlock(final EntityDamageByBlockEvent event) {}
@ -504,15 +506,6 @@ public class PKListener implements Listener {
public void onEntityDamageEvent(final EntityDamageEvent event) { public void onEntityDamageEvent(final EntityDamageEvent event) {
final Entity entity = event.getEntity(); final Entity entity = event.getEntity();
if (event.getCause() == DamageCause.FIRE && BlazeArc.getIgnitedBlocks().containsKey(entity.getLocation().getBlock())) {
new FireDamageTimer(entity, BlazeArc.getIgnitedBlocks().get(entity.getLocation().getBlock()));
}
if (FireDamageTimer.isEnflamed(entity) && event.getCause() == DamageCause.FIRE_TICK) {
event.setCancelled(true);
FireDamageTimer.dealFlameDamage(entity);
}
if (entity instanceof LivingEntity && TempArmor.hasTempArmor((LivingEntity) entity)) { if (entity instanceof LivingEntity && TempArmor.hasTempArmor((LivingEntity) entity)) {
if (event.isApplicable(DamageModifier.ARMOR)) { if (event.isApplicable(DamageModifier.ARMOR)) {
event.setDamage(DamageModifier.ARMOR, 0); event.setDamage(DamageModifier.ARMOR, 0);
@ -568,12 +561,27 @@ public class PKListener implements Listener {
} }
} }
final CoreAbility[] cookingFireCombos = { CoreAbility.getAbility("JetBlast"), CoreAbility.getAbility("FireWheel"), CoreAbility.getAbility("FireSpin"), CoreAbility.getAbility("FireKick") }; Ability ability = null;
VelocityTracker tracker = VelocityTracker.getTracker(event.getEntity());
AbilityDamageTimestamp adt = AbilityDamageTimestamp.get(event.getEntity());
if (tracker != null) {
ability = tracker.getAbility();
} else if (adt != null) {
ability = adt.getAbility();
} else {
return;
}
EntityBendingDeathEvent bendingDeath = new EntityBendingDeathEvent(event.getEntity(), ability);
Bukkit.getServer().getPluginManager().callEvent(bendingDeath);
final List<String> cookingFireCombos = Arrays.asList("JetBlaze", "FireWheel", "FireSpin", "FireKick");
if (!cookingFireCombos.contains(ability.getName())) {
return;
}
if (BENDING_ENTITY_DEATH.containsKey(event.getEntity())) {
final CoreAbility coreAbility = (CoreAbility) BENDING_ENTITY_DEATH.get(event.getEntity());
for (final CoreAbility fireCombo : cookingFireCombos) {
if (coreAbility.getName().equalsIgnoreCase(fireCombo.getName())) {
final List<ItemStack> drops = event.getDrops(); final List<ItemStack> drops = event.getDrops();
final List<ItemStack> newDrops = new ArrayList<>(); final List<ItemStack> newDrops = new ArrayList<>();
for (int i = 0; i < drops.size(); i++) { for (int i = 0; i < drops.size(); i++) {
@ -607,13 +615,9 @@ public class PKListener implements Listener {
newDrops.add(cooked); newDrops.add(cooked);
} }
event.getDrops().clear(); event.getDrops().clear();
event.getDrops().addAll(newDrops); event.getDrops().addAll(newDrops);
break;
}
}
}
} }
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
@ -732,24 +736,6 @@ public class PKListener implements Listener {
} }
} }
@EventHandler
public void onHorizontalCollision(final HorizontalVelocityChangeEvent e) {
if (e.getEntity() instanceof LivingEntity) {
if (e.getEntity().getEntityId() != e.getInstigator().getEntityId()) {
final double minimumDistance = this.plugin.getConfig().getDouble("Properties.HorizontalCollisionPhysics.WallDamageMinimumDistance");
final double maxDamage = this.plugin.getConfig().getDouble("Properties.HorizontalCollisionPhysics.WallDamageCap");
final double damage = ((e.getDistanceTraveled() - minimumDistance) < 0 ? 0 : e.getDistanceTraveled() - minimumDistance) / (e.getDifference().length());
if (damage > 0) {
if (damage <= maxDamage) {
DamageHandler.damageEntity(e.getEntity(), damage, e.getAbility());
} else {
DamageHandler.damageEntity(e.getEntity(), maxDamage, e.getAbility());
}
}
}
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onInventoryClick(final InventoryClickEvent event) { public void onInventoryClick(final InventoryClickEvent event) {
for (final MetalClips clips : CoreAbility.getAbilities(MetalClips.class)) { for (final MetalClips clips : CoreAbility.getAbilities(MetalClips.class)) {
@ -768,29 +754,11 @@ public class PKListener implements Listener {
@EventHandler(priority = EventPriority.NORMAL) @EventHandler(priority = EventPriority.NORMAL)
public void onEntityBendingDeath(final EntityBendingDeathEvent event) { public void onEntityBendingDeath(final EntityBendingDeathEvent event) {
BENDING_ENTITY_DEATH.put(event.getEntity(), event.getAbility());
if (event.getEntity() instanceof Player) {
if (ConfigManager.languageConfig.get().getBoolean("DeathMessages.Enabled")) {
final Ability ability = event.getAbility();
if (ability == null) {
return;
}
BENDING_PLAYER_DEATH.put((Player) event.getEntity(), ability.getElement().getColor() + ability.getName());
final Player player = (Player) event.getEntity();
new BukkitRunnable() {
@Override
public void run() {
BENDING_PLAYER_DEATH.remove(player);
}
}.runTaskLater(ProjectKorra.plugin, 20);
}
if (event.getAttacker() != null && ProjectKorra.isStatisticsEnabled()) { if (event.getAttacker() != null && ProjectKorra.isStatisticsEnabled()) {
if (event.getEntity() instanceof Player) {
StatisticsMethods.addStatisticAbility(event.getAttacker().getUniqueId(), CoreAbility.getAbility(event.getAbility().getName()), com.projectkorra.projectkorra.util.Statistic.PLAYER_KILLS, 1); StatisticsMethods.addStatisticAbility(event.getAttacker().getUniqueId(), CoreAbility.getAbility(event.getAbility().getName()), com.projectkorra.projectkorra.util.Statistic.PLAYER_KILLS, 1);
} }
}
if (event.getAttacker() != null && ProjectKorra.isStatisticsEnabled()) {
StatisticsMethods.addStatisticAbility(event.getAttacker().getUniqueId(), CoreAbility.getAbility(event.getAbility().getName()), com.projectkorra.projectkorra.util.Statistic.TOTAL_KILLS, 1); StatisticsMethods.addStatisticAbility(event.getAttacker().getUniqueId(), CoreAbility.getAbility(event.getAbility().getName()), com.projectkorra.projectkorra.util.Statistic.TOTAL_KILLS, 1);
} }
} }
@ -1021,50 +989,24 @@ public class PKListener implements Listener {
armor.revert(); armor.revert();
} }
} }
} else {
// Do nothing. TempArmor drops are handled by the EntityDeath event and not PlayerDeath.
} }
if (event.getEntity().getKiller() != null) { if (event.getEntity().getKiller() == null) {
if (BENDING_PLAYER_DEATH.containsKey(event.getEntity())) { return;
String message = ConfigManager.languageConfig.get().getString("DeathMessages.Default"); } else if (!ConfigManager.languageConfig.get().getBoolean("DeathMessages.Enabled")) {
final String ability = BENDING_PLAYER_DEATH.get(event.getEntity()); return;
final String tempAbility = ChatColor.stripColor(ability).replaceAll(" ", "");
final CoreAbility coreAbil = CoreAbility.getAbility(tempAbility);
Element element = null;
final boolean isAvatarAbility = false;
if (coreAbil != null) {
element = coreAbil.getElement();
} }
if (HorizontalVelocityTracker.hasBeenDamagedByHorizontalVelocity(event.getEntity()) && Arrays.asList(HorizontalVelocityTracker.abils).contains(tempAbility)) { AbilityDamageTimestamp adt = AbilityDamageTimestamp.get(event.getEntity());
if (ConfigManager.languageConfig.get().contains("Abilities." + element.getName() + "." + tempAbility + ".HorizontalVelocityDeath")) {
message = ConfigManager.languageConfig.get().getString("Abilities." + element.getName() + "." + tempAbility + ".HorizontalVelocityDeath"); if (adt == null) {
return;
} }
} else if (element != null) {
if (element instanceof SubElement) { String message = adt.getAbility().getDeathMessage(adt.isVelocityDamage());
element = ((SubElement) element).getParentElement(); String ability = adt.getAbility().getElement().getColor() + adt.getAbility().getName();
} message = message.replace("{victim}", event.getEntity().getDisplayName()).replace("{attacker}", event.getEntity().getKiller().getDisplayName()).replace("{ability}", ability);
if (ConfigManager.languageConfig.get().contains("Abilities." + element.getName() + "." + tempAbility + ".DeathMessage")) {
message = ConfigManager.languageConfig.get().getString("Abilities." + element.getName() + "." + tempAbility + ".DeathMessage");
} else if (ConfigManager.languageConfig.get().contains("Abilities." + element.getName() + ".Combo." + tempAbility + ".DeathMessage")) {
message = ConfigManager.languageConfig.get().getString("Abilities." + element.getName() + ".Combo." + tempAbility + ".DeathMessage");
}
} else {
if (isAvatarAbility) {
if (ConfigManager.languageConfig.get().contains("Abilities.Avatar." + tempAbility + ".DeathMessage")) {
message = ConfigManager.languageConfig.get().getString("Abilities.Avatar." + tempAbility + ".DeathMessage");
}
} else if (ConfigManager.languageConfig.get().contains("Abilities.Avatar.Combo." + tempAbility + ".DeathMessage")) {
message = ConfigManager.languageConfig.get().getString("Abilities.Avatar.Combo." + tempAbility + ".DeathMessage");
}
}
message = message.replace("{victim}", event.getEntity().getName()).replace("{attacker}", event.getEntity().getKiller().getName()).replace("{ability}", ability);
event.setDeathMessage(message); event.setDeathMessage(message);
BENDING_PLAYER_DEATH.remove(event.getEntity());
}
}
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
@ -1219,56 +1161,6 @@ public class PKListener implements Listener {
PassiveManager.registerPassives(event.getPlayer()); PassiveManager.registerPassives(event.getPlayer());
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerKick(final PlayerKickEvent event) {
final Player player = event.getPlayer();
final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
if (ProjectKorra.isStatisticsEnabled()) {
Manager.getManager(StatisticsManager.class).store(player.getUniqueId());
}
if (bPlayer != null) {
GeneralMethods.savePlayer(bPlayer);
if (ProjectKorra.isDatabaseCooldownsEnabled()) {
bPlayer.saveCooldowns();
}
if (TOGGLED_OUT.contains(player.getUniqueId()) && bPlayer.isToggled()) {
TOGGLED_OUT.remove(player.getUniqueId());
}
if (!bPlayer.isToggled()) {
TOGGLED_OUT.add(player.getUniqueId());
}
}
if (Commands.invincible.contains(player.getName())) {
Commands.invincible.remove(player.getName());
}
Preset.unloadPreset(player);
if (TempArmor.hasTempArmor(player)) {
for (final TempArmor armor : TempArmor.getTempArmorList(player)) {
armor.revert();
}
}
if (MetalClips.isControlled(event.getPlayer())) {
MetalClips.removeControlledEnitity(event.getPlayer());
}
MultiAbilityManager.remove(player);
JUMPS.remove(player);
for (final CoreAbility ca : CoreAbility.getAbilities()) {
if (CoreAbility.getAbility(event.getPlayer(), ca.getClass()) != null) {
CoreAbility.getAbility(event.getPlayer(), ca.getClass()).remove();
}
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerMove(final PlayerMoveEvent event) { public void onPlayerMove(final PlayerMoveEvent event) {
if (event.getTo().getX() == event.getFrom().getX() && event.getTo().getY() == event.getFrom().getY() && event.getTo().getZ() == event.getFrom().getZ()) { if (event.getTo().getX() == event.getFrom().getX() && event.getTo().getY() == event.getFrom().getY() && event.getTo().getZ() == event.getFrom().getZ()) {
@ -1962,10 +1854,6 @@ public class PKListener implements Listener {
} }
} }
public static HashMap<Player, String> getBendingPlayerDeath() {
return BENDING_PLAYER_DEATH;
}
public static List<UUID> getRightClickInteract() { public static List<UUID> getRightClickInteract() {
return RIGHT_CLICK_INTERACT; return RIGHT_CLICK_INTERACT;
} }

View file

@ -3,18 +3,15 @@ package com.projectkorra.projectkorra;
import java.util.HashMap; import java.util.HashMap;
import java.util.logging.Logger; import java.util.logging.Logger;
import com.bekvon.bukkit.residence.protection.FlagPermissions;
import co.aikar.timings.lib.MCTiming;
import co.aikar.timings.lib.TimingManager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Statistic; import org.bukkit.Statistic;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import com.bekvon.bukkit.residence.protection.FlagPermissions;
import com.projectkorra.projectkorra.ability.CoreAbility; import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.util.CollisionInitializer; import com.projectkorra.projectkorra.ability.util.CollisionInitializer;
import com.projectkorra.projectkorra.ability.util.CollisionManager; import com.projectkorra.projectkorra.ability.util.CollisionManager;
@ -26,7 +23,6 @@ import com.projectkorra.projectkorra.chiblocking.util.ChiblockingManager;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.configuration.ConfigManager; import com.projectkorra.projectkorra.configuration.ConfigManager;
import com.projectkorra.projectkorra.earthbending.util.EarthbendingManager; import com.projectkorra.projectkorra.earthbending.util.EarthbendingManager;
import com.projectkorra.projectkorra.firebending.util.FirebendingManager;
import com.projectkorra.projectkorra.hooks.PlaceholderAPIHook; import com.projectkorra.projectkorra.hooks.PlaceholderAPIHook;
import com.projectkorra.projectkorra.hooks.WorldGuardFlag; import com.projectkorra.projectkorra.hooks.WorldGuardFlag;
import com.projectkorra.projectkorra.object.Preset; import com.projectkorra.projectkorra.object.Preset;
@ -38,6 +34,9 @@ import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.Updater; import com.projectkorra.projectkorra.util.Updater;
import com.projectkorra.projectkorra.waterbending.util.WaterbendingManager; import com.projectkorra.projectkorra.waterbending.util.WaterbendingManager;
import co.aikar.timings.lib.MCTiming;
import co.aikar.timings.lib.TimingManager;
public class ProjectKorra extends JavaPlugin { public class ProjectKorra extends JavaPlugin {
public static ProjectKorra plugin; public static ProjectKorra plugin;
@ -83,7 +82,6 @@ public class ProjectKorra extends JavaPlugin {
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new AirbendingManager(this), 0, 1); this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new AirbendingManager(this), 0, 1);
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new WaterbendingManager(this), 0, 1); this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new WaterbendingManager(this), 0, 1);
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new EarthbendingManager(this), 0, 1); this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new EarthbendingManager(this), 0, 1);
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new FirebendingManager(this), 0, 1);
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new ChiblockingManager(this), 0, 1); this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new ChiblockingManager(this), 0, 1);
this.revertChecker = this.getServer().getScheduler().runTaskTimerAsynchronously(this, new RevertChecker(this), 0, 200); this.revertChecker = this.getServer().getScheduler().runTaskTimerAsynchronously(this, new RevertChecker(this), 0, 200);
if (ConfigManager.languageConfig.get().getBoolean("Chat.Branding.AutoAnnouncer.Enabled")) { if (ConfigManager.languageConfig.get().getBoolean("Chat.Branding.AutoAnnouncer.Enabled")) {
@ -103,6 +101,23 @@ public class ProjectKorra extends JavaPlugin {
} }
TempBlock.startReversion(); TempBlock.startReversion();
final int autosaveInterval = ConfigManager.defaultConfig.get().getInt("Properties.Autosave.Interval");
final String autosaveMessage = ChatColor.translateAlternateColorCodes('&', ConfigManager.languageConfig.get().getString("Extras.Autosave.Message.Text"));
new BukkitRunnable() {
@Override
public void run() {
if (ConfigManager.languageConfig.get().getBoolean("Extras.Autosave.Message.Enabled")) {
Bukkit.getServer().broadcast(autosaveMessage, ConfigManager.languageConfig.get().getString("Extras.Autosave.Message.Permission"));
}
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
GeneralMethods.savePlayer(BendingPlayer.getBendingPlayer(player));
}
}
}.runTaskTimer(this, autosaveInterval, autosaveInterval);
for (final Player player : Bukkit.getOnlinePlayers()) { for (final Player player : Bukkit.getOnlinePlayers()) {
PKListener.getJumpStatistics().put(player, player.getStatistic(Statistic.JUMP)); PKListener.getJumpStatistics().put(player, player.getStatistic(Statistic.JUMP));

View file

@ -153,4 +153,12 @@ public interface Ability {
* @see BendingPlayer#canBend(CoreAbility) * @see BendingPlayer#canBend(CoreAbility)
*/ */
public Location getLocation(); public Location getLocation();
/**
* The death message is what shows when a player is killed using this ability.
* <br>For formatting: {victim} is the killed player, {attacker} is the killer
* @param horizontalVelocity Whether to get the HorizontalVelocityDeath message or not
* @return the death message for this ability
*/
public String getDeathMessage(boolean velocityImpact);
} }

View file

@ -3,8 +3,11 @@ package com.projectkorra.projectkorra.ability;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.bukkit.Color;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Particle.DustOptions;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -19,6 +22,8 @@ import com.projectkorra.projectkorra.util.ParticleEffect;
public abstract class AirAbility extends ElementalAbility { public abstract class AirAbility extends ElementalAbility {
private static final DustOptions COLOR = new DustOptions(Color.fromRGB(217, 253, 255), 1.12f);
public AirAbility(final Player player) { public AirAbility(final Player player) {
super(player); super(player);
} }
@ -83,6 +88,12 @@ public abstract class AirAbility extends ElementalAbility {
return ParticleEffect.CLOUD; return ParticleEffect.CLOUD;
} else if (particle.equalsIgnoreCase("smallsmoke")) { } else if (particle.equalsIgnoreCase("smallsmoke")) {
return ParticleEffect.SNOW_SHOVEL; return ParticleEffect.SNOW_SHOVEL;
} else if (particle.equalsIgnoreCase("colorsmoke")) {
return ParticleEffect.CLOUD;
} else if (particle.equalsIgnoreCase("colorspell")) {
return ParticleEffect.SPELL_MOB_AMBIENT;
} else if (particle.equalsIgnoreCase("ash")) {
return ParticleEffect.ASH;
} else { } else {
return ParticleEffect.CLOUD; return ParticleEffect.CLOUD;
} }
@ -125,8 +136,19 @@ public abstract class AirAbility extends ElementalAbility {
* @param zOffset The zOffset to use * @param zOffset The zOffset to use
*/ */
public static void playAirbendingParticles(final Location loc, final int amount, final double xOffset, final double yOffset, final double zOffset) { public static void playAirbendingParticles(final Location loc, final int amount, final double xOffset, final double yOffset, final double zOffset) {
if (getConfig().getString("Properties.Air.Particles").equalsIgnoreCase("colorsmoke")) {
ParticleEffect.REDSTONE.display(loc, amount, xOffset, yOffset, zOffset, COLOR);
} else if (getConfig().getString("Properties.Air.Particles").equalsIgnoreCase("colorspell")) {
for (int i = 0; i < amount; i++) {
double x = loc.getX() + 2 * xOffset * (Math.random() - 0.5);
double y = loc.getY() + 2 * yOffset * (Math.random() - 0.5);
double z = loc.getZ() + 2 * zOffset * (Math.random() - 0.5);
loc.getWorld().spawnParticle(Particle.SPELL_MOB_AMBIENT, x, y, z, 0, 98 / 255D, 188 / 255D, 192 / 255D, 1);
}
} else {
getAirbendingParticles().display(loc, amount, xOffset, yOffset, zOffset); getAirbendingParticles().display(loc, amount, xOffset, yOffset, zOffset);
} }
}
/** /**
* Plays the Airbending Sound at a location if enabled in the config. * Plays the Airbending Sound at a location if enabled in the config.

View file

@ -0,0 +1,23 @@
package com.projectkorra.projectkorra.ability;
import org.bukkit.entity.Player;
import com.projectkorra.projectkorra.Element;
public abstract class BlueFireAbility extends FireAbility implements SubAbility {
public BlueFireAbility(final Player player) {
super(player);
}
@Override
public Class<? extends Ability> getParentAbility() {
return FireAbility.class;
}
@Override
public Element getElement() {
return Element.COMBUSTION;
}
}

View file

@ -828,6 +828,18 @@ public abstract class CoreAbility implements Ability {
return ConfigManager.languageConfig.get().getString("Abilities." + elementName + "." + this.getName() + ".Description"); return ConfigManager.languageConfig.get().getString("Abilities." + elementName + "." + this.getName() + ".Description");
} }
@Override
public String getDeathMessage(boolean velocityImpact) {
String message = velocityImpact ? ConfigManager.languageConfig.get().getString("DeathMessages.VelocityImpactDefault") : ConfigManager.languageConfig.get().getString("DeathMessages.Default");
String path = "Abilities." + this.getElement().getName() + (this instanceof ComboAbility ? ".Combo." : ".") + this.getName() + (velocityImpact ? ".VelocityImpactDeath" : ".DeathMessage");
if (ConfigManager.languageConfig.get().contains(path)) {
message = ConfigManager.languageConfig.get().getString(path);
}
return message;
}
public String getMovePreview(final Player player) { public String getMovePreview(final Player player) {
final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player); final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
String displayedMessage = ""; String displayedMessage = "";
@ -1034,6 +1046,19 @@ public abstract class CoreAbility implements Ability {
}); });
} }
/**
* Checks if the ability has a specific attribute, which are case-sensitive
* @param attribute Attribute to check for
* @return true if ability has attribute
*/
public boolean hasAttribute(String attribute) {
if (!ATTRIBUTE_FIELDS.containsKey(this.getClass())) {
return false;
}
return ATTRIBUTE_FIELDS.get(this.getClass()).containsKey(attribute);
}
/** /**
* @return the current FileConfiguration for the plugin * @return the current FileConfiguration for the plugin
*/ */

View file

@ -1,11 +1,7 @@
package com.projectkorra.projectkorra.ability; package com.projectkorra.projectkorra.ability;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
@ -14,21 +10,19 @@ import org.bukkit.Sound;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.projectkorra.projectkorra.BendingPlayer;
import com.projectkorra.projectkorra.Element; import com.projectkorra.projectkorra.Element;
import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra; import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.util.Collision; import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.configuration.ConfigManager; import com.projectkorra.projectkorra.configuration.ConfigManager;
import com.projectkorra.projectkorra.firebending.BlazeArc; import com.projectkorra.projectkorra.firebending.BlazeArc;
import com.projectkorra.projectkorra.util.Information;
import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
public abstract class FireAbility extends ElementalAbility { public abstract class FireAbility extends ElementalAbility {
private static final Map<Location, Information> TEMP_FIRE = new ConcurrentHashMap<Location, Information>();
public FireAbility(final Player player) { public FireAbility(final Player player) {
super(player); super(player);
} }
@ -52,7 +46,7 @@ public abstract class FireAbility extends ElementalAbility {
public void handleCollision(final Collision collision) { public void handleCollision(final Collision collision) {
super.handleCollision(collision); super.handleCollision(collision);
if (collision.isRemovingFirst()) { if (collision.isRemovingFirst()) {
ParticleEffect.BLOCK_CRACK.display(collision.getLocationFirst(), 10, 1, 1, 1, 0.1, Material.FIRE.createBlockData()); ParticleEffect.BLOCK_CRACK.display(collision.getLocationFirst(), 10, 1, 1, 1, 0.1, getFireColor().createBlockData());
} }
} }
@ -64,27 +58,16 @@ public abstract class FireAbility extends ElementalAbility {
return getConfig().getBoolean("Properties.Fire.FireGriefing"); return getConfig().getBoolean("Properties.Fire.FireGriefing");
} }
/** public static TempBlock createTempFire(Location loc, BendingPlayer bPlayer) {
* Creates a fire block meant to replace other blocks but reverts when the TempBlock tb = new TempBlock(loc.getBlock(), getFireColor(bPlayer));
* fire dissipates or is destroyed. tb.setRevertTime(ConfigManager.getConfig().getLong("Properties.Fire.RevertTicks"));
*/ return tb;
public static void createTempFire(final Location loc) {
if (ElementalAbility.isAir(loc.getBlock().getType())) {
loc.getBlock().setType(Material.FIRE);
return;
} }
Information info = new Information();
final long time = getConfig().getLong("Properties.Fire.RevertTicks") + (long) ((new Random()).nextDouble() * getConfig().getLong("Properties.Fire.RevertTicks")); public static TempBlock createTempFire(Block block, BendingPlayer bPlayer) {
if (TEMP_FIRE.containsKey(loc)) { TempBlock tb = new TempBlock(block, getFireColor(bPlayer));
info = TEMP_FIRE.get(loc); tb.setRevertTime(ConfigManager.getConfig().getLong("Properties.Fire.RevertTicks"));
} else { return tb;
info.setBlock(loc.getBlock());
info.setLocation(loc);
info.setState(loc.getBlock().getState());
}
info.setTime(time + System.currentTimeMillis());
loc.getBlock().setType(Material.FIRE);
TEMP_FIRE.put(loc, info);
} }
public double getDayFactor(final double value) { public double getDayFactor(final double value) {
@ -113,10 +96,46 @@ public abstract class FireAbility extends ElementalAbility {
return value; return value;
} }
public static Material getFireColor(final BendingPlayer bPlayer) {
if (bPlayer.hasSubElement(Element.BLUE_FIRE)) {
return Material.SOUL_FIRE;
} else {
return Material.FIRE;
}
}
public Material getFireColor() {
if (bPlayer.hasSubElement(Element.BLUE_FIRE)) {
return Material.SOUL_FIRE;
} else {
return Material.FIRE;
}
}
public static ParticleEffect getFireParticle(final BendingPlayer bPlayer) {
if (bPlayer.hasSubElement(Element.BLUE_FIRE)) {
return ParticleEffect.SOUL_FLAME;
} else {
return ParticleEffect.FLAME;
}
}
public ParticleEffect getFireParticle() {
if (bPlayer.hasSubElement(Element.BLUE_FIRE)) {
return ParticleEffect.SOUL_FLAME;
} else {
return ParticleEffect.FLAME;
}
}
public static ChatColor getSubChatColor() { public static ChatColor getSubChatColor() {
return ChatColor.valueOf(ConfigManager.getConfig().getString("Properties.Chat.Colors.FireSub")); return ChatColor.valueOf(ConfigManager.getConfig().getString("Properties.Chat.Colors.FireSub"));
} }
public static boolean isFire(final Block block) {
return block.getType() == Material.FIRE || block.getType() == Material.SOUL_FIRE;
}
public static boolean isIgnitable(final Block block) { public static boolean isIgnitable(final Block block) {
return block != null ? isIgnitable(block.getType()) : false; return block != null ? isIgnitable(block.getType()) : false;
} }
@ -158,8 +177,16 @@ public abstract class FireAbility extends ElementalAbility {
} }
} }
public static void playFirebendingParticles(final Location loc, final int amount, final double xOffset, final double yOffset, final double zOffset) { public void playFirebendingParticles(final Location loc, final int amount, final double xOffset, final double yOffset, final double zOffset, final double speed) {
ParticleEffect.FLAME.display(loc, amount, xOffset, yOffset, zOffset); getFireParticle().display(loc, amount, xOffset, yOffset, zOffset, speed);
}
public void playFirebendingParticles(final Location loc, final int amount, final double xOffset, final double yOffset, final double zOffset) {
getFireParticle().display(loc, amount, xOffset, yOffset, zOffset, 0.012);
}
public void playFirebendingParticles(final Location loc, final int amount) {
getFireParticle().display(loc, amount, 0, 0, 0, 0.012);
} }
public static void playFirebendingSound(final Location loc) { public static void playFirebendingSound(final Location loc) {
@ -204,47 +231,4 @@ public abstract class FireAbility extends ElementalAbility {
} }
} }
/** Removes all temp fire that no longer needs to be there */
public static void removeFire() {
final Iterator<Location> it = TEMP_FIRE.keySet().iterator();
while (it.hasNext()) {
final Location loc = it.next();
final Information info = TEMP_FIRE.get(loc);
if (info.getLocation().getBlock().getType() != Material.FIRE && !ElementalAbility.isAir(info.getLocation().getBlock().getType())) {
revertTempFire(loc);
} else if (ElementalAbility.isAir(info.getBlock().getType()) || System.currentTimeMillis() > info.getTime()) {
revertTempFire(loc);
}
}
}
/**
* Revert the temp fire at the location if any is there.
*
* @param location The Location
*/
public static void revertTempFire(final Location location) {
if (!TEMP_FIRE.containsKey(location)) {
return;
}
final Information info = TEMP_FIRE.get(location);
if (info.getLocation().getBlock().getType() != Material.FIRE && !ElementalAbility.isAir(info.getLocation().getBlock().getType())) {
if (info.getState().getType().isBurnable() && !info.getState().getType().isOccluding()) {
final ItemStack itemStack = new ItemStack(info.getState().getType(), 1);
info.getState().getBlock().getWorld().dropItemNaturally(info.getLocation(), itemStack);
}
} else {
info.getBlock().setType(info.getState().getType());
info.getBlock().setBlockData(info.getState().getBlockData());
}
TEMP_FIRE.remove(location);
}
public static void stopBending() {
BlazeArc.removeAllCleanup();
for (final Location loc : TEMP_FIRE.keySet()) {
revertTempFire(loc);
}
}
} }

View file

@ -1,9 +1,10 @@
package com.projectkorra.projectkorra.airbending; package com.projectkorra.projectkorra.airbending;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Effect; import org.bukkit.Effect;
@ -26,13 +27,14 @@ import com.projectkorra.projectkorra.BendingPlayer;
import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra; import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.AirAbility; import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.util.Collision; import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.earthbending.lava.LavaFlow; import com.projectkorra.projectkorra.earthbending.lava.LavaFlow;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class AirBlast extends AirAbility { public class AirBlast extends AirAbility {
@ -70,8 +72,9 @@ public class AirBlast extends AirAbility {
private Vector direction; private Vector direction;
private AirBurst source; private AirBurst source;
private Random random; private Random random;
private ArrayList<Block> affectedLevers; private Set<Block> affectedLevers;
private ArrayList<Entity> affectedEntities; private Set<Entity> affectedEntities;
private VelocityBuilder velocity;
public AirBlast(final Player player) { public AirBlast(final Player player) {
super(player); super(player);
@ -116,9 +119,6 @@ public class AirBlast extends AirAbility {
this.setFields(); this.setFields();
this.affectedLevers = new ArrayList<>();
this.affectedEntities = new ArrayList<>();
// prevent the airburst related airblasts from triggering doors/levers/buttons. // prevent the airburst related airblasts from triggering doors/levers/buttons.
this.canOpenDoors = false; this.canOpenDoors = false;
this.canPressButtons = false; this.canPressButtons = false;
@ -151,8 +151,9 @@ public class AirBlast extends AirAbility {
this.isFromOtherOrigin = false; this.isFromOtherOrigin = false;
this.showParticles = true; this.showParticles = true;
this.random = new Random(); this.random = new Random();
this.affectedLevers = new ArrayList<>(); this.affectedLevers = new HashSet<>();
this.affectedEntities = new ArrayList<>(); this.affectedEntities = new HashSet<>();
this.velocity = new VelocityBuilder();
} }
private static void playOriginEffect(final Player player) { private static void playOriginEffect(final Player player) {
@ -198,7 +199,7 @@ public class AirBlast extends AirAbility {
private void advanceLocation() { private void advanceLocation() {
if (this.showParticles) { if (this.showParticles) {
playAirbendingParticles(this.location, this.particles, 0.275F, 0.275F, 0.275F); playAirbendingParticles(this.location, this.particles, 0.4, 0.4, 0.4);
} }
if (this.random.nextInt(4) == 0) { if (this.random.nextInt(4) == 0) {
playAirbendingSound(this.location); playAirbendingSound(this.location);
@ -244,32 +245,21 @@ public class AirBlast extends AirAbility {
knockback *= 1 - this.location.distance(this.origin) / (2 * this.range); knockback *= 1 - this.location.distance(this.origin) / (2 * this.range);
} }
if (GeneralMethods.isSolid(entity.getLocation().add(0, -0.5, 0).getBlock()) && source == null) {
knockback *= 0.85;
}
push.normalize().multiply(knockback); push.normalize().multiply(knockback);
if (Math.abs(entity.getVelocity().dot(push)) > knockback && entity.getVelocity().angle(push) > Math.PI / 3) { if (Math.abs(entity.getVelocity().dot(push)) > knockback * knockback && entity.getVelocity().angle(push) > Math.PI / 3) {
push.normalize().add(entity.getVelocity()).multiply(knockback); push.add(entity.getVelocity());
} }
GeneralMethods.setVelocity(entity, push); CoreAbility source = this;
if (this.source != null) { if (this.source != null) {
new HorizontalVelocityTracker(entity, this.player, 200l, this.source); source = this.source;
} else {
new HorizontalVelocityTracker(entity, this.player, 200l, this);
} }
if (this.damage > 0 && entity instanceof LivingEntity && !entity.equals(this.player) && !this.affectedEntities.contains(entity)) { velocity.direction(push).knockback(knockback).apply(entity, source, true, true);
if (this.source != null) {
DamageHandler.damageEntity(entity, this.damage, this.source);
} else {
DamageHandler.damageEntity(entity, this.damage, this);
}
this.affectedEntities.add(entity); if (this.damage > 0 && entity instanceof LivingEntity && !entity.equals(this.player) && !affectedEntities.contains(entity)) {
DamageHandler.damageEntity(entity, this.damage, source);
} }
if (entity.getFireTicks() > 0) { if (entity.getFireTicks() > 0) {
@ -278,6 +268,7 @@ public class AirBlast extends AirAbility {
entity.setFireTicks(0); entity.setFireTicks(0);
breakBreathbendingHold(entity); breakBreathbendingHold(entity);
this.affectedEntities.add(entity);
} }
@Override @Override
@ -618,11 +609,11 @@ public class AirBlast extends AirAbility {
this.source = source; this.source = source;
} }
public ArrayList<Block> getAffectedLevers() { public Set<Block> getAffectedLevers() {
return this.affectedLevers; return this.affectedLevers;
} }
public ArrayList<Entity> getAffectedEntities() { public Set<Entity> getAffectedEntities() {
return this.affectedEntities; return this.affectedEntities;
} }

View file

@ -18,6 +18,7 @@ import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.avatar.AvatarState; import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class AirShield extends AirAbility { public class AirShield extends AirAbility {
@ -38,6 +39,7 @@ public class AirShield extends AirAbility {
private Random random; private Random random;
private HashMap<Integer, Integer> angles; private HashMap<Integer, Integer> angles;
private boolean dynamicCooldown; private boolean dynamicCooldown;
private VelocityBuilder velocity;
public AirShield(final Player player) { public AirShield(final Player player) {
super(player); super(player);
@ -57,6 +59,7 @@ public class AirShield extends AirAbility {
} }
this.random = new Random(); this.random = new Random();
this.angles = new HashMap<>(); this.angles = new HashMap<>();
this.velocity = new VelocityBuilder();
if (this.bPlayer.isAvatarState() && hasAbility(player, AirShield.class) && this.isToggledByAvatarState) { if (this.bPlayer.isAvatarState() && hasAbility(player, AirShield.class) && this.isToggledByAvatarState) {
getAbility(player, AirShield.class).remove(); getAbility(player, AirShield.class).remove();
@ -160,8 +163,7 @@ public class AirShield extends AirAbility {
} }
} }
velocity.multiply(0.5); this.velocity.direction(velocity).knockback(0.5).apply(entity, this);
GeneralMethods.setVelocity(entity, velocity);
entity.setFallDistance(0); entity.setFallDistance(0);
} }
} }

View file

@ -23,7 +23,7 @@ import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.util.Collision; import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker; import com.projectkorra.projectkorra.util.VelocityBuilder;
import com.projectkorra.projectkorra.waterbending.WaterSpout; import com.projectkorra.projectkorra.waterbending.WaterSpout;
public class AirSuction extends AirAbility { public class AirSuction extends AirAbility {
@ -232,8 +232,7 @@ public class AirSuction extends AirAbility {
push.normalize().add(entity.getVelocity()).multiply(knockback); push.normalize().add(entity.getVelocity()).multiply(knockback);
} }
GeneralMethods.setVelocity(entity, push.normalize().multiply(knockback)); new VelocityBuilder(push).knockback(knockback).apply(entity, this, true, false);
new HorizontalVelocityTracker(entity, this.player, 200l, this);
entity.setFallDistance(0); entity.setFallDistance(0);
if (entity.getFireTicks() > 0) { if (entity.getFireTicks() > 0) {

View file

@ -16,6 +16,7 @@ import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.ability.ElementalAbility;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class Tornado extends AirAbility { public class Tornado extends AirAbility {
@ -40,7 +41,8 @@ public class Tornado extends AirAbility {
private double currentRadius; private double currentRadius;
private Location origin; private Location origin;
private final Random random; private final Random random;
private final Map<Integer, Integer> angles; private final Map<Integer, Double> angles;
private VelocityBuilder velocity;
public Tornado(final Player player) { public Tornado(final Player player) {
super(player); super(player);
@ -55,18 +57,19 @@ public class Tornado extends AirAbility {
this.radius = getConfig().getDouble("Abilities.Air.Tornado.Radius"); this.radius = getConfig().getDouble("Abilities.Air.Tornado.Radius");
this.npcPushFactor = getConfig().getDouble("Abilities.Air.Tornado.NpcPushFactor"); this.npcPushFactor = getConfig().getDouble("Abilities.Air.Tornado.NpcPushFactor");
this.speed = getConfig().getDouble("Abilities.Air.Tornado.Speed"); this.speed = getConfig().getDouble("Abilities.Air.Tornado.Speed");
this.numberOfStreams = (int) (.3 * this.maxHeight); this.numberOfStreams = getConfig().getInt("Abilities.Air.Tornado.StreamCount");
this.currentHeight = 2; this.currentHeight = 2;
this.currentRadius = this.currentHeight / this.maxHeight * this.radius; this.currentRadius = 0;
this.random = new Random(); this.random = new Random();
this.angles = new ConcurrentHashMap<>(); this.angles = new ConcurrentHashMap<>();
this.velocity = new VelocityBuilder();
int angle = 0; double angle = 0;
for (int i = 0; i <= this.maxHeight; i += (int) this.maxHeight / this.numberOfStreams) { for (int i = 0; i <= this.maxHeight; i += (int) this.maxHeight / this.numberOfStreams) {
this.angles.put(i, angle); this.angles.put(i, angle);
angle += 90; angle += 360 / this.numberOfStreams;
if (angle == 360) { if (angle >= 360) {
angle = 0; angle -= 360;
} }
} }
@ -101,7 +104,7 @@ public class Tornado extends AirAbility {
} }
private void rotateTornado() { private void rotateTornado() {
this.origin = this.player.getTargetBlock((HashSet<Material>) null, (int) this.range).getLocation(); this.origin = GeneralMethods.getTargetedLocation(player, range, getTransparentMaterials()).subtract(0, 1, 0);
final double timefactor = this.currentHeight / this.maxHeight; final double timefactor = this.currentHeight / this.maxHeight;
this.currentRadius = timefactor * this.radius; this.currentRadius = timefactor * this.radius;
@ -164,12 +167,8 @@ public class Tornado extends AirAbility {
} }
} }
final Vector velocity = entity.getVelocity().clone(); Vector dir = new Vector(vx, vy, vz);
velocity.setX(vx); this.velocity.direction(dir).knockback(dir.length() * timefactor).apply(entity, this);
velocity.setZ(vz);
velocity.setY(vy);
velocity.multiply(timefactor);
GeneralMethods.setVelocity(entity, velocity);
entity.setFallDistance(0); entity.setFallDistance(0);
breakBreathbendingHold(entity); breakBreathbendingHold(entity);
@ -177,27 +176,34 @@ public class Tornado extends AirAbility {
} }
} }
double x, z;
for (double j = 0; j < currentHeight; j += 0.4) {
for (final int i : this.angles.keySet()) { for (final int i : this.angles.keySet()) {
double x, y, z, factor; if (Math.random() < 0.4) {
continue;
}
double angle = this.angles.get(i); double angle = this.angles.get(i);
angle = Math.toRadians(angle); angle = Math.toRadians(angle);
y = this.origin.getY() + timefactor * i; x = this.origin.getX() + (j / this.maxHeight) * this.radius * Math.cos(angle + j);
factor = i / this.currentHeight; z = this.origin.getZ() + (j / this.maxHeight) * this.radius * Math.sin(angle + j);
x = this.origin.getX() + timefactor * factor * this.currentRadius * Math.cos(angle); final Location effect = new Location(this.origin.getWorld(), x, origin.getY() + j, z);
z = this.origin.getZ() + timefactor * factor * this.currentRadius * Math.sin(angle);
final Location effect = new Location(this.origin.getWorld(), x, y, z);
if (!GeneralMethods.isRegionProtectedFromBuild(this, effect)) { if (!GeneralMethods.isRegionProtectedFromBuild(this, effect)) {
playAirbendingParticles(effect, this.particleCount); playAirbendingParticles(effect, 1, 0.14, 0.14, 0.14);
if (this.random.nextInt(20) == 0) { if (this.random.nextInt(20) == 0) {
playAirbendingSound(effect); playAirbendingSound(effect);
} }
} }
this.angles.put(i, this.angles.get(i) + 25 * (int) this.speed);
} }
} }
}
for (int i : this.angles.keySet()) {
this.angles.put(i, this.angles.get(i) + this.speed * 360 / this.numberOfStreams / 10);
}
this.currentHeight = this.currentHeight > this.maxHeight ? this.maxHeight : this.currentHeight + 1; this.currentHeight = this.currentHeight > this.maxHeight ? this.maxHeight : this.currentHeight + 1;
} }
@ -319,7 +325,7 @@ public class Tornado extends AirAbility {
this.currentRadius = currentRadius; this.currentRadius = currentRadius;
} }
public Map<Integer, Integer> getAngles() { public Map<Integer, Double> getAngles() {
return this.angles; return this.angles;
} }
} }

View file

@ -3,7 +3,6 @@ package com.projectkorra.projectkorra.airbending.combo;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
@ -22,6 +21,8 @@ import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.firebending.combo.FireComboStream; import com.projectkorra.projectkorra.firebending.combo.FireComboStream;
import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class AirSweep extends AirAbility implements ComboAbility { public class AirSweep extends AirAbility implements ComboAbility {
@ -152,7 +153,7 @@ public class AirSweep extends AirAbility implements ComboAbility {
fs.setDensity(1); fs.setDensity(1);
fs.setSpread(0F); fs.setSpread(0F);
fs.setUseNewParticles(true); fs.setUseNewParticles(true);
fs.setParticleEffect(getAirbendingParticles()); fs.setParticleEffect(null);
fs.setCollides(false); fs.setCollides(false);
fs.runTaskTimer(ProjectKorra.plugin, (long) (i / 2.5), 1L); fs.runTaskTimer(ProjectKorra.plugin, (long) (i / 2.5), 1L);
this.tasks.add(fs); this.tasks.add(fs);
@ -187,6 +188,9 @@ public class AirSweep extends AirAbility implements ComboAbility {
return; return;
} }
} }
playAirbendingParticles(loc, 1, 0, 0, 0);
if (i % 3 == 0) { if (i % 3 == 0) {
for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, 2.5)) { for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, 2.5)) {
if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation())) { if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation())) {
@ -196,8 +200,7 @@ public class AirSweep extends AirAbility implements ComboAbility {
if (!entity.equals(this.player) && !(entity instanceof Player && Commands.invincible.contains(((Player) entity).getName()))) { if (!entity.equals(this.player) && !(entity instanceof Player && Commands.invincible.contains(((Player) entity).getName()))) {
if (this.knockback != 0) { if (this.knockback != 0) {
final Vector force = fstream.getLocation().getDirection(); final Vector force = fstream.getLocation().getDirection();
GeneralMethods.setVelocity(entity, force.clone().multiply(this.knockback)); new VelocityBuilder(force).knockback(knockback).apply(entity, this, true, false);
new HorizontalVelocityTracker(entity, this.player, 200l, this);
entity.setFallDistance(0); entity.setFallDistance(0);
} }
if(!this.affectedEntities.contains(entity)) { if(!this.affectedEntities.contains(entity)) {

View file

@ -15,6 +15,7 @@ import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformatio
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class Twister extends AirAbility implements ComboAbility { public class Twister extends AirAbility implements ComboAbility {
@ -146,7 +147,7 @@ public class Twister extends AirAbility implements ComboAbility {
continue; continue;
} }
final Vector forceDir = GeneralMethods.getDirection(entity.getLocation(), this.currentLoc.clone().add(0, height, 0)); final Vector forceDir = GeneralMethods.getDirection(entity.getLocation(), this.currentLoc.clone().add(0, height, 0));
entity.setVelocity(forceDir.clone().normalize().multiply(0.3)); new VelocityBuilder(forceDir).knockback(0.3).apply(entity, this);
} }
} }

View file

@ -24,7 +24,7 @@ public class ToggleCommand extends PKCommand {
private final String toggledOffForAll, toggleOffSelf, toggleOnSelf, toggleOffAll, toggleOnAll, toggledOffSingleElement, toggledOnSingleElement, wrongElementOther, toggledOnOtherElementConfirm, toggledOffOtherElementConfirm, toggledOnOtherElement, toggledOffOtherElement, wrongElement, notFound; private final String toggledOffForAll, toggleOffSelf, toggleOnSelf, toggleOffAll, toggleOnAll, toggledOffSingleElement, toggledOnSingleElement, wrongElementOther, toggledOnOtherElementConfirm, toggledOffOtherElementConfirm, toggledOnOtherElement, toggledOffOtherElement, wrongElement, notFound;
public ToggleCommand() { public ToggleCommand() {
super("toggle", "/bending toggle <All/Element/Player> [Player]", ConfigManager.languageConfig.get().getString("Commands.Toggle.Description"), new String[] { "toggle", "t" }); super("toggle", "/bending toggle <all/<element>> [player]", ConfigManager.languageConfig.get().getString("Commands.Toggle.Description"), new String[] { "toggle", "t" });
final FileConfiguration c = ConfigManager.languageConfig.get(); final FileConfiguration c = ConfigManager.languageConfig.get();

View file

@ -281,6 +281,9 @@ public class WhoCommand extends PKCommand {
if (bPlayer.canLightningbend()) { if (bPlayer.canLightningbend()) {
sender.sendMessage(Element.LIGHTNING.getColor() + " Can Lightningbend"); sender.sendMessage(Element.LIGHTNING.getColor() + " Can Lightningbend");
} }
if (bPlayer.hasSubElement(Element.BLUE_FIRE)) {
sender.sendMessage(Element.BLUE_FIRE.getColor() + " Creates Blue Flames");
}
for (final SubElement se : Element.getAddonSubElements(Element.FIRE)) { for (final SubElement se : Element.getAddonSubElements(Element.FIRE)) {
if (bPlayer.canUseSubElement(se)) { if (bPlayer.canUseSubElement(se)) {
sender.sendMessage(se.getColor() + " Can " + (!se.getType().equals(ElementType.NO_SUFFIX) ? "" : "use ") + se.getName() + se.getType().getBend()); sender.sendMessage(se.getColor() + " Can " + (!se.getType().equals(ElementType.NO_SUFFIX) ? "" : "use ") + se.getName() + se.getType().getBend());

View file

@ -77,6 +77,9 @@ public class ConfigManager {
config.addDefault("Chat.Prefixes.Avatar", "[Avatar]"); config.addDefault("Chat.Prefixes.Avatar", "[Avatar]");
config.addDefault("Chat.Prefixes.Nonbender", "[Nonbender]"); config.addDefault("Chat.Prefixes.Nonbender", "[Nonbender]");
config.addDefault("Extras.Autosave.Message.Enabled", true);
config.addDefault("Extras.Autosave.Message.Text", "&6Autosaving bending player data!");
config.addDefault("Extras.Autosave.Message.Permission", "bending.admin");
config.addDefault("Extras.Water.NightMessage", "Your waterbending has become empowered due to the moon rising."); config.addDefault("Extras.Water.NightMessage", "Your waterbending has become empowered due to the moon rising.");
config.addDefault("Extras.Water.DayMessage", "You feel the empowering of your waterbending subside as the moon sets."); config.addDefault("Extras.Water.DayMessage", "You feel the empowering of your waterbending subside as the moon sets.");
config.addDefault("Extras.Fire.NightMessage", "You feel the empowering of your firebending subside as the sun sets."); config.addDefault("Extras.Fire.NightMessage", "You feel the empowering of your firebending subside as the sun sets.");
@ -235,6 +238,7 @@ public class ConfigManager {
config.addDefault("DeathMessages.Enabled", true); config.addDefault("DeathMessages.Enabled", true);
config.addDefault("DeathMessages.Default", "{victim} was slain by {attacker}'s {ability}"); config.addDefault("DeathMessages.Default", "{victim} was slain by {attacker}'s {ability}");
config.addDefault("DeathMessages.VelocityImpactDefault", "{victim} was thrown by {attacker}'s {ability}");
config.addDefault("Abilities.Avatar.AvatarState.Description", "The signature ability of the Avatar, this is a toggle. Left click to activate to become " + "nearly unstoppable. While in the Avatar State, the user takes severely reduced damage from " + "all sources, regenerates health rapidly, and is granted extreme speed. Nearly all abilities " + "are incredibly amplified in this state. Additionally, AirShield and FireJet become toggle-able " + "abilities and last until you deactivate them or the Avatar State. Left click again with the Avatar " + "State selected to deactivate it."); config.addDefault("Abilities.Avatar.AvatarState.Description", "The signature ability of the Avatar, this is a toggle. Left click to activate to become " + "nearly unstoppable. While in the Avatar State, the user takes severely reduced damage from " + "all sources, regenerates health rapidly, and is granted extreme speed. Nearly all abilities " + "are incredibly amplified in this state. Additionally, AirShield and FireJet become toggle-able " + "abilities and last until you deactivate them or the Avatar State. Left click again with the Avatar " + "State selected to deactivate it.");
@ -242,11 +246,11 @@ public class ConfigManager {
config.addDefault("Abilities.Air.AirBlast.Description", "AirBlast is the most fundamental bending technique of an airbender. It allows the bender to be extremely agile and possess great mobility, but also has many utility options, such as cooling lava, opening doors and flicking levers."); config.addDefault("Abilities.Air.AirBlast.Description", "AirBlast is the most fundamental bending technique of an airbender. It allows the bender to be extremely agile and possess great mobility, but also has many utility options, such as cooling lava, opening doors and flicking levers.");
config.addDefault("Abilities.Air.AirBlast.Instructions", "\n" + "(Push) " + "Left click while aiming at an entity to push them back." + "\n" + "(Throw) " + "Tap sneak to select a location and left click in a direction to throw entities away from the selected location."); config.addDefault("Abilities.Air.AirBlast.Instructions", "\n" + "(Push) " + "Left click while aiming at an entity to push them back." + "\n" + "(Throw) " + "Tap sneak to select a location and left click in a direction to throw entities away from the selected location.");
config.addDefault("Abilities.Air.AirBlast.DeathMessage", "{victim} was flung by {attacker}'s {ability}"); config.addDefault("Abilities.Air.AirBlast.DeathMessage", "{victim} was flung by {attacker}'s {ability}");
config.addDefault("Abilities.Air.AirBlast.HorizontalVelocityDeath", "{victim} experienced a fatal collision by {attacker}'s {ability}"); config.addDefault("Abilities.Air.AirBlast.VelocityImpactDeath", "{victim} experienced a fatal collision by {attacker}'s {ability}");
config.addDefault("Abilities.Air.AirBurst.Description", "AirBurst is one of the most powerful abilities in the airbender's arsenal. It allows the bender to create space between them and whoever is close to them. AirBurst is extremely useful when you're surrounded by mobs, of if you're low in health and need to escape. It can also be useful for confusing your target also."); config.addDefault("Abilities.Air.AirBurst.Description", "AirBurst is one of the most powerful abilities in the airbender's arsenal. It allows the bender to create space between them and whoever is close to them. AirBurst is extremely useful when you're surrounded by mobs, of if you're low in health and need to escape. It can also be useful for confusing your target also.");
config.addDefault("Abilities.Air.AirBurst.Instructions", "\n" + "(Sphere) Hold sneak until particles appear and then release shift to create air that expands outwards, pushing entities back. If you fall from great height while you are on this slot, the burst will automatically activate." + "\n" + "(Cone) While charging the move with shift, click to send the burst in a cone only going in one direction."); config.addDefault("Abilities.Air.AirBurst.Instructions", "\n" + "(Sphere) Hold sneak until particles appear and then release shift to create air that expands outwards, pushing entities back. If you fall from great height while you are on this slot, the burst will automatically activate." + "\n" + "(Cone) While charging the move with shift, click to send the burst in a cone only going in one direction.");
config.addDefault("Abilities.Air.AirBurst.DeathMessage", "{victim} was thrown down by {attacker}'s {ability}"); config.addDefault("Abilities.Air.AirBurst.DeathMessage", "{victim} was thrown down by {attacker}'s {ability}");
config.addDefault("Abilities.Air.AirBurst.HorizontalVelocityDeath", "{victim} experienced a fatal collision by {attacker}'s {ability}"); config.addDefault("Abilities.Air.AirBurst.VelocityImpactDeath", "{victim} experienced a fatal collision by {attacker}'s {ability}");
config.addDefault("Abilities.Air.AirScooter.Description", "AirScooter is a fast means of transportation. It can be used to escape from enemies or confuse them by using air scooter around them."); config.addDefault("Abilities.Air.AirScooter.Description", "AirScooter is a fast means of transportation. It can be used to escape from enemies or confuse them by using air scooter around them.");
config.addDefault("Abilities.Air.AirScooter.Instructions", "Sprint, jump, and left click while in the air to activate air scooter. You will then move forward in the direction you're looking."); config.addDefault("Abilities.Air.AirScooter.Instructions", "Sprint, jump, and left click while in the air to activate air scooter. You will then move forward in the direction you're looking.");
config.addDefault("Abilities.Air.Tornado.Description", "Tornado is one of the most powerful and advanced abilities that an Airbender knows. If the tornado meets a player or mob, it will push them around. Tornado can also be used to push back projectiles and used for mobility. Use a tornado directly under you to propel yourself upwards."); config.addDefault("Abilities.Air.Tornado.Description", "Tornado is one of the most powerful and advanced abilities that an Airbender knows. If the tornado meets a player or mob, it will push them around. Tornado can also be used to push back projectiles and used for mobility. Use a tornado directly under you to propel yourself upwards.");
@ -257,7 +261,7 @@ public class ConfigManager {
config.addDefault("Abilities.Air.AirSpout.Instructions", "Left click to activate a spout beneath you and hold spacebar to go higher. If you wish to go lower, simply hold sneak. To disable this ability, left click once again."); config.addDefault("Abilities.Air.AirSpout.Instructions", "Left click to activate a spout beneath you and hold spacebar to go higher. If you wish to go lower, simply hold sneak. To disable this ability, left click once again.");
config.addDefault("Abilities.Air.AirSuction.Description", "AirSuction is a basic ability that allows you to manipulation an entity's movement. It can be used to bring someone back to you when they're running away, or even to get yourself to great heights."); config.addDefault("Abilities.Air.AirSuction.Description", "AirSuction is a basic ability that allows you to manipulation an entity's movement. It can be used to bring someone back to you when they're running away, or even to get yourself to great heights.");
config.addDefault("Abilities.Air.AirSuction.Instructions", "\n" + "(Pull) Left click while aiming at a target to pull them towards you." + "\n" + "(Manipulation) Sneak to select a point and then left click at a target or yourself to send you or your target to the point that you selected."); config.addDefault("Abilities.Air.AirSuction.Instructions", "\n" + "(Pull) Left click while aiming at a target to pull them towards you." + "\n" + "(Manipulation) Sneak to select a point and then left click at a target or yourself to send you or your target to the point that you selected.");
config.addDefault("Abilities.Air.AirSuction.HorizontalVelocityDeath", "{victim} experienced a fatal collision by {attacker}'s {ability}"); config.addDefault("Abilities.Air.AirSuction.VelocityImpactDeath", "{victim} experienced a fatal collision by {attacker}'s {ability}");
config.addDefault("Abilities.Air.AirSwipe.Description", "AirSwipe is the most commonly used damage ability in an airbender's arsenal. An arc of air will flow from you towards the direction you're facing, cutting and pushing back anything in its path. This ability will extinguish fires, cool lava, and cut things like grass, mushrooms, and flowers."); config.addDefault("Abilities.Air.AirSwipe.Description", "AirSwipe is the most commonly used damage ability in an airbender's arsenal. An arc of air will flow from you towards the direction you're facing, cutting and pushing back anything in its path. This ability will extinguish fires, cool lava, and cut things like grass, mushrooms, and flowers.");
config.addDefault("Abilities.Air.AirSwipe.Instructions", "\n" + "(Uncharged) Simply left click to send an air swipe out that will damage targets that it comes into contact with." + "\n" + "(Charged) Hold sneak until particles appear, then release sneak to send a more powerful air swipe out that damages entity's that it comes into contact with."); config.addDefault("Abilities.Air.AirSwipe.Instructions", "\n" + "(Uncharged) Simply left click to send an air swipe out that will damage targets that it comes into contact with." + "\n" + "(Charged) Hold sneak until particles appear, then release sneak to send a more powerful air swipe out that damages entity's that it comes into contact with.");
config.addDefault("Abilities.Air.AirSwipe.DeathMessage", "{victim} was struck by {attacker}'s {ability}"); config.addDefault("Abilities.Air.AirSwipe.DeathMessage", "{victim} was struck by {attacker}'s {ability}");
@ -273,6 +277,7 @@ public class ConfigManager {
config.addDefault("Abilities.Air.Combo.AirSweep.Description", "Sweep the air in front of you hitting multiple enemies, causing moderate damage and a large knockback. The radius and direction of AirSweep is controlled by moving your mouse in a sweeping motion. For example, if you want to AirSweep upward, then move your mouse upward right after you left click AirBurst"); config.addDefault("Abilities.Air.Combo.AirSweep.Description", "Sweep the air in front of you hitting multiple enemies, causing moderate damage and a large knockback. The radius and direction of AirSweep is controlled by moving your mouse in a sweeping motion. For example, if you want to AirSweep upward, then move your mouse upward right after you left click AirBurst");
config.addDefault("Abilities.Air.Combo.AirSweep.DeathMessage", "{victim} was swept away by {attacker}'s {ability}"); config.addDefault("Abilities.Air.Combo.AirSweep.DeathMessage", "{victim} was swept away by {attacker}'s {ability}");
config.addDefault("Abilities.Air.Combo.AirSweep.Instructions", "AirSwipe (Left Click) > AirSwipe (Left Click) > AirBurst (Hold Shift) > AirBurst (Left Click)"); config.addDefault("Abilities.Air.Combo.AirSweep.Instructions", "AirSwipe (Left Click) > AirSwipe (Left Click) > AirBurst (Hold Shift) > AirBurst (Left Click)");
config.addDefault("Abilities.Air.Combo.AirSweep.VelocityImpactDeath", "{attacker}'s {ability} flung {victim} into a hard surface");
config.addDefault("Abilities.Air.Passive.AirAgility.Description", "AirAgility is a passive ability which enables airbenders to run faster and jump higher."); config.addDefault("Abilities.Air.Passive.AirAgility.Description", "AirAgility is a passive ability which enables airbenders to run faster and jump higher.");
config.addDefault("Abilities.Air.Passive.AirSaturation.Description", "AirSaturation is a passive ability which causes airbenders' hunger to deplete at a slower rate."); config.addDefault("Abilities.Air.Passive.AirSaturation.Description", "AirSaturation is a passive ability which causes airbenders' hunger to deplete at a slower rate.");
config.addDefault("Abilities.Air.Passive.GracefulDescent.Description", "GracefulDescent is a passive ability which allows airbenders to make a gentle landing, negating all fall damage on any surface."); config.addDefault("Abilities.Air.Passive.GracefulDescent.Description", "GracefulDescent is a passive ability which allows airbenders to make a gentle landing, negating all fall damage on any surface.");
@ -297,6 +302,7 @@ public class ConfigManager {
config.addDefault("Abilities.Water.PhaseChange.Instructions", "\n" + "(Melt) To melt ice, hold sneak while looking at an ice block." + "\n" + "(Freeze) To freeze water and turn it into ice, simply left click at water. This ice will stay so long as you are in range, otherwise it will revert back to water. This only freezes the top layer of ice."); config.addDefault("Abilities.Water.PhaseChange.Instructions", "\n" + "(Melt) To melt ice, hold sneak while looking at an ice block." + "\n" + "(Freeze) To freeze water and turn it into ice, simply left click at water. This ice will stay so long as you are in range, otherwise it will revert back to water. This only freezes the top layer of ice.");
config.addDefault("Abilities.Water.Surge.Description", "Surge offers great utility and is one of the most important defence abilities for waterbender's. It can be used to push entities back, used to push yourself in a direction, trap entities and protect yourself with a shield."); config.addDefault("Abilities.Water.Surge.Description", "Surge offers great utility and is one of the most important defence abilities for waterbender's. It can be used to push entities back, used to push yourself in a direction, trap entities and protect yourself with a shield.");
config.addDefault("Abilities.Water.Surge.Instructions", "\n" + "(Shield) Left click on a water source and then hold sneak while looking up to create a water shield that will move wherever you look. Additionally, you can left click to turn this shield into ice. If you let go of sneak at any point, this ability will cancel." + "\n" + "(Surge) Tap sneak at a water source and click in a direction to fire a surge of water that will knock entities back. Additionally, if you tap sneak again before the surge reaches an entity, when it hits them it will encase them in ice."); config.addDefault("Abilities.Water.Surge.Instructions", "\n" + "(Shield) Left click on a water source and then hold sneak while looking up to create a water shield that will move wherever you look. Additionally, you can left click to turn this shield into ice. If you let go of sneak at any point, this ability will cancel." + "\n" + "(Surge) Tap sneak at a water source and click in a direction to fire a surge of water that will knock entities back. Additionally, if you tap sneak again before the surge reaches an entity, when it hits them it will encase them in ice.");
config.addDefault("Abilities.Water.Surge.VelocityImpactDeath", "{victim} was crushed by {attacker}'s {ability}");
config.addDefault("Abilities.Water.Torrent.Description", "Torrent is one of the strongest moves in a waterbender's arsenal. It has the potential to do immense damage and to be comboed with other abilities to perform a deal a large damage burst. Torrent is fundamental for waterbender's. "); config.addDefault("Abilities.Water.Torrent.Description", "Torrent is one of the strongest moves in a waterbender's arsenal. It has the potential to do immense damage and to be comboed with other abilities to perform a deal a large damage burst. Torrent is fundamental for waterbender's. ");
config.addDefault("Abilities.Water.Torrent.Instructions", "\n" + "(Torrent) Left click at a water source and hold sneak to form the torrent. Then, left click and the torrent will shoot out, moving in the direction you're looking. If the torrent hits an entity, it can drag them and deal damage. Additionally, if you left click before the torrent hits a surface or entity it will freeze on impact." + "\n" + "(Wave) Left click a water source and hold sneak to form a torrent around you. Then, release sneak to send a wave of water expanding outwards every direction that will push entities back."); config.addDefault("Abilities.Water.Torrent.Instructions", "\n" + "(Torrent) Left click at a water source and hold sneak to form the torrent. Then, left click and the torrent will shoot out, moving in the direction you're looking. If the torrent hits an entity, it can drag them and deal damage. Additionally, if you left click before the torrent hits a surface or entity it will freeze on impact." + "\n" + "(Wave) Left click a water source and hold sneak to form a torrent around you. Then, release sneak to send a wave of water expanding outwards every direction that will push entities back.");
config.addDefault("Abilities.Water.Torrent.DeathMessage", "{victim} was washed away by {attacker}'s {ability}"); config.addDefault("Abilities.Water.Torrent.DeathMessage", "{victim} was washed away by {attacker}'s {ability}");
@ -345,6 +351,7 @@ public class ConfigManager {
config.addDefault("Abilities.Earth.EarthSmash.Description", "EarthSmash is an advanced earthbending technique that has lots of utility. It can be comboed with abilities such as Shockwave, but also be used for mobility and to produce high damage. EarthSmash is great for escaping when at low health."); config.addDefault("Abilities.Earth.EarthSmash.Description", "EarthSmash is an advanced earthbending technique that has lots of utility. It can be comboed with abilities such as Shockwave, but also be used for mobility and to produce high damage. EarthSmash is great for escaping when at low health.");
config.addDefault("Abilities.Earth.EarthSmash.Instructions", "\n" + "(Smash) Hold sneak until particles appear, then release sneak while looking at an earthbendable block which will raise an earth boulder. Then, hold sneak while looking at this boulder to control it. Left click to send the bounder in the direction you're facing, damanging entities and knocking them back." + "\n" + "(Ride) After you have created an earth boulder, hold sneak and right click on the boulder to ride it. You will now ride the boulder in whatever direction you look. Additionally, you can ride the boulder by going on top of it and holding sneak. If you come into contact with an entity while riding the boulder, it will drag them along with you. If you left go of sneak, the ability will cancel."); config.addDefault("Abilities.Earth.EarthSmash.Instructions", "\n" + "(Smash) Hold sneak until particles appear, then release sneak while looking at an earthbendable block which will raise an earth boulder. Then, hold sneak while looking at this boulder to control it. Left click to send the bounder in the direction you're facing, damanging entities and knocking them back." + "\n" + "(Ride) After you have created an earth boulder, hold sneak and right click on the boulder to ride it. You will now ride the boulder in whatever direction you look. Additionally, you can ride the boulder by going on top of it and holding sneak. If you come into contact with an entity while riding the boulder, it will drag them along with you. If you left go of sneak, the ability will cancel.");
config.addDefault("Abilities.Earth.EarthSmash.DeathMessage", "{victim} was crushed by {attacker}'s {ability}"); config.addDefault("Abilities.Earth.EarthSmash.DeathMessage", "{victim} was crushed by {attacker}'s {ability}");
config.addDefault("Abilities.Earth.EarthSmash.VelocityImpactDeath", "{victim} was launched by {attacker}'s {ability}");
config.addDefault("Abilities.Earth.MetalClips.Description", "MetalClips is an advanced metalbending ability that allows you to take control of a fight. It gives the metalbender the ability to control an entity, create space between them and a player and even added utility."); config.addDefault("Abilities.Earth.MetalClips.Description", "MetalClips is an advanced metalbending ability that allows you to take control of a fight. It gives the metalbender the ability to control an entity, create space between them and a player and even added utility.");
config.addDefault("Abilities.Earth.MetalClips.Instructions", "\n" + "(Clips) This ability requires iron ingots in your inventory. Left click to throw an ingot at an entity, dealing damage to them. This ingot will form into armor, wrapping itself around the entity. Once enough armor pieces are around the entity, you can then control them. To control them, hold sneak while looking at them and then they will be moved in the direction you look. Additionally, you can release sneak to throw them in the direction you're looking." + "\n" + "(Magnet) Hold sneak with this ability to pull iron ingots towards you."); config.addDefault("Abilities.Earth.MetalClips.Instructions", "\n" + "(Clips) This ability requires iron ingots in your inventory. Left click to throw an ingot at an entity, dealing damage to them. This ingot will form into armor, wrapping itself around the entity. Once enough armor pieces are around the entity, you can then control them. To control them, hold sneak while looking at them and then they will be moved in the direction you look. Additionally, you can release sneak to throw them in the direction you're looking." + "\n" + "(Magnet) Hold sneak with this ability to pull iron ingots towards you.");
config.addDefault("Abilities.Earth.MetalClips.DeathMessage", "{victim} was too slow for {attacker}'s {ability}"); config.addDefault("Abilities.Earth.MetalClips.DeathMessage", "{victim} was too slow for {attacker}'s {ability}");
@ -353,6 +360,7 @@ public class ConfigManager {
config.addDefault("Abilities.Earth.Shockwave.Description", "Shockwave is one of the most powerful earthbending abilities. It allows the earthbender to deal mass damage to everyone around them and knock them back. It's extremely useful when fighting more than one target or if you're surrounded by mobs."); config.addDefault("Abilities.Earth.Shockwave.Description", "Shockwave is one of the most powerful earthbending abilities. It allows the earthbender to deal mass damage to everyone around them and knock them back. It's extremely useful when fighting more than one target or if you're surrounded by mobs.");
config.addDefault("Abilities.Earth.Shockwave.Instructions", "Hold sneak until you see particles and then release sneak to send a wave of earth outwards, damaging and knocking entities back that it collides with. Additionally, instead of releasing sneak you can send a cone of earth forwards by left clicking. If you are on the Shockwave slot and you fall from a great height, your Shockwave will automatically activate."); config.addDefault("Abilities.Earth.Shockwave.Instructions", "Hold sneak until you see particles and then release sneak to send a wave of earth outwards, damaging and knocking entities back that it collides with. Additionally, instead of releasing sneak you can send a cone of earth forwards by left clicking. If you are on the Shockwave slot and you fall from a great height, your Shockwave will automatically activate.");
config.addDefault("Abilities.Earth.Shockwave.DeathMessage", "{victim} was blown away by {attacker}'s {ability}"); config.addDefault("Abilities.Earth.Shockwave.DeathMessage", "{victim} was blown away by {attacker}'s {ability}");
config.addDefault("Abilities.Earth.Shockwave.VelocityImpactDeath", "{victim} was shell-shocked {attacker}'s {ability}");
config.addDefault("Abilities.Earth.Tremorsense.Description", "This is a pure utility ability for earthbenders. If you are in an area of low-light and are standing on top of an earthbendable block, this ability will automatically turn that block into glowstone, visible *only by you*. If you lose contact with a bendable block, the light will go out as you have lost contact with the earth and cannot 'see' until you can touch earth again. Additionally, if you click with this ability selected, smoke will appear above nearby earth with pockets of air beneath them."); config.addDefault("Abilities.Earth.Tremorsense.Description", "This is a pure utility ability for earthbenders. If you are in an area of low-light and are standing on top of an earthbendable block, this ability will automatically turn that block into glowstone, visible *only by you*. If you lose contact with a bendable block, the light will go out as you have lost contact with the earth and cannot 'see' until you can touch earth again. Additionally, if you click with this ability selected, smoke will appear above nearby earth with pockets of air beneath them.");
config.addDefault("Abilities.Earth.Tremorsense.Instructions", "Simply left click while on an earthbendable block."); config.addDefault("Abilities.Earth.Tremorsense.Instructions", "Simply left click while on an earthbendable block.");
config.addDefault("Abilities.Earth.Combo.EarthDome.Description", "EarthDome allows earthbenders to surround themselves or another entity in earth, temporarily preventing anything from entering or escaping the dome."); config.addDefault("Abilities.Earth.Combo.EarthDome.Description", "EarthDome allows earthbenders to surround themselves or another entity in earth, temporarily preventing anything from entering or escaping the dome.");
@ -549,11 +557,16 @@ public class ConfigManager {
config.addDefault("Properties.SeaLevel", 62); config.addDefault("Properties.SeaLevel", 62);
config.addDefault("Properties.ChooseCooldown", 0L); config.addDefault("Properties.ChooseCooldown", 0L);
config.addDefault("Properties.MaxPresets", 10); config.addDefault("Properties.MaxPresets", 10);
config.addDefault("Properties.AbilityDamageTimestampDuration", 5000);
config.addDefault("Properties.HorizontalCollisionPhysics.Enabled", true); config.addDefault("Properties.Autosave.Interval", 6000);
config.addDefault("Properties.HorizontalCollisionPhysics.DamageOnBarrierBlock", false);
config.addDefault("Properties.HorizontalCollisionPhysics.WallDamageMinimumDistance", 5.0); config.addDefault("Properties.CollisionPhysics.Enabled", true);
config.addDefault("Properties.HorizontalCollisionPhysics.WallDamageCap", 5.0); config.addDefault("Properties.CollisionPhysics.ImpactOnBarrierBlock", false);
config.addDefault("Properties.CollisionPhysics.ImpactMinimumDistance", 5.0);
config.addDefault("Properties.CollisionPhysics.ImpactDamageCap", 5.0);
config.addDefault("Properties.CollisionPhysics.ImpactDamageFactor", 0.42);
config.addDefault("Properties.CollisionPhysics.VelocityChangeThreshold", 0.52);
config.addDefault("Properties.RegionProtection.AllowHarmlessAbilities", true); config.addDefault("Properties.RegionProtection.AllowHarmlessAbilities", true);
config.addDefault("Properties.RegionProtection.RespectWorldGuard", true); config.addDefault("Properties.RegionProtection.RespectWorldGuard", true);
@ -900,6 +913,7 @@ public class ConfigManager {
config.addDefault("Abilities.Air.Tornado.Speed", 1); config.addDefault("Abilities.Air.Tornado.Speed", 1);
config.addDefault("Abilities.Air.Tornado.NpcPushFactor", 1); config.addDefault("Abilities.Air.Tornado.NpcPushFactor", 1);
config.addDefault("Abilities.Air.Tornado.PlayerPushFactor", 1); config.addDefault("Abilities.Air.Tornado.PlayerPushFactor", 1);
config.addDefault("Abilities.Air.Tornado.StreamCount", 3);
config.addDefault("Abilities.Air.Twister.Enabled", true); config.addDefault("Abilities.Air.Twister.Enabled", true);
config.addDefault("Abilities.Air.Twister.Speed", 0.35); config.addDefault("Abilities.Air.Twister.Speed", 0.35);
@ -1317,6 +1331,8 @@ public class ConfigManager {
config.addDefault("Abilities.Earth.EarthPillars.Damage.Value", 2); config.addDefault("Abilities.Earth.EarthPillars.Damage.Value", 2);
config.addDefault("Abilities.Earth.EarthPillars.FallThreshold", 12); config.addDefault("Abilities.Earth.EarthPillars.FallThreshold", 12);
config.addDefault("Abilities.Fire.Passives.BlueFlames.DamageMultiplier", 1.3);
config.addDefault("Abilities.Fire.Blaze.Enabled", true); config.addDefault("Abilities.Fire.Blaze.Enabled", true);
config.addDefault("Abilities.Fire.Blaze.Arc", 14); config.addDefault("Abilities.Fire.Blaze.Arc", 14);
config.addDefault("Abilities.Fire.Blaze.Range", 7); config.addDefault("Abilities.Fire.Blaze.Range", 7);

View file

@ -24,6 +24,7 @@ import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class EarthSmash extends EarthAbility { public class EarthSmash extends EarthAbility {
@ -76,6 +77,7 @@ public class EarthSmash extends EarthAbility {
private ArrayList<Entity> affectedEntities; private ArrayList<Entity> affectedEntities;
private ArrayList<BlockRepresenter> currentBlocks; private ArrayList<BlockRepresenter> currentBlocks;
private ArrayList<TempBlock> affectedBlocks; private ArrayList<TempBlock> affectedBlocks;
private VelocityBuilder velocity;
public EarthSmash(final Player player, final ClickType type) { public EarthSmash(final Player player, final ClickType type) {
super(player); super(player);
@ -87,6 +89,7 @@ public class EarthSmash extends EarthAbility {
this.affectedEntities = new ArrayList<>(); this.affectedEntities = new ArrayList<>();
this.currentBlocks = new ArrayList<>(); this.currentBlocks = new ArrayList<>();
this.affectedBlocks = new ArrayList<>(); this.affectedBlocks = new ArrayList<>();
this.velocity = new VelocityBuilder();
if (type == ClickType.SHIFT_DOWN || type == ClickType.SHIFT_UP && !player.isSneaking()) { if (type == ClickType.SHIFT_DOWN || type == ClickType.SHIFT_UP && !player.isSneaking()) {
final EarthSmash flySmash = flyingInSmashCheck(player); final EarthSmash flySmash = flyingInSmashCheck(player);
@ -293,7 +296,8 @@ public class EarthSmash extends EarthAbility {
if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) { if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || ((entity instanceof Player) && Commands.invincible.contains(((Player) entity).getName()))) {
continue; continue;
} }
entity.setVelocity(direction.clone().multiply(this.flightSpeed));
velocity.direction(direction).knockback(this.flightSpeed).apply(entity, this);
} }
// These values tend to work well when dealing with a person aiming upward or downward. // These values tend to work well when dealing with a person aiming upward or downward.
@ -573,7 +577,7 @@ public class EarthSmash extends EarthAbility {
final double damage = this.currentBlocks.size() / 13.0 * this.damage; final double damage = this.currentBlocks.size() / 13.0 * this.damage;
DamageHandler.damageEntity(entity, damage, this); DamageHandler.damageEntity(entity, damage, this);
final Vector travelVec = GeneralMethods.getDirection(this.location, entity.getLocation()); final Vector travelVec = GeneralMethods.getDirection(this.location, entity.getLocation());
entity.setVelocity(travelVec.setY(this.knockup).normalize().multiply(this.knockback)); velocity.direction(travelVec).knockback(this.knockback).knockup(this.knockup).apply(entity, this, true, true);
} }
} }
} }

View file

@ -20,6 +20,7 @@ import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.avatar.AvatarState; import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class Ripple extends EarthAbility { public class Ripple extends EarthAbility {
@ -283,9 +284,8 @@ public class Ripple extends EarthAbility {
} }
final Vector vector = this.direction.clone(); final Vector vector = this.direction.clone();
vector.setY(.5);
final double knock = this.bPlayer.isAvatarState() ? AvatarState.getValue(this.knockback) : this.knockback; final double knock = this.bPlayer.isAvatarState() ? AvatarState.getValue(this.knockback) : this.knockback;
entity.setVelocity(vector.clone().normalize().multiply(knock)); new VelocityBuilder(vector).knockback(knock).knockup(0.5).apply(entity, this, true, false);
AirAbility.breakBreathbendingHold(entity); AirAbility.breakBreathbendingHold(entity);
} }

View file

@ -22,7 +22,6 @@ public class AbilityDamageEntityEvent extends Event implements Cancellable {
private final Entity entity; private final Entity entity;
private final Ability ability; private final Ability ability;
private double damage; private double damage;
private final boolean ignoreArmor;
/** /**
* Create a new AbilityDamageEntityEvent * Create a new AbilityDamageEntityEvent
@ -31,11 +30,10 @@ public class AbilityDamageEntityEvent extends Event implements Cancellable {
* @param ability The damaging ability * @param ability The damaging ability
* @param damage The amount of damage done * @param damage The amount of damage done
*/ */
public AbilityDamageEntityEvent(final Entity entity, final Ability ability, final double damage, final boolean ignoreArmor) { public AbilityDamageEntityEvent(final Entity entity, final Ability ability, final double damage) {
this.entity = entity; this.entity = entity;
this.ability = ability; this.ability = ability;
this.damage = damage; this.damage = damage;
this.ignoreArmor = ignoreArmor;
} }
/** /**
@ -74,10 +72,6 @@ public class AbilityDamageEntityEvent extends Event implements Cancellable {
return this.ability; return this.ability;
} }
public boolean doesIgnoreArmor() {
return this.ignoreArmor;
}
/** /**
* Gets the player that used the ability * Gets the player that used the ability
* *

View file

@ -5,13 +5,10 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.HandlerList; import org.bukkit.event.HandlerList;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.Ability; import com.projectkorra.projectkorra.ability.Ability;
/** /**
* Called when an entity is killed by * Called when an entity is killed by Bending
* {@link GeneralMethods#damageEntity(Player player, Entity entity, double damage, String ability)
* GeneralMethods.damageEntity}
*/ */
public class EntityBendingDeathEvent extends Event { public class EntityBendingDeathEvent extends Event {
@ -19,20 +16,16 @@ public class EntityBendingDeathEvent extends Event {
public static final HandlerList handlers = new HandlerList(); public static final HandlerList handlers = new HandlerList();
private final Entity entity; private final Entity entity;
private final Ability ability; private final Ability ability;
private final double damage;
/** /**
* Creates a new EntityBendingDeathEvent * Creates a new EntityBendingDeathEvent
* *
* @param entity the entity who died * @param entity the entity who died
* @param damage the amount of damage done in the attack that killed the
* victim
* @param ability the ability used to kill the entity * @param ability the ability used to kill the entity
*/ */
public EntityBendingDeathEvent(final Entity entity, final double damage, final Ability ability) { public EntityBendingDeathEvent(final Entity entity, final Ability ability) {
this.entity = entity; this.entity = entity;
this.ability = ability; this.ability = ability;
this.damage = damage;
} }
/** /**
@ -59,14 +52,6 @@ public class EntityBendingDeathEvent extends Event {
return this.ability; return this.ability;
} }
/**
*
* @return the amount of damage done in the attack that killed the victim
*/
public double getDamage() {
return this.damage;
}
@Override @Override
public HandlerList getHandlers() { public HandlerList getHandlers() {
return handlers; return handlers;

View file

@ -1,108 +0,0 @@
package com.projectkorra.projectkorra.event;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.ability.Ability;
/**
* Created by Carbogen on 2/2/2015.
*/
public class HorizontalVelocityChangeEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean isCancelled;
private final Entity entity;
private final Player instigator;
private final Vector from;
private final Vector to;
private final Vector difference;
private Location start;
private Location end;
private Ability abil;
@Deprecated
public HorizontalVelocityChangeEvent(final Entity entity, final Player instigator, final Vector from, final Vector to, final Vector difference) {
this.entity = entity;
this.instigator = instigator;
this.from = from;
this.to = to;
this.difference = difference;
}
public HorizontalVelocityChangeEvent(final Entity entity, final Player instigator, final Vector from, final Vector to, final Vector difference, final Location start, final Location end, final Ability ability) {
this.entity = entity;
this.instigator = instigator;
this.from = from;
this.to = to;
this.difference = difference;
this.start = start;
this.end = end;
this.abil = ability;
}
public Entity getEntity() {
return this.entity;
}
public Player getInstigator() {
return this.instigator;
}
public Vector getFrom() {
return this.from;
}
public Vector getTo() {
return this.to;
}
public Location getStartPoint() {
return this.start;
}
public Location getEndPoint() {
return this.end;
}
public double getDistanceTraveled() {
if (!this.start.getWorld().equals(this.end.getWorld())) {
return 0;
}
return this.start.distance(this.end);
}
public Vector getDifference() {
return this.difference;
}
public Ability getAbility() {
return this.abil;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
@Override
public boolean isCancelled() {
return this.isCancelled;
}
@Override
public void setCancelled(final boolean value) {
this.isCancelled = value;
}
}

View file

@ -0,0 +1,60 @@
package com.projectkorra.projectkorra.event;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.util.VelocityBuilder;
/**
* Event for velocity changes made by a {@link VelocityBuilder}
*/
public class VelocityChangeEvent extends Event implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
private boolean cancelled;
private Entity entity;
private CoreAbility ability;
private Vector velocity;
public VelocityChangeEvent(Entity entity, CoreAbility ability, Vector velocity) {
this.entity = entity;
this.ability = ability;
this.velocity = velocity;
}
public Entity getEntity() {
return entity;
}
public CoreAbility getAbility() {
return ability;
}
public Vector getVelocity() {
return velocity;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View file

@ -0,0 +1,60 @@
package com.projectkorra.projectkorra.event;
import org.bukkit.entity.Entity;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import com.projectkorra.projectkorra.ability.CoreAbility;
public class VelocityImpactDamageEvent extends Event implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
private Entity entity;
private CoreAbility ability;
private double damage;
private boolean cancelled;
public VelocityImpactDamageEvent(Entity entity, CoreAbility ability, double damage) {
this.entity = entity;
this.ability = ability;
this.damage = damage;
this.cancelled = false;
}
public Entity getEntity() {
return entity;
}
public CoreAbility getAbility() {
return ability;
}
public double getDamage() {
return damage;
}
public void setDamage(double damage) {
this.damage = damage;
}
@Override
public HandlerList getHandlers() {
return HANDLERS;
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
}

View file

@ -1,13 +1,9 @@
package com.projectkorra.projectkorra.firebending; package com.projectkorra.projectkorra.firebending;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
@ -16,14 +12,12 @@ import com.projectkorra.projectkorra.Element;
import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.FireAbility; import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
public class BlazeArc extends FireAbility { public class BlazeArc extends FireAbility {
private static final long DISSIPATE_REMOVE_TIME = 400; private static final long DISSIPATE_REMOVE_TIME = 400;
private static final Map<Block, Player> IGNITED_BLOCKS = new ConcurrentHashMap<>();
private static final Map<Block, Long> IGNITED_TIMES = new ConcurrentHashMap<>();
private static final Map<Location, BlockState> REPLACED_BLOCKS = new ConcurrentHashMap<>();
private long time; private long time;
private long interval; private long interval;
@ -53,19 +47,19 @@ public class BlazeArc extends FireAbility {
} }
private void ignite(final Block block) { private void ignite(final Block block) {
if (block.getType() != Material.FIRE && !isAir(block.getType())) { if (!GeneralMethods.isSolid(block.getRelative(BlockFace.DOWN))) {
return;
}
if (!isFire(block) && !isAir(block.getType())) {
if (canFireGrief()) { if (canFireGrief()) {
if (isPlant(block) || isSnow(block)) { if (isPlant(block) || isSnow(block)) {
new PlantRegrowth(this.player, block); new PlantRegrowth(this.player, block);
} }
} else if (block.getType() != Material.FIRE) {
REPLACED_BLOCKS.put(block.getLocation(), block.getState());
} }
} }
block.setType(Material.FIRE); new TempBlock(block, getFireColor()).setRevertTime(DISSIPATE_REMOVE_TIME);
IGNITED_BLOCKS.put(block, this.player);
IGNITED_TIMES.put(block, System.currentTimeMillis());
} }
@Override @Override
@ -78,7 +72,7 @@ public class BlazeArc extends FireAbility {
this.time = System.currentTimeMillis(); this.time = System.currentTimeMillis();
final Block block = this.location.getBlock(); final Block block = this.location.getBlock();
if (block.getType() == Material.FIRE) { if (isFire(block)) {
return; return;
} }
@ -96,32 +90,8 @@ public class BlazeArc extends FireAbility {
} }
} }
public static void dissipateAll() {
if (DISSIPATE_REMOVE_TIME != 0) {
for (final Block block : IGNITED_TIMES.keySet()) {
if (block.getType() != Material.FIRE) {
removeBlock(block);
} else {
final long time = IGNITED_TIMES.get(block);
if (System.currentTimeMillis() > time + DISSIPATE_REMOVE_TIME) {
block.setType(Material.AIR);
removeBlock(block);
}
}
}
}
}
public static void handleDissipation() {
for (final Block block : IGNITED_BLOCKS.keySet()) {
if (block.getType() != Material.FIRE) {
IGNITED_BLOCKS.remove(block);
}
}
}
public static Block getIgnitable(final Block block) { public static Block getIgnitable(final Block block) {
Block top = block; Block top = GeneralMethods.isSolid(block) ? block.getRelative(BlockFace.UP) : block;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
if (GeneralMethods.isSolid(top.getRelative(BlockFace.DOWN))) { if (GeneralMethods.isSolid(top.getRelative(BlockFace.DOWN))) {
@ -158,12 +128,6 @@ public class BlazeArc extends FireAbility {
} }
} }
public static void removeAllCleanup() {
for (final Block block : IGNITED_BLOCKS.keySet()) {
removeBlock(block);
}
}
public static void removeAroundPoint(final Location location, final double radius) { public static void removeAroundPoint(final Location location, final double radius) {
for (final BlazeArc stream : getAbilities(BlazeArc.class)) { for (final BlazeArc stream : getAbilities(BlazeArc.class)) {
if (stream.location.getWorld().equals(location.getWorld())) { if (stream.location.getWorld().equals(location.getWorld())) {
@ -174,20 +138,6 @@ public class BlazeArc extends FireAbility {
} }
} }
public static void removeBlock(final Block block) {
if (IGNITED_BLOCKS.containsKey(block)) {
IGNITED_BLOCKS.remove(block);
}
if (IGNITED_TIMES.containsKey(block)) {
IGNITED_TIMES.remove(block);
}
if (REPLACED_BLOCKS.containsKey(block.getLocation())) {
block.setType(REPLACED_BLOCKS.get(block.getLocation()).getType());
block.setBlockData(REPLACED_BLOCKS.get(block.getLocation()).getBlockData());
REPLACED_BLOCKS.remove(block.getLocation());
}
}
@Override @Override
public String getName() { public String getName() {
return "Blaze"; return "Blaze";
@ -268,18 +218,6 @@ public class BlazeArc extends FireAbility {
return DISSIPATE_REMOVE_TIME; return DISSIPATE_REMOVE_TIME;
} }
public static Map<Block, Player> getIgnitedBlocks() {
return IGNITED_BLOCKS;
}
public static Map<Block, Long> getIgnitedTimes() {
return IGNITED_TIMES;
}
public static Map<Location, BlockState> getReplacedBlocks() {
return REPLACED_BLOCKS;
}
public void setLocation(final Location location) { public void setLocation(final Location location) {
this.location = location; this.location = location;
} }

View file

@ -22,7 +22,6 @@ import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.avatar.AvatarState; import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.firebending.util.FireDamageTimer;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
@ -127,8 +126,8 @@ public class FireBlast extends FireAbility {
} }
if (this.showParticles) { if (this.showParticles) {
ParticleEffect.FLAME.display(this.location, 6, this.flameRadius, this.flameRadius, this.flameRadius); playFirebendingParticles(this.location, 12, this.flameRadius, this.flameRadius, this.flameRadius);
ParticleEffect.SMOKE_NORMAL.display(this.location, 3, this.smokeRadius, this.smokeRadius, this.smokeRadius); ParticleEffect.SMOKE_NORMAL.display(this.location, 2, this.smokeRadius, this.smokeRadius, this.smokeRadius);
} }
if (GeneralMethods.checkDiagonalWall(this.location, this.direction)) { if (GeneralMethods.checkDiagonalWall(this.location, this.direction)) {
@ -154,27 +153,21 @@ public class FireBlast extends FireAbility {
entity.setFireTicks((int) (this.fireTicks * 20)); entity.setFireTicks((int) (this.fireTicks * 20));
DamageHandler.damageEntity(entity, this.damage, this); DamageHandler.damageEntity(entity, this.damage, this);
AirAbility.breakBreathbendingHold(entity); AirAbility.breakBreathbendingHold(entity);
new FireDamageTimer(entity, this.player);
this.remove(); this.remove();
} }
} }
} }
private void ignite(final Location location) { private void ignite(final Location location) {
for (final Block block : GeneralMethods.getBlocksAroundPoint(location, this.collisionRadius)) { for (final Block block : GeneralMethods.getBlocksAroundPoint(location, 1 + this.collisionRadius)) {
if (BlazeArc.isIgnitable(this.player, block) && !this.safeBlocks.contains(block) && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) { if (BlazeArc.isIgnitable(this.player, block) && !this.safeBlocks.contains(block) && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) {
if (canFireGrief()) { if (canFireGrief()) {
if (isPlant(block) || isSnow(block)) { if (isPlant(block) || isSnow(block)) {
new PlantRegrowth(this.player, block); new PlantRegrowth(this.player, block);
} }
block.setType(Material.FIRE); block.setType(getFireColor(bPlayer));
} else { } else {
createTempFire(block.getLocation()); createTempFire(block, bPlayer);
}
if (this.dissipate) {
BlazeArc.getIgnitedBlocks().put(block, this.player);
BlazeArc.getIgnitedTimes().put(block, System.currentTimeMillis());
} }
} }
} }
@ -221,6 +214,11 @@ public class FireBlast extends FireAbility {
this.affect(entity); this.affect(entity);
} }
Entity target = GeneralMethods.getTargetedEntity(player, range);
if (target != null) {
this.direction.add(GeneralMethods.getDirection(location, target.getLocation().add(0, 1, 0)).normalize().multiply(0.025));
}
this.advanceLocation(); this.advanceLocation();
} }

View file

@ -5,7 +5,6 @@ import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Effect;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Sound; import org.bukkit.Sound;
@ -207,7 +206,7 @@ public class FireBlastCharged extends FireAbility {
private void executeFireball() { private void executeFireball() {
for (final Block block : GeneralMethods.getBlocksAroundPoint(this.location, this.collisionRadius)) { for (final Block block : GeneralMethods.getBlocksAroundPoint(this.location, this.collisionRadius)) {
ParticleEffect.FLAME.display(block.getLocation(), 5, 0.5, 0.5, 0.5, 0); playFirebendingParticles(block.getLocation(), 5, 0.5, 0.5, 0.5);
ParticleEffect.SMOKE_NORMAL.display(block.getLocation(), 2, 0.5, 0.5, 0.5, 0); ParticleEffect.SMOKE_NORMAL.display(block.getLocation(), 2, 0.5, 0.5, 0.5, 0);
if ((new Random()).nextInt(4) == 0) { if ((new Random()).nextInt(4) == 0) {
playFirebendingSound(this.location); playFirebendingSound(this.location);
@ -234,14 +233,7 @@ public class FireBlastCharged extends FireAbility {
private void ignite(final Location location) { private void ignite(final Location location) {
for (final Block block : GeneralMethods.getBlocksAroundPoint(location, this.collisionRadius)) { for (final Block block : GeneralMethods.getBlocksAroundPoint(location, this.collisionRadius)) {
if (BlazeArc.isIgnitable(this.player, block)) { if (BlazeArc.isIgnitable(this.player, block)) {
if (block.getType() != Material.FIRE) { createTempFire(block, bPlayer);
BlazeArc.getReplacedBlocks().put(block.getLocation(), block.getState());
}
block.setType(Material.FIRE);
if (this.dissipate) {
BlazeArc.getIgnitedBlocks().put(block, this.player);
BlazeArc.getIgnitedTimes().put(block, System.currentTimeMillis());
}
} }
} }
} }
@ -282,7 +274,7 @@ public class FireBlastCharged extends FireAbility {
if (!this.launched && !this.charged) { if (!this.launched && !this.charged) {
return; return;
} else if (!this.launched) { } else if (!this.launched) {
this.player.getWorld().playEffect(this.player.getEyeLocation(), Effect.MOBSPAWNER_FLAMES, 0, 3); playFirebendingParticles(player.getEyeLocation().add(player.getEyeLocation().getDirection().normalize()), 1, 0, 0, 0);
return; return;
} }

View file

@ -3,7 +3,6 @@ package com.projectkorra.projectkorra.firebending;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.bukkit.Effect;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -137,8 +136,7 @@ public class FireBurst extends FireAbility {
this.remove(); this.remove();
} }
} else if (this.charged) { } else if (this.charged) {
final Location location = this.player.getEyeLocation(); playFirebendingParticles(player.getEyeLocation().add(player.getEyeLocation().getDirection().normalize()), 1, 0, 0, 0);
location.getWorld().playEffect(location, Effect.MOBSPAWNER_FLAMES, 4, 3);
} }
} }

View file

@ -7,14 +7,16 @@ import java.util.Random;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.ability.ElementalAbility;
import com.projectkorra.projectkorra.ability.FireAbility; import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.airbending.AirSpout; import com.projectkorra.projectkorra.airbending.AirSpout;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class FireJet extends FireAbility { public class FireJet extends FireAbility {
@ -60,12 +62,12 @@ public class FireJet extends FireAbility {
if (BlazeArc.isIgnitable(player, block) || ElementalAbility.isAir(block.getType()) || block.getType() == Material.STONE_SLAB || block.getType() == Material.ACACIA_SLAB || block.getType() == Material.BIRCH_SLAB || block.getType() == Material.DARK_OAK_SLAB || block.getType() == Material.JUNGLE_SLAB || block.getType() == Material.OAK_SLAB || block.getType() == Material.SPRUCE_SLAB || isIlluminationTorch(block) || this.bPlayer.isAvatarState()) { if (BlazeArc.isIgnitable(player, block) || ElementalAbility.isAir(block.getType()) || block.getType() == Material.STONE_SLAB || block.getType() == Material.ACACIA_SLAB || block.getType() == Material.BIRCH_SLAB || block.getType() == Material.DARK_OAK_SLAB || block.getType() == Material.JUNGLE_SLAB || block.getType() == Material.OAK_SLAB || block.getType() == Material.SPRUCE_SLAB || isIlluminationTorch(block) || this.bPlayer.isAvatarState()) {
player.setVelocity(player.getEyeLocation().getDirection().clone().normalize().multiply(this.speed)); player.setVelocity(player.getEyeLocation().getDirection().clone().normalize().multiply(this.speed));
if (!canFireGrief()) { if (!canFireGrief()) {
if (ElementalAbility.isAir(block.getType())) { if (ElementalAbility.isAir(block.getType()) && GeneralMethods.isSolid(block.getRelative(BlockFace.DOWN))) {
createTempFire(block.getLocation()); createTempFire(block, bPlayer);
} }
} else if (ElementalAbility.isAir(block.getType())) { } else if (ElementalAbility.isAir(block.getType())) {
block.setType(Material.FIRE); block.setType(getFireColor());
} }
this.flightHandler.createInstance(player, this.getName()); this.flightHandler.createInstance(player, this.getName());
@ -93,7 +95,7 @@ public class FireJet extends FireAbility {
playFirebendingSound(this.player.getLocation()); playFirebendingSound(this.player.getLocation());
} }
ParticleEffect.FLAME.display(this.player.getLocation(), 20, 0.6, 0.6, 0.6); playFirebendingParticles(this.player.getLocation(), 20, 0.6, 0.6, 0.6);
ParticleEffect.SMOKE_NORMAL.display(this.player.getLocation(), 10, 0.6, 0.6, 0.6); ParticleEffect.SMOKE_NORMAL.display(this.player.getLocation(), 10, 0.6, 0.6, 0.6);
double timefactor; double timefactor;
@ -103,8 +105,7 @@ public class FireJet extends FireAbility {
timefactor = 1 - (System.currentTimeMillis() - this.time) / (2.0 * this.duration); timefactor = 1 - (System.currentTimeMillis() - this.time) / (2.0 * this.duration);
} }
final Vector velocity = this.player.getEyeLocation().getDirection().clone().normalize().multiply(this.speed * timefactor); new VelocityBuilder(player.getEyeLocation().getDirection()).knockback(this.speed * timefactor).apply(player, this);
this.player.setVelocity(velocity);
this.player.setFallDistance(0); this.player.setFallDistance(0);
} }
} }

View file

@ -113,7 +113,7 @@ public class FireManipulation extends FireAbility {
this.points.remove(point); this.points.remove(point);
return; return;
} }
ParticleEffect.FLAME.display(point, 12, 0.25, 0.25, 0.25); playFirebendingParticles(point, 12, 0.25, 0.25, 0.25);
ParticleEffect.SMOKE_NORMAL.display(point, 6, 0.25, 0.25, 0.25); ParticleEffect.SMOKE_NORMAL.display(point, 6, 0.25, 0.25, 0.25);
for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(point, 1.2D)) { for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(point, 1.2D)) {
if (entity instanceof LivingEntity && entity.getUniqueId() != this.player.getUniqueId()) { if (entity instanceof LivingEntity && entity.getUniqueId() != this.player.getUniqueId()) {
@ -143,7 +143,7 @@ public class FireManipulation extends FireAbility {
for (final Location point : this.points.keySet()) { for (final Location point : this.points.keySet()) {
final Vector direction = this.focalPoint.toVector().subtract(point.toVector()); final Vector direction = this.focalPoint.toVector().subtract(point.toVector());
point.add(direction.clone().multiply(this.streamSpeed / 5)); point.add(direction.clone().multiply(this.streamSpeed / 5));
ParticleEffect.FLAME.display(point, this.shieldParticles, 0.25, 0.25, 0.25); playFirebendingParticles(point, this.shieldParticles, 0.25, 0.25, 0.25);
ParticleEffect.SMOKE_NORMAL.display(point, this.shieldParticles / 2, 0.25, 0.25, 0.25); ParticleEffect.SMOKE_NORMAL.display(point, this.shieldParticles / 2, 0.25, 0.25, 0.25);
} }
} else { } else {
@ -173,7 +173,7 @@ public class FireManipulation extends FireAbility {
return; return;
} }
ParticleEffect.FLAME.display(this.shotPoint, this.streamParticles, 0.5, 0.5, 0.5, 0.01); playFirebendingParticles(this.shotPoint, this.streamParticles, 0.5, 0.5, 0.5);
ParticleEffect.SMOKE_NORMAL.display(this.shotPoint, this.streamParticles / 2, 0.5, 0.5, 0.5, 0.01); ParticleEffect.SMOKE_NORMAL.display(this.shotPoint, this.streamParticles / 2, 0.5, 0.5, 0.5, 0.01);
for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(this.shotPoint, 2)) { for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(this.shotPoint, 2)) {
if (entity instanceof LivingEntity && entity.getUniqueId() != this.player.getUniqueId()) { if (entity instanceof LivingEntity && entity.getUniqueId() != this.player.getUniqueId()) {

View file

@ -16,7 +16,6 @@ import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.FireAbility; import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.ability.util.Collision; import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.firebending.util.FireDamageTimer;
import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.ParticleEffect;
public class FireShield extends FireAbility { public class FireShield extends FireAbility {
@ -129,7 +128,7 @@ public class FireShield extends FireAbility {
ParticleEffect.SMOKE_NORMAL.display(display, 1, 0, 0, 0); ParticleEffect.SMOKE_NORMAL.display(display, 1, 0, 0, 0);
} }
if (this.random.nextInt(4) == 0) { if (this.random.nextInt(4) == 0) {
ParticleEffect.FLAME.display(display, 1, 0.1, 0.1, 0.1, 0.013); playFirebendingParticles(display, 1, 0.1, 0.1, 0.1, 0.013);
} }
if (this.random.nextInt(7) == 0) { if (this.random.nextInt(7) == 0) {
playFirebendingSound(display); playFirebendingSound(display);
@ -143,7 +142,7 @@ public class FireShield extends FireAbility {
} }
for (final Block testblock : GeneralMethods.getBlocksAroundPoint(this.player.getLocation(), this.shieldRadius)) { for (final Block testblock : GeneralMethods.getBlocksAroundPoint(this.player.getLocation(), this.shieldRadius)) {
if (testblock.getType() == Material.FIRE) { if (isFire(testblock)) {
testblock.setType(Material.AIR); testblock.setType(Material.AIR);
testblock.getWorld().playEffect(testblock.getLocation(), Effect.EXTINGUISH, 0); testblock.getWorld().playEffect(testblock.getLocation(), Effect.EXTINGUISH, 0);
} }
@ -155,7 +154,6 @@ public class FireShield extends FireAbility {
} else if (entity instanceof LivingEntity) { } else if (entity instanceof LivingEntity) {
if (this.player.getEntityId() != entity.getEntityId() && this.ignite) { if (this.player.getEntityId() != entity.getEntityId() && this.ignite) {
entity.setFireTicks((int) (this.shieldFireTicks * 20)); entity.setFireTicks((int) (this.shieldFireTicks * 20));
new FireDamageTimer(entity, this.player);
} }
} else if (entity instanceof Projectile) { } else if (entity instanceof Projectile) {
entity.remove(); entity.remove();
@ -165,7 +163,7 @@ public class FireShield extends FireAbility {
this.location = this.player.getEyeLocation().clone(); this.location = this.player.getEyeLocation().clone();
final Vector direction = this.location.getDirection(); final Vector direction = this.location.getDirection();
this.location.add(direction.multiply(this.shieldRadius)); this.location.add(direction.multiply(this.shieldRadius));
ParticleEffect.FLAME.display(this.location, 3, 0.2, 0.2, 0.2, 0.00023); playFirebendingParticles(this.location, 3, 0.2, 0.2, 0.2, 0.00023);
for (double theta = 0; theta < 360; theta += 20) { for (double theta = 0; theta < 360; theta += 20) {
final Vector vector = GeneralMethods.getOrthogonalVector(direction, theta, this.discRadius / 1.5); final Vector vector = GeneralMethods.getOrthogonalVector(direction, theta, this.discRadius / 1.5);
@ -173,7 +171,7 @@ public class FireShield extends FireAbility {
if (this.random.nextInt(6) == 0) { if (this.random.nextInt(6) == 0) {
ParticleEffect.SMOKE_NORMAL.display(display, 1, 0, 0, 0); ParticleEffect.SMOKE_NORMAL.display(display, 1, 0, 0, 0);
} }
ParticleEffect.FLAME.display(display, 2, 0.3, 0.2, 0.3, 0.023); playFirebendingParticles(display, 2, 0.3, 0.2, 0.3, 0.023);
if (this.random.nextInt(4) == 0) { if (this.random.nextInt(4) == 0) {
playFirebendingSound(display); playFirebendingSound(display);
} }
@ -186,7 +184,6 @@ public class FireShield extends FireAbility {
} else if (entity instanceof LivingEntity) { } else if (entity instanceof LivingEntity) {
if (this.player.getEntityId() != entity.getEntityId() && this.ignite) { if (this.player.getEntityId() != entity.getEntityId() && this.ignite) {
entity.setFireTicks((int) (this.discFireTicks * 20)); entity.setFireTicks((int) (this.discFireTicks * 20));
new FireDamageTimer(entity, this.player);
} }
} else if (entity instanceof Projectile) { } else if (entity instanceof Projectile) {
entity.remove(); entity.remove();

View file

@ -193,9 +193,7 @@ public class HeatControl extends FireAbility {
} }
for (final Block block : GeneralMethods.getBlocksAroundPoint(this.player.getLocation(), this.extinguishRadius)) { for (final Block block : GeneralMethods.getBlocksAroundPoint(this.player.getLocation(), this.extinguishRadius)) {
final Material material = block.getType(); if (isFire(block) && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) {
if (material == Material.FIRE && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) {
block.setType(Material.AIR); block.setType(Material.AIR);
block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0); block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0);
} }
@ -281,7 +279,7 @@ public class HeatControl extends FireAbility {
} }
public void displayCookParticles() { public void displayCookParticles() {
ParticleEffect.FLAME.display(this.player.getLocation().clone().add(0, 1, 0), 3, 0.5, 0.5, 0.5); playFirebendingParticles(this.player.getLocation().clone().add(0, 1, 0), 3, 0.5, 0.5, 0.5);
ParticleEffect.SMOKE_NORMAL.display(this.player.getLocation().clone().add(0, 1, 0), 2, 0.5, 0.5, 0.5); ParticleEffect.SMOKE_NORMAL.display(this.player.getLocation().clone().add(0, 1, 0), 2, 0.5, 0.5, 0.5);
} }

View file

@ -125,7 +125,7 @@ public class Illumination extends FireAbility {
} }
this.revert(); this.revert();
this.block = new TempBlock(standingBlock, Material.TORCH); this.block = new TempBlock(standingBlock, bPlayer.hasSubElement(Element.BLUE_FIRE) ? Material.SOUL_TORCH : Material.TORCH);
BLOCKS.put(this.block, this.player); BLOCKS.put(this.block, this.player);
} }

View file

@ -15,7 +15,6 @@ import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.AirAbility; import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.FireAbility; import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.firebending.util.FireDamageTimer;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempBlock;
@ -115,7 +114,6 @@ public class WallOfFire extends FireAbility {
AirAbility.breakBreathbendingHold(entity); AirAbility.breakBreathbendingHold(entity);
} }
entity.setFireTicks((int) (this.fireTicks * 20)); entity.setFireTicks((int) (this.fireTicks * 20));
new FireDamageTimer(entity, this.player);
} }
private void damage() { private void damage() {
@ -147,7 +145,7 @@ public class WallOfFire extends FireAbility {
if (!this.isTransparent(block)) { if (!this.isTransparent(block)) {
continue; continue;
} }
ParticleEffect.FLAME.display(block.getLocation(), 3, 0.6, 0.6, 0.6); playFirebendingParticles(block.getLocation(), 3, 0.6, 0.6, 0.6);
ParticleEffect.SMOKE_NORMAL.display(block.getLocation(), 2, 0.6, 0.6, 0.6); ParticleEffect.SMOKE_NORMAL.display(block.getLocation(), 2, 0.6, 0.6, 0.6);
if (this.random.nextInt(7) == 0) { if (this.random.nextInt(7) == 0) {

View file

@ -0,0 +1,54 @@
package com.projectkorra.projectkorra.firebending.bluefire;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import com.projectkorra.projectkorra.ability.BlueFireAbility;
import com.projectkorra.projectkorra.ability.PassiveAbility;
public class BlueFlames extends BlueFireAbility implements PassiveAbility {
public BlueFlames(Player player) {
super(player);
}
@Override
public void progress() {
}
@Override
public boolean isSneakAbility() {
return false;
}
@Override
public boolean isHarmlessAbility() {
return true;
}
@Override
public long getCooldown() {
return 0;
}
@Override
public String getName() {
return "BlueFlames";
}
@Override
public Location getLocation() {
return null;
}
@Override
public boolean isInstantiable() {
return false;
}
@Override
public boolean isProgressable() {
return false;
}
}

View file

@ -2,8 +2,6 @@ package com.projectkorra.projectkorra.firebending.combo;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;
import org.bukkit.Effect;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -18,8 +16,8 @@ import com.projectkorra.projectkorra.BendingPlayer;
import com.projectkorra.projectkorra.GeneralMethods; import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.CoreAbility; import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.ElementalAbility; import com.projectkorra.projectkorra.ability.ElementalAbility;
import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.firebending.util.FireDamageTimer;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.ParticleEffect;
@ -61,9 +59,9 @@ public class FireComboStream extends BukkitRunnable {
this.checkCollisionCounter = 0; this.checkCollisionCounter = 0;
this.spread = 0; this.spread = 0;
this.collisionRadius = 2; this.collisionRadius = 2;
this.particleEffect = ParticleEffect.FLAME;
this.player = player; this.player = player;
this.bPlayer = BendingPlayer.getBendingPlayer(player); this.bPlayer = BendingPlayer.getBendingPlayer(player);
this.particleEffect = FireAbility.getFireParticle(bPlayer);
this.coreAbility = coreAbility; this.coreAbility = coreAbility;
this.direction = direction; this.direction = direction;
this.speed = speed; this.speed = speed;
@ -79,12 +77,13 @@ public class FireComboStream extends BukkitRunnable {
this.remove(); this.remove();
return; return;
} }
for (int i = 0; i < this.density; i++) {
if (this.useNewParticles) { if (this.useNewParticles) {
this.particleEffect.display(this.location, 1, this.spread, this.spread, this.spread); if (particleEffect != null) {
} else { this.particleEffect.display(this.location, this.density, this.spread, this.spread, this.spread);
this.location.getWorld().playEffect(this.location, Effect.MOBSPAWNER_FLAMES, 0, 15);
} }
} else {
FireAbility.getFireParticle(bPlayer).display(this.location, this.density, this.spread, this.spread, this.spread);
} }
if (GeneralMethods.checkDiagonalWall(this.location, this.direction)) { if (GeneralMethods.checkDiagonalWall(this.location, this.direction)) {
@ -144,7 +143,6 @@ public class FireComboStream extends BukkitRunnable {
jetBlaze.getAffectedEntities().add(entity); jetBlaze.getAffectedEntities().add(entity);
DamageHandler.damageEntity(entity, this.damage, coreAbility); DamageHandler.damageEntity(entity, this.damage, coreAbility);
entity.setFireTicks((int) (this.fireTicks * 20)); entity.setFireTicks((int) (this.fireTicks * 20));
new FireDamageTimer(entity, this.player);
} }
} else if (coreAbility.getName().equalsIgnoreCase("FireWheel")) { } else if (coreAbility.getName().equalsIgnoreCase("FireWheel")) {
final FireWheel fireWheel = CoreAbility.getAbility(this.player, FireWheel.class); final FireWheel fireWheel = CoreAbility.getAbility(this.player, FireWheel.class);
@ -153,7 +151,6 @@ public class FireComboStream extends BukkitRunnable {
fireWheel.getAffectedEntities().add(entity); fireWheel.getAffectedEntities().add(entity);
DamageHandler.damageEntity(entity, this.damage, coreAbility); DamageHandler.damageEntity(entity, this.damage, coreAbility);
entity.setFireTicks((int) (this.fireTicks * 20)); entity.setFireTicks((int) (this.fireTicks * 20));
new FireDamageTimer(entity, this.player);
this.remove(); this.remove();
} }
} }

View file

@ -18,10 +18,8 @@ import com.projectkorra.projectkorra.ability.ElementalAbility;
import com.projectkorra.projectkorra.ability.FireAbility; import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation; import com.projectkorra.projectkorra.ability.util.ComboManager.AbilityInformation;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.firebending.util.FireDamageTimer;
import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect;
public class FireWheel extends FireAbility implements ComboAbility { public class FireWheel extends FireAbility implements ComboAbility {
@ -120,7 +118,7 @@ public class FireWheel extends FireAbility implements ComboAbility {
if (topBlock == null || isWater(topBlock)) { if (topBlock == null || isWater(topBlock)) {
this.remove(); this.remove();
return; return;
} else if (topBlock.getType() == Material.FIRE) { } else if (isFire(topBlock)) {
topBlock = topBlock.getRelative(BlockFace.DOWN); topBlock = topBlock.getRelative(BlockFace.DOWN);
} else if (ElementalAbility.isPlant(topBlock)) { } else if (ElementalAbility.isPlant(topBlock)) {
topBlock.breakNaturally(); topBlock.breakNaturally();
@ -139,7 +137,7 @@ public class FireWheel extends FireAbility implements ComboAbility {
final Vector newDir = this.direction.clone().multiply(this.radius * Math.cos(Math.toRadians(i))); final Vector newDir = this.direction.clone().multiply(this.radius * Math.cos(Math.toRadians(i)));
tempLoc.add(newDir); tempLoc.add(newDir);
tempLoc.setY(tempLoc.getY() + (this.radius * Math.sin(Math.toRadians(i)))); tempLoc.setY(tempLoc.getY() + (this.radius * Math.sin(Math.toRadians(i))));
ParticleEffect.FLAME.display(tempLoc, 0, 0, 0, 0, 1); playFirebendingParticles(tempLoc, 0, 0, 0, 0, 1);
} }
for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(this.location, this.radius + 0.5)) { for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(this.location, this.radius + 0.5)) {
@ -148,7 +146,6 @@ public class FireWheel extends FireAbility implements ComboAbility {
this.affectedEntities.add((LivingEntity) entity); this.affectedEntities.add((LivingEntity) entity);
DamageHandler.damageEntity(entity, this.damage, this); DamageHandler.damageEntity(entity, this.damage, this);
entity.setFireTicks((int) (this.fireTicks * 20)); entity.setFireTicks((int) (this.fireTicks * 20));
new FireDamageTimer(entity, this.player);
} }
} }
} }

View file

@ -90,7 +90,7 @@ public class JetBlast extends FireAbility implements ComboAbility {
final FireComboStream fs = new FireComboStream(this.player, this, this.player.getVelocity().clone().multiply(-1), this.player.getLocation(), 3, 0.5); final FireComboStream fs = new FireComboStream(this.player, this, this.player.getVelocity().clone().multiply(-1), this.player.getLocation(), 3, 0.5);
fs.setDensity(1); fs.setDensity(2);
fs.setSpread(0.9F); fs.setSpread(0.9F);
fs.setUseNewParticles(true); fs.setUseNewParticles(true);
fs.setCollides(false); fs.setCollides(false);

View file

@ -6,6 +6,7 @@ import java.util.List;
import com.projectkorra.projectkorra.ability.CoreAbility; import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.firebending.FireJet; import com.projectkorra.projectkorra.firebending.FireJet;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
@ -498,6 +499,7 @@ public class Lightning extends LightningAbility {
this.cancel(); this.cancel();
} else if (this.count == 1) { } else if (this.count == 1) {
if (!Lightning.this.isTransparentForLightning(Lightning.this.player, this.location.getBlock())) { if (!Lightning.this.isTransparentForLightning(Lightning.this.player, this.location.getBlock())) {
this.location.getWorld().playSound(location, Sound.ENTITY_LIGHTNING_BOLT_IMPACT, 3, 0.3f);
this.arc.cancel(); this.arc.cancel();
return; return;
} }
@ -546,6 +548,7 @@ public class Lightning extends LightningAbility {
} }
Lightning.this.electrocute(lent); Lightning.this.electrocute(lent);
this.location.getWorld().playSound(lent.getLocation().add(0, 1, 0), Sound.ENTITY_LIGHTNING_BOLT_IMPACT, 3, 0.3f);
// Handle Chain Lightning. // Handle Chain Lightning.
if (Lightning.this.maxChainArcs >= 1 && Math.random() <= Lightning.this.chainArcChance) { if (Lightning.this.maxChainArcs >= 1 && Math.random() <= Lightning.this.chainArcChance) {

View file

@ -1,73 +0,0 @@
package com.projectkorra.projectkorra.firebending.util;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import com.projectkorra.projectkorra.Element;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.firebending.HeatControl;
import com.projectkorra.projectkorra.util.DamageHandler;
public class FireDamageTimer {
private static final int MAX_TICKS = 90;
private static final int DAMAGE = 1;
private static final long BUFFER = 30;
private static final Map<Entity, Player> INSTANCES = new ConcurrentHashMap<>();
private static final Map<Entity, Long> TIMES = new ConcurrentHashMap<>();
public FireDamageTimer(final Entity entity, final Player source) {
if (entity.getEntityId() == source.getEntityId()) {
return;
}
INSTANCES.put(entity, source);
}
public static boolean isEnflamed(final Entity entity) {
if (INSTANCES.containsKey(entity)) {
if (TIMES.containsKey(entity)) {
final long time = TIMES.get(entity);
if (System.currentTimeMillis() < time + BUFFER) {
return false;
}
}
TIMES.put(entity, System.currentTimeMillis());
return true;
} else {
return false;
}
}
public static void dealFlameDamage(final Entity entity) {
if (INSTANCES.containsKey(entity) && entity instanceof LivingEntity) {
if (entity instanceof Player) {
if (!HeatControl.canBurn((Player) entity)) {
return;
}
}
final LivingEntity Lentity = (LivingEntity) entity;
final Player source = INSTANCES.get(entity);
// damages the entity.
DamageHandler.damageEntity(Lentity, source, DAMAGE, CoreAbility.getAbilitiesByElement(Element.FIRE).get(0));
if (entity.getFireTicks() > MAX_TICKS) {
entity.setFireTicks(MAX_TICKS);
}
}
}
public static void handleFlames() {
for (final Entity entity : INSTANCES.keySet()) {
if (entity.getFireTicks() <= 0) {
INSTANCES.remove(entity);
}
}
}
}

View file

@ -1,22 +0,0 @@
package com.projectkorra.projectkorra.firebending.util;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.firebending.BlazeArc;
public class FirebendingManager implements Runnable {
public ProjectKorra plugin;
public FirebendingManager(final ProjectKorra plugin) {
this.plugin = plugin;
}
@Override
public void run() {
BlazeArc.handleDissipation();
FireDamageTimer.handleFlames();
BlazeArc.dissipateAll();
FireAbility.removeFire();
}
}

View file

@ -1,147 +0,0 @@
package com.projectkorra.projectkorra.object;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.Ability;
import com.projectkorra.projectkorra.ability.ElementalAbility;
import com.projectkorra.projectkorra.configuration.ConfigManager;
import com.projectkorra.projectkorra.event.HorizontalVelocityChangeEvent;
/**
* Created by Carbogen on 2/2/2015.
*/
public class HorizontalVelocityTracker {
public static Map<Entity, HorizontalVelocityTracker> instances = new ConcurrentHashMap<Entity, HorizontalVelocityTracker>();
public boolean hasBeenDamaged = false;
public boolean barrier = ConfigManager.defaultConfig.get().getBoolean("Properties.HorizontalCollisionPhysics.DamageOnBarrierBlock");
private long delay;
private long fireTime;
private Entity entity;
private Player instigator;
private Vector lastVelocity;
private Vector thisVelocity;
private Location launchLocation;
private Location impactLocation;
private Ability abil;
public static String[] abils = { "AirBlast", "AirBurst", "AirSuction", "Bloodbending" };
public HorizontalVelocityTracker(final Entity e, final Player instigator, final long delay, final Ability ability) {
if (!ProjectKorra.plugin.getConfig().getBoolean("Properties.HorizontalCollisionPhysics.Enabled")) {
return;
}
if (!(e instanceof LivingEntity)) {
return;
}
remove(e);
this.entity = e;
this.instigator = instigator;
this.fireTime = System.currentTimeMillis();
this.delay = delay;
this.thisVelocity = e.getVelocity().clone();
this.launchLocation = e.getLocation().clone();
this.impactLocation = this.launchLocation.clone();
this.abil = ability;
this.update();
instances.put(this.entity, this);
}
public void update() {
if (System.currentTimeMillis() < this.fireTime + this.delay) {
return;
}
if (this.entity.isOnGround()) {
this.remove();
return;
}
if (System.currentTimeMillis() > (this.fireTime + 30000)) {
ProjectKorra.log.info("removed HorizontalVelocityTracker lasting over 30 seconds: " + this.instigator.getName() + " using " + this.abil.getName() + " on " + this.entity);
this.remove();
return;
}
this.lastVelocity = this.thisVelocity.clone();
this.thisVelocity = this.entity.getVelocity().clone();
final Vector diff = this.thisVelocity.subtract(this.lastVelocity);
final List<Block> blocks = GeneralMethods.getBlocksAroundPoint(this.entity.getLocation(), 1.5);
for (final Block b : blocks) {
if (ElementalAbility.isWater(b)) {
this.remove();
return;
}
}
if (this.thisVelocity.length() < this.lastVelocity.length()) {
if ((diff.getX() > 1 || diff.getX() < -1) || (diff.getZ() > 1 || diff.getZ() < -1)) {
this.impactLocation = this.entity.getLocation();
for (final Block b : blocks) {
if (b.getType() == Material.BARRIER && !this.barrier) {
return;
}
if (GeneralMethods.isSolid(b) && (this.entity.getLocation().getBlock().getRelative(BlockFace.EAST, 1).equals(b) || this.entity.getLocation().getBlock().getRelative(BlockFace.NORTH, 1).equals(b) || this.entity.getLocation().getBlock().getRelative(BlockFace.WEST, 1).equals(b) || this.entity.getLocation().getBlock().getRelative(BlockFace.SOUTH, 1).equals(b))) {
if (!ElementalAbility.isTransparent(this.instigator, b)) {
this.hasBeenDamaged = true;
ProjectKorra.plugin.getServer().getPluginManager().callEvent(new HorizontalVelocityChangeEvent(this.entity, this.instigator, this.lastVelocity, this.thisVelocity, diff, this.launchLocation, this.impactLocation, this.abil));
this.remove();
return;
}
}
}
}
}
}
public static void updateAll() {
for (final Entity e : instances.keySet()) {
if (e != null && !e.isDead() && instances.get(e) != null) {
instances.get(e).update();
} else {
instances.remove(e);
}
}
}
public void remove() {
instances.remove(this.entity);
}
public static void remove(final Entity e) {
instances.remove(e);
}
public static boolean hasBeenDamagedByHorizontalVelocity(final Entity e) {
if (instances.containsKey(e)) {
return instances.get(e).hasBeenDamaged;
}
return false;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}

View file

@ -0,0 +1,170 @@
package com.projectkorra.projectkorra.object;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.configuration.ConfigManager;
import com.projectkorra.projectkorra.event.VelocityImpactDamageEvent;
import com.projectkorra.projectkorra.util.DamageHandler;
public class VelocityTracker extends BukkitRunnable {
private static Map<Entity, VelocityTracker> trackers = new HashMap<>();
private static final double DAMAGE_CAP = ConfigManager.getConfig().getDouble("Properties.CollisionPhysics.ImpactDamageCap");
private static final double MINIMUM_DISTANCE = ConfigManager.getConfig().getDouble("Properties.CollisionPhysics.ImpactMinimumDistance");
private static final boolean BARRIER_IMPACT = ConfigManager.getConfig().getBoolean("Properties.CollisionPhysics.ImpactOnBarrierBlock");
private static final double VELOCITY_CHANGE = ConfigManager.getConfig().getDouble("Properties.CollisionPhysics.VelocityChangeThreshold");
private static final double IMPACT_FACTOR = ConfigManager.getConfig().getDouble("Properties.CollisionPhysics.ImpactDamageFactor");
private Entity entity;
private CoreAbility ability;
private Vector curr, prev;
private long startTime;
private Location start, last;
private double travelled;
private boolean testImpact, damageSelf;
public VelocityTracker(Entity entity, CoreAbility ability, boolean testImpact, boolean damageSelf) {
if (trackers.containsKey(entity)) {
trackers.get(entity).cancel();
}
this.entity = entity;
this.ability = ability;
this.start = entity.getLocation();
this.last = entity.getLocation();
this.curr = entity.getVelocity().clone();
this.prev = entity.getVelocity().clone();
this.startTime = System.currentTimeMillis();
this.testImpact = testImpact;
this.damageSelf = damageSelf;
this.travelled = 0;
this.runTaskTimer(ProjectKorra.plugin, 1l, 1l);
trackers.put(entity, this);
}
@Override
public void run() {
if (this.isCancelled()) {
return;
}
if (ability.getPlayer() == null) {
cancel();
return;
} else if (!damageSelf && ability.getPlayer().getEntityId() == entity.getEntityId()) {
cancel();
return;
} else if (entity.isDead()) {
cancel();
return;
} else if (entity.isOnGround()) {
cancel();
return;
} else if (System.currentTimeMillis() > startTime + 4000) {
cancel();
return;
}
curr = entity.getVelocity();
if (curr.angle(prev) > 100) {
cancel();
return;
}
travelled += last.distance(entity.getLocation());
double diff = prev.length() - curr.length();
prev = curr.clone();
last = entity.getLocation();
if (diff > VELOCITY_CHANGE && testImpact) {
Vector direction = curr.clone().normalize();
if (!BARRIER_IMPACT && entity.getLocation().add(direction).getBlock().getType() == Material.BARRIER) {
cancel();
return;
} else if (entity.getLocation().getBlock().getType() == Material.WATER) {
cancel();
return;
} else if (travelled < MINIMUM_DISTANCE) {
cancel();
return;
} else if (curr.getY() < 0 && curr.angle(new Vector(0, -1, 0)) < 30) {
return;
}
double damage = 0.5 + (IMPACT_FACTOR * ((start.distance(entity.getLocation()) - MINIMUM_DISTANCE) / diff));
double capped = Math.min(damage, DAMAGE_CAP);
VelocityImpactDamageEvent impact = new VelocityImpactDamageEvent(entity, ability, capped);
Bukkit.getServer().getPluginManager().callEvent(impact);
if (impact.isCancelled()) {
cancel();
return;
}
DamageHandler.damageEntity(entity, ability.getPlayer(), impact.getDamage(), ability, true);
cancel();
return;
}
}
@Override
public void cancel() {
if (this.isCancelled()) {
return;
}
super.cancel();
trackers.remove(entity);
if (entity.hasMetadata("immovable")) {
entity.removeMetadata("immovable", ProjectKorra.plugin);
}
}
public CoreAbility getAbility() {
return ability;
}
public Entity getEntity() {
return entity;
}
public boolean canDamageSelf() {
return damageSelf;
}
public double getDistanceTravelled() {
return travelled;
}
public static void cancelAll() {
for (VelocityTracker tracker : trackers.values()) {
tracker.cancel();
}
trackers.clear();
}
public static VelocityTracker getTracker(Entity e) {
if (trackers.containsKey(e)) {
return trackers.get(e);
}
return null;
}
}

View file

@ -0,0 +1,65 @@
package com.projectkorra.projectkorra.util;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.entity.Entity;
import org.bukkit.scheduler.BukkitRunnable;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.Ability;
import com.projectkorra.projectkorra.configuration.ConfigManager;
public class AbilityDamageTimestamp {
private static final Map<Entity, AbilityDamageTimestamp> ENTITIES = new HashMap<>();
private Ability ability;
private long time;
private boolean velocityDamage;
private BukkitRunnable endTask;
public AbilityDamageTimestamp(Entity entity, Ability ability, long time, boolean velocityDamage) {
this.ability = ability;
this.time = time;
this.velocityDamage = velocityDamage;
if (ENTITIES.containsKey(entity)) {
ENTITIES.get(entity).endTask.cancel();
}
ENTITIES.put(entity, this);
endTask = new BukkitRunnable() {
@Override
public void run() {
if (isCancelled()) {
return;
}
ENTITIES.remove(entity);
}
};
endTask.runTaskLater(ProjectKorra.plugin, ConfigManager.getConfig().getLong("Properties.AbilityDamageTimestampDuration") / 1000 * 20);
}
public Ability getAbility() {
return ability;
}
public long getTime() {
return time;
}
public boolean isVelocityDamage() {
return velocityDamage;
}
public static AbilityDamageTimestamp get(Entity entity) {
if (ENTITIES.containsKey(entity)) {
return ENTITIES.get(entity);
}
return null;
}
}

View file

@ -1,70 +1,15 @@
package com.projectkorra.projectkorra.util; package com.projectkorra.projectkorra.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import com.projectkorra.projectkorra.util.ReflectionHandler.PackageType; import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
public class ActionBar { public class ActionBar {
private static boolean initialised = false; public static void sendActionBar(final String message, final Player... players) {
private static Constructor<?> chatSer; for (Player player : players) {
private static Constructor<?> packetChat; player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(message));
public static Method getHandle;
private static Field playerConnection;
private static Method sendPacket;
private static int version;
static {
try {
version = Integer.parseInt(PackageType.getServerVersion().split("_")[1]);
chatSer = ReflectionHandler.getConstructor(PackageType.MINECRAFT_SERVER.getClass("ChatComponentText"), String.class);
if (version >= 12) {
packetChat = PackageType.MINECRAFT_SERVER.getClass("PacketPlayOutChat").getConstructor(PackageType.MINECRAFT_SERVER.getClass("IChatBaseComponent"), PackageType.MINECRAFT_SERVER.getClass("ChatMessageType"));
} else {
packetChat = PackageType.MINECRAFT_SERVER.getClass("PacketPlayOutChat").getConstructor(PackageType.MINECRAFT_SERVER.getClass("IChatBaseComponent"), byte.class);
}
getHandle = ReflectionHandler.getMethod("CraftPlayer", PackageType.CRAFTBUKKIT_ENTITY, "getHandle");
playerConnection = ReflectionHandler.getField("EntityPlayer", PackageType.MINECRAFT_SERVER, false, "playerConnection");
sendPacket = ReflectionHandler.getMethod(playerConnection.getType(), "sendPacket", PackageType.MINECRAFT_SERVER.getClass("Packet"));
initialised = true;
} catch (final ReflectiveOperationException e) {
initialised = false;
}
}
public static boolean isInitialised() {
return initialised;
}
public static boolean sendActionBar(final String message, final Player... player) {
if (!initialised) {
return false;
}
try {
final Object o = chatSer.newInstance(message);
Object packet;
if (version >= 12) {
packet = packetChat.newInstance(o, PackageType.MINECRAFT_SERVER.getClass("ChatMessageType").getEnumConstants()[2]);
} else {
packet = packetChat.newInstance(o, (byte) 2);
}
sendTo(packet, player);
} catch (final ReflectiveOperationException e) {
e.printStackTrace();
initialised = false;
}
return initialised;
}
private static void sendTo(final Object packet, final Player... player) throws ReflectiveOperationException {
for (final Player p : player) {
final Object entityplayer = getHandle.invoke(p);
final Object PlayerConnection = playerConnection.get(entityplayer);
sendPacket.invoke(PlayerConnection, packet);
} }
} }
} }

View file

@ -6,13 +6,11 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
import com.projectkorra.projectkorra.ability.Ability; import com.projectkorra.projectkorra.ability.Ability;
import com.projectkorra.projectkorra.ability.CoreAbility; import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.event.AbilityDamageEntityEvent; import com.projectkorra.projectkorra.event.AbilityDamageEntityEvent;
import com.projectkorra.projectkorra.event.EntityBendingDeathEvent;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager; import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
@ -27,26 +25,36 @@ public class DamageHandler {
* @param entity The entity that is receiving the damage * @param entity The entity that is receiving the damage
* @param damage The amount of damage to deal * @param damage The amount of damage to deal
*/ */
public static void damageEntity(final Entity entity, Player source, double damage, final Ability ability, boolean ignoreArmor) { public static void damageEntity(final Entity entity, Player source, double damage, final Ability ability, final boolean velocityDamage) {
if (entity instanceof LivingEntity && TempArmor.hasTempArmor((LivingEntity) entity)) {
ignoreArmor = true;
}
if (ability == null) { if (ability == null) {
return; return;
} else if (!(entity instanceof LivingEntity)) {
return;
} else if (entity.isDead()) {
return;
} }
if (source == null) { if (source == null) {
source = ability.getPlayer(); source = ability.getPlayer();
} }
final AbilityDamageEntityEvent damageEvent = new AbilityDamageEntityEvent(entity, ability, damage, ignoreArmor); LivingEntity target = (LivingEntity) entity;
Bukkit.getServer().getPluginManager().callEvent(damageEvent);
if (entity instanceof LivingEntity) {
if (entity instanceof Player && Commands.invincible.contains(entity.getName())) { if (entity instanceof Player && Commands.invincible.contains(entity.getName())) {
damageEvent.setCancelled(true); return;
} }
if (!damageEvent.isCancelled()) {
final AbilityDamageEntityEvent damageEvent = new AbilityDamageEntityEvent(entity, ability, damage);
Bukkit.getServer().getPluginManager().callEvent(damageEvent);
if (damageEvent.isCancelled()) {
return;
}
damage = damageEvent.getDamage(); damage = damageEvent.getDamage();
if (Bukkit.getPluginManager().isPluginEnabled("NoCheatPlus") && source != null) { final boolean noCheat = Bukkit.getPluginManager().isPluginEnabled("NoCheatPlus") && source != null;
if (noCheat) {
NCPExemptionManager.exemptPermanently(source, CheckType.FIGHT_REACH); NCPExemptionManager.exemptPermanently(source, CheckType.FIGHT_REACH);
NCPExemptionManager.exemptPermanently(source, CheckType.FIGHT_DIRECTION); NCPExemptionManager.exemptPermanently(source, CheckType.FIGHT_DIRECTION);
NCPExemptionManager.exemptPermanently(source, CheckType.FIGHT_NOSWING); NCPExemptionManager.exemptPermanently(source, CheckType.FIGHT_NOSWING);
@ -55,23 +63,14 @@ public class DamageHandler {
NCPExemptionManager.exemptPermanently(source, CheckType.FIGHT_SELFHIT); NCPExemptionManager.exemptPermanently(source, CheckType.FIGHT_SELFHIT);
} }
if (((LivingEntity) entity).getHealth() - damage <= 0 && !entity.isDead()) { final EntityDamageByEntityEvent finalEvent = new EntityDamageByEntityEvent(source, target, DamageCause.CUSTOM, damage);
final EntityBendingDeathEvent event = new EntityBendingDeathEvent(entity, damage, ability); final double prevHealth = target.getHealth();
Bukkit.getServer().getPluginManager().callEvent(event); new AbilityDamageTimestamp(entity, ability, System.currentTimeMillis(), velocityDamage);
} target.damage(damage, source);
final double nextHealth = target.getHealth();
final EntityDamageByEntityEvent finalEvent = new EntityDamageByEntityEvent(source, entity, DamageCause.CUSTOM, damage);
final double prevHealth = ((LivingEntity) entity).getHealth();
((LivingEntity) entity).damage(damage, source);
final double nextHealth = ((LivingEntity) entity).getHealth();
entity.setLastDamageCause(finalEvent); entity.setLastDamageCause(finalEvent);
if (ignoreArmor) {
if (finalEvent.isApplicable(DamageModifier.ARMOR)) {
finalEvent.setDamage(DamageModifier.ARMOR, 0);
}
}
if (Bukkit.getPluginManager().isPluginEnabled("NoCheatPlus") && source != null) { if (noCheat) {
NCPExemptionManager.unexempt(source, CheckType.FIGHT_REACH); NCPExemptionManager.unexempt(source, CheckType.FIGHT_REACH);
NCPExemptionManager.unexempt(source, CheckType.FIGHT_DIRECTION); NCPExemptionManager.unexempt(source, CheckType.FIGHT_DIRECTION);
NCPExemptionManager.unexempt(source, CheckType.FIGHT_NOSWING); NCPExemptionManager.unexempt(source, CheckType.FIGHT_NOSWING);
@ -87,12 +86,9 @@ public class DamageHandler {
StatisticsMethods.addStatisticAbility(source.getUniqueId(), CoreAbility.getAbility(ability.getName()), Statistic.TOTAL_DAMAGE, (long) damage); StatisticsMethods.addStatisticAbility(source.getUniqueId(), CoreAbility.getAbility(ability.getName()), Statistic.TOTAL_DAMAGE, (long) damage);
} }
} }
}
}
public static void damageEntity(final Entity entity, final Player source, final double damage, final Ability ability) { public static void damageEntity(final Entity entity, final Player source, final double damage, final Ability ability) {
damageEntity(entity, source, damage, ability, true); damageEntity(entity, source, damage, ability, false);
} }
public static void damageEntity(final Entity entity, final double damage, final Ability ability) { public static void damageEntity(final Entity entity, final double damage, final Ability ability) {

View file

@ -10,6 +10,7 @@ import org.bukkit.scheduler.BukkitRunnable;
import com.projectkorra.projectkorra.Manager; import com.projectkorra.projectkorra.Manager;
import com.projectkorra.projectkorra.ProjectKorra; import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.object.VelocityTracker;
public class FlightHandler extends Manager { public class FlightHandler extends Manager {
@ -82,6 +83,11 @@ public class FlightHandler extends Manager {
* @param identifier The ability using Flight * @param identifier The ability using Flight
*/ */
public void createInstance(final Player player, final Player source, final long duration, final String identifier) { public void createInstance(final Player player, final Player source, final long duration, final String identifier) {
VelocityTracker vt = VelocityTracker.getTracker(player);
if (vt != null) {
vt.cancel();
}
if (this.INSTANCES.containsKey(player.getUniqueId())) { if (this.INSTANCES.containsKey(player.getUniqueId())) {
final Flight flight = this.INSTANCES.get(player.getUniqueId()); final Flight flight = this.INSTANCES.get(player.getUniqueId());
final FlightAbility ability = new FlightAbility(player, identifier, duration); final FlightAbility ability = new FlightAbility(player, identifier, duration);

View file

@ -6,6 +6,7 @@ import org.bukkit.Particle.DustOptions;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
public enum ParticleEffect { public enum ParticleEffect {
ASH (Particle.ASH),
BARRIER (Particle.BARRIER), BARRIER (Particle.BARRIER),
/** /**
@ -21,7 +22,7 @@ public enum ParticleEffect {
BUBBLE_POP (Particle.BUBBLE_POP), BUBBLE_POP (Particle.BUBBLE_POP),
CLOUD (Particle.CLOUD), CLOUD (Particle.CLOUD),
CRIT (Particle.CRIT), CRIT (Particle.CRIT),
CRIT_MAGIC (Particle.CRIT_MAGIC), @Deprecated MAGIC_CRIT (Particle.CRIT_MAGIC), CRIT_MAGIC (Particle.CRIT_MAGIC),
CURRENT_DOWN (Particle.CURRENT_DOWN), CURRENT_DOWN (Particle.CURRENT_DOWN),
DAMAGE_INDICATOR (Particle.DAMAGE_INDICATOR), DAMAGE_INDICATOR (Particle.DAMAGE_INDICATOR),
DOLPHIN (Particle.DOLPHIN), DOLPHIN (Particle.DOLPHIN),
@ -30,9 +31,9 @@ public enum ParticleEffect {
DRIP_WATER (Particle.DRIP_WATER), DRIP_WATER (Particle.DRIP_WATER),
ENCHANTMENT_TABLE (Particle.ENCHANTMENT_TABLE), ENCHANTMENT_TABLE (Particle.ENCHANTMENT_TABLE),
END_ROD (Particle.END_ROD), END_ROD (Particle.END_ROD),
EXPLOSION_HUGE (Particle.EXPLOSION_HUGE), @Deprecated HUGE_EXPLOSION (Particle.EXPLOSION_HUGE), EXPLOSION_HUGE (Particle.EXPLOSION_HUGE),
EXPLOSION_LARGE (Particle.EXPLOSION_LARGE), @Deprecated LARGE_EXPLODE (Particle.EXPLOSION_LARGE), EXPLOSION_LARGE (Particle.EXPLOSION_LARGE),
EXPLOSION_NORMAL (Particle.EXPLOSION_NORMAL), @Deprecated EXPLODE (Particle.EXPLOSION_NORMAL), EXPLOSION_NORMAL (Particle.EXPLOSION_NORMAL),
/** /**
* Applicable data: {@link BlockData} * Applicable data: {@link BlockData}
@ -55,30 +56,32 @@ public enum ParticleEffect {
/** /**
* Applicable data: {@link DustOptions} * Applicable data: {@link DustOptions}
*/ */
REDSTONE (Particle.REDSTONE), @Deprecated RED_DUST (Particle.REDSTONE), REDSTONE (Particle.REDSTONE),
SLIME (Particle.SLIME), SLIME (Particle.SLIME),
SMOKE_NORMAL (Particle.SMOKE_NORMAL), @Deprecated SMOKE (Particle.SMOKE_NORMAL), SMOKE_NORMAL (Particle.SMOKE_NORMAL),
SMOKE_LARGE (Particle.SMOKE_LARGE), @Deprecated LARGE_SMOKE (Particle.SMOKE_LARGE), SMOKE_LARGE (Particle.SMOKE_LARGE),
SNOW_SHOVEL (Particle.SNOW_SHOVEL), SNOW_SHOVEL (Particle.SNOW_SHOVEL),
SNOWBALL (Particle.SNOWBALL), @Deprecated SNOWBALL_PROOF (Particle.SNOWBALL), SNOWBALL (Particle.SNOWBALL),
SPELL (Particle.SPELL), SPELL (Particle.SPELL),
SPELL_INSTANT (Particle.SPELL_INSTANT), @Deprecated INSTANT_SPELL (Particle.SPELL_INSTANT), SPELL_INSTANT (Particle.SPELL_INSTANT),
SPELL_MOB (Particle.SPELL_MOB), @Deprecated MOB_SPELL (Particle.SPELL_MOB), SPELL_MOB (Particle.SPELL_MOB),
SPELL_MOB_AMBIENT (Particle.SPELL_MOB_AMBIENT), @Deprecated MOB_SPELL_AMBIENT (Particle.SPELL_MOB_AMBIENT), SPELL_MOB_AMBIENT (Particle.SPELL_MOB_AMBIENT),
SPELL_WITCH (Particle.SPELL_WITCH), @Deprecated WITCH_SPELL (Particle.SPELL_WITCH), SPELL_WITCH (Particle.SPELL_WITCH),
SPIT (Particle.SPIT), SPIT (Particle.SPIT),
SOUL (Particle.SOUL),
SOUL_FLAME (Particle.SOUL_FIRE_FLAME),
SQUID_INK (Particle.SQUID_INK), SQUID_INK (Particle.SQUID_INK),
SUSPENDED (Particle.SUSPENDED), @Deprecated SUSPEND (Particle.SUSPENDED), SUSPENDED (Particle.SUSPENDED),
SUSPENDED_DEPTH (Particle.SUSPENDED_DEPTH), @Deprecated DEPTH_SUSPEND (Particle.SUSPENDED_DEPTH), SUSPENDED_DEPTH (Particle.SUSPENDED_DEPTH),
SWEEP_ATTACK (Particle.SWEEP_ATTACK), SWEEP_ATTACK (Particle.SWEEP_ATTACK),
TOTEM (Particle.TOTEM), TOTEM (Particle.TOTEM),
TOWN_AURA (Particle.TOWN_AURA), TOWN_AURA (Particle.TOWN_AURA),
VILLAGER_ANGRY (Particle.VILLAGER_ANGRY), @Deprecated ANGRY_VILLAGER (Particle.VILLAGER_ANGRY), VILLAGER_ANGRY (Particle.VILLAGER_ANGRY),
VILLAGER_HAPPY (Particle.VILLAGER_HAPPY), @Deprecated HAPPY_VILLAGER (Particle.VILLAGER_HAPPY), VILLAGER_HAPPY (Particle.VILLAGER_HAPPY),
WATER_BUBBLE (Particle.WATER_BUBBLE), @Deprecated BUBBLE (Particle.WATER_BUBBLE), WATER_BUBBLE (Particle.WATER_BUBBLE),
WATER_DROP (Particle.WATER_DROP), WATER_DROP (Particle.WATER_DROP),
WATER_SPLASH (Particle.WATER_SPLASH), @Deprecated SPLASH (Particle.WATER_SPLASH), WATER_SPLASH (Particle.WATER_SPLASH),
WATER_WAKE (Particle.WATER_WAKE), @Deprecated WAKE (Particle.WATER_WAKE); WATER_WAKE (Particle.WATER_WAKE);
Particle particle; Particle particle;
Class<?> dataClass; Class<?> dataClass;

View file

@ -0,0 +1,92 @@
package com.projectkorra.projectkorra.util;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.event.VelocityChangeEvent;
import com.projectkorra.projectkorra.object.VelocityTracker;
public class VelocityBuilder {
private static final Vector ZERO = new Vector(0, 0, 0);
private Vector direction;
private double knockback, knockup;
public VelocityBuilder(Vector direction) {
this.direction = direction.clone();
this.knockback = 1;
this.knockup = direction.getY();
}
public VelocityBuilder() {
this(ZERO);
}
/**
* Sets the direction of the velocity to match the vector
*/
public VelocityBuilder direction(Vector direction) {
this.direction = direction.clone();
this.knockup = direction.getY();
return this;
}
/**
* Sets the knockback (or speed) of the velocity to the given magnitude
*/
public VelocityBuilder knockback(double mag) {
this.knockback = Math.abs(mag);
return this;
}
/**
* Sets the knockup of the velocity to the given magnitude
*
* <br><br>If the builder is calling {@link VelocityBuilder#direction(Vector)}, this method should be called after that.
*/
public VelocityBuilder knockup(double mag) {
this.knockup = Math.abs(mag);
return this;
}
public void apply(Entity entity, CoreAbility ability, boolean testImpact, boolean damageSelf, boolean movable) {
if (direction.equals(ZERO)) {
return;
} else if (entity == null) {
return;
} else if (ability == null) {
return;
} else if (entity.hasMetadata("immovable") && entity.getMetadata("immovable").get(0).value() != ability) {
return;
}
direction.setY(knockup).normalize().multiply(knockback);
VelocityChangeEvent event = new VelocityChangeEvent(entity, ability, direction);
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
return;
}
if (!movable && !entity.hasMetadata("immovable")) {
entity.setMetadata("immovable", new FixedMetadataValue(ProjectKorra.plugin, ability));
}
entity.setVelocity(direction);
new VelocityTracker(entity, ability, testImpact, damageSelf);
}
public void apply(Entity entity, CoreAbility ability, boolean testImpact, boolean damageSelf) {
apply(entity, ability, testImpact, damageSelf, true);
}
public void apply(Entity entity, CoreAbility ability) {
apply(entity, ability, false, false, true);
}
}

View file

@ -24,6 +24,7 @@ import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
import com.projectkorra.projectkorra.waterbending.ice.PhaseChange; import com.projectkorra.projectkorra.waterbending.ice.PhaseChange;
import com.projectkorra.projectkorra.waterbending.ice.PhaseChange.PhaseChangeType; import com.projectkorra.projectkorra.waterbending.ice.PhaseChange.PhaseChangeType;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
@ -179,7 +180,7 @@ public class OctopusForm extends WaterAbility {
} else if (!GeneralMethods.isAdjacentToThreeOrMoreSources(this.sourceBlock) && this.sourceBlock != null) { } else if (!GeneralMethods.isAdjacentToThreeOrMoreSources(this.sourceBlock) && this.sourceBlock != null) {
this.sourceBlock.setType(Material.AIR); this.sourceBlock.setType(Material.AIR);
} }
this.source = new TempBlock(this.sourceBlock, Material.WATER, GeneralMethods.getWaterData(0)); this.source = new TempBlock(this.sourceBlock, Material.WATER);
} }
private void attack() { private void attack() {
@ -206,7 +207,7 @@ public class OctopusForm extends WaterAbility {
} }
final double knock = this.bPlayer.isAvatarState() ? AvatarState.getValue(this.knockback) : this.knockback; final double knock = this.bPlayer.isAvatarState() ? AvatarState.getValue(this.knockback) : this.knockback;
entity.setVelocity(GeneralMethods.getDirection(this.player.getLocation(), location).normalize().multiply(knock)); new VelocityBuilder(GeneralMethods.getDirection(this.player.getLocation(), location)).knockback(knock).apply(entity, this);
if (entity instanceof LivingEntity) { if (entity instanceof LivingEntity) {
DamageHandler.damageEntity(entity, this.damage, this); DamageHandler.damageEntity(entity, this.damage, this);
@ -253,7 +254,7 @@ public class OctopusForm extends WaterAbility {
this.sourceLocation = newBlock.getLocation(); this.sourceLocation = newBlock.getLocation();
if (!GeneralMethods.isSolid(newBlock)) { if (!GeneralMethods.isSolid(newBlock)) {
this.source = new TempBlock(newBlock, Material.WATER, GeneralMethods.getWaterData(0)); this.source = new TempBlock(newBlock, Material.WATER);
this.sourceBlock = newBlock; this.sourceBlock = newBlock;
} else { } else {
this.remove(); this.remove();
@ -266,7 +267,7 @@ public class OctopusForm extends WaterAbility {
this.sourceLocation = newBlock.getLocation(); this.sourceLocation = newBlock.getLocation();
if (!GeneralMethods.isSolid(newBlock)) { if (!GeneralMethods.isSolid(newBlock)) {
this.source = new TempBlock(newBlock, Material.WATER, GeneralMethods.getWaterData(0)); this.source = new TempBlock(newBlock, Material.WATER);
this.sourceBlock = newBlock; this.sourceBlock = newBlock;
} else { } else {
this.remove(); this.remove();
@ -282,7 +283,7 @@ public class OctopusForm extends WaterAbility {
this.source.revertBlock(); this.source.revertBlock();
} }
if (!GeneralMethods.isSolid(newBlock)) { if (!GeneralMethods.isSolid(newBlock)) {
this.source = new TempBlock(newBlock, Material.WATER, GeneralMethods.getWaterData(0)); this.source = new TempBlock(newBlock, Material.WATER);
this.sourceBlock = newBlock; this.sourceBlock = newBlock;
} }
} }
@ -426,7 +427,7 @@ public class OctopusForm extends WaterAbility {
if (!SurgeWave.canThaw(block)) { if (!SurgeWave.canThaw(block)) {
SurgeWave.thaw(block); SurgeWave.thaw(block);
} }
tblock.setType(Material.WATER, GeneralMethods.getWaterData(0)); tblock.setType(Material.WATER);
this.newBlocks.add(tblock); this.newBlocks.add(tblock);
} else if (this.blocks.contains(tblock)) { } else if (this.blocks.contains(tblock)) {
this.newBlocks.add(tblock); this.newBlocks.add(tblock);
@ -435,7 +436,7 @@ public class OctopusForm extends WaterAbility {
if (isWater(block) && !TempBlock.isTempBlock(block)) { if (isWater(block) && !TempBlock.isTempBlock(block)) {
ParticleEffect.WATER_BUBBLE.display(block.getLocation().clone().add(0.5, 0.5, 0.5), 5, Math.random(), Math.random(), Math.random(), 0); ParticleEffect.WATER_BUBBLE.display(block.getLocation().clone().add(0.5, 0.5, 0.5), 5, Math.random(), Math.random(), Math.random(), 0);
} }
this.newBlocks.add(new TempBlock(block, Material.WATER, GeneralMethods.getWaterData(0))); this.newBlocks.add(new TempBlock(block, Material.WATER));
} }
} }

View file

@ -27,6 +27,7 @@ import com.projectkorra.projectkorra.util.BlockSource;
import com.projectkorra.projectkorra.util.ClickType; import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
import com.projectkorra.projectkorra.waterbending.util.WaterReturn; import com.projectkorra.projectkorra.waterbending.util.WaterReturn;
@ -107,7 +108,7 @@ public class SurgeWave extends WaterAbility {
if (GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) { if (GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) {
return; return;
} else if (!TempBlock.isTempBlock(block)) { } else if (!TempBlock.isTempBlock(block)) {
new TempBlock(block, Material.WATER, GeneralMethods.getWaterData(0)); new TempBlock(block, Material.WATER);
this.waveBlocks.put(block, block); this.waveBlocks.put(block, block);
} }
} }
@ -349,8 +350,7 @@ public class SurgeWave extends WaterAbility {
continue; continue;
} }
final Vector dir = direction.clone(); final Vector dir = direction.clone();
dir.setY(dir.getY() * this.knockup); new VelocityBuilder(dir).knockback(this.knockback).knockup(dir.getY() * this.knockup).apply(entity, this, true, canHitSelf);
GeneralMethods.setVelocity(entity, entity.getVelocity().clone().add(dir.clone().multiply(this.getNightFactor(this.knockback))));
entity.setFallDistance(0); entity.setFallDistance(0);
if (entity.getFireTicks() > 0) { if (entity.getFireTicks() > 0) {

View file

@ -8,7 +8,6 @@ import java.util.Random;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -29,6 +28,7 @@ import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect; import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
import com.projectkorra.projectkorra.waterbending.util.WaterReturn; import com.projectkorra.projectkorra.waterbending.util.WaterReturn;
@ -207,7 +207,7 @@ public class Torrent extends WaterAbility {
this.sourceBlock.setType(Material.AIR); this.sourceBlock.setType(Material.AIR);
} }
this.source = new TempBlock(this.sourceBlock, Material.WATER, GeneralMethods.getWaterData(0)); this.source = new TempBlock(this.sourceBlock, Material.WATER);
this.location = this.sourceBlock.getLocation(); this.location = this.sourceBlock.getLocation();
} else { } else {
playFocusWaterEffect(this.sourceBlock); playFocusWaterEffect(this.sourceBlock);
@ -261,7 +261,7 @@ public class Torrent extends WaterAbility {
this.remove(); this.remove();
return; return;
} }
this.source = new TempBlock(this.location.getBlock(), Material.WATER, GeneralMethods.getWaterData(0)); this.source = new TempBlock(this.location.getBlock(), Material.WATER);
} }
} }
if (this.forming && !this.player.isSneaking()) { if (this.forming && !this.player.isSneaking()) {
@ -354,7 +354,7 @@ public class Torrent extends WaterAbility {
final Block block = blockloc.getBlock(); final Block block = blockloc.getBlock();
if (!doneBlocks.contains(block) && !GeneralMethods.isRegionProtectedFromBuild(this, blockloc)) { if (!doneBlocks.contains(block) && !GeneralMethods.isRegionProtectedFromBuild(this, blockloc)) {
if (isTransparent(this.player, block)) { if (isTransparent(this.player, block)) {
this.launchedBlocks.add(new TempBlock(block, Material.WATER, GeneralMethods.getWaterData(0))); this.launchedBlocks.add(new TempBlock(block, Material.WATER));
doneBlocks.add(block); doneBlocks.add(block);
} else if (!isTransparent(this.player, block)) { } else if (!isTransparent(this.player, block)) {
break; break;
@ -422,7 +422,7 @@ public class Torrent extends WaterAbility {
if (isWater(locBlock)) { if (isWater(locBlock)) {
ParticleEffect.WATER_BUBBLE.display(locBlock.getLocation().clone().add(.5, .5, .5), 5, Math.random(), Math.random(), Math.random(), 0); ParticleEffect.WATER_BUBBLE.display(locBlock.getLocation().clone().add(.5, .5, .5), 5, Math.random(), Math.random(), Math.random(), 0);
} }
newBlocks.add(new TempBlock(locBlock, Material.WATER, GeneralMethods.getWaterData(0))); newBlocks.add(new TempBlock(locBlock, Material.WATER));
} else { } else {
if (this.layer < this.maxLayer) { if (this.layer < this.maxLayer) {
if (this.layer == 0) { if (this.layer == 0) {
@ -487,7 +487,7 @@ public class Torrent extends WaterAbility {
final Block block = blockLoc.getBlock(); final Block block = blockLoc.getBlock();
if (!doneBlocks.contains(block)) { if (!doneBlocks.contains(block)) {
if (isTransparent(this.player, block)) { if (isTransparent(this.player, block)) {
this.blocks.add(new TempBlock(block, Material.WATER, GeneralMethods.getWaterData(0))); this.blocks.add(new TempBlock(block, Material.WATER));
doneBlocks.add(block); doneBlocks.add(block);
for (final Entity entity : entities) { for (final Entity entity : entities) {
if (entity.getWorld() != blockLoc.getWorld()) { if (entity.getWorld() != blockLoc.getWorld()) {
@ -607,11 +607,14 @@ public class Torrent extends WaterAbility {
if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || (entity instanceof Player && Commands.invincible.contains(((Player) entity).getName()))) { if (GeneralMethods.isRegionProtectedFromBuild(this, entity.getLocation()) || (entity instanceof Player && Commands.invincible.contains(((Player) entity).getName()))) {
return; return;
} }
VelocityBuilder velocity = new VelocityBuilder(direction);
if (direction.getY() > this.knockup) { if (direction.getY() > this.knockup) {
direction.setY(this.knockup); velocity.knockup(this.knockup);
} }
if (!this.freeze) { if (!this.freeze) {
entity.setVelocity(direction.multiply(this.knockback)); velocity.knockback(this.knockback).apply(entity, this, false, false);
} }
if (entity instanceof LivingEntity && !this.hurtEntities.contains(entity)) { if (entity instanceof LivingEntity && !this.hurtEntities.contains(entity)) {
double damageDealt = this.getNightFactor(this.damage); double damageDealt = this.getNightFactor(this.damage);

View file

@ -18,6 +18,7 @@ import com.projectkorra.projectkorra.ability.WaterAbility;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
import com.projectkorra.projectkorra.waterbending.util.WaterReturn; import com.projectkorra.projectkorra.waterbending.util.WaterReturn;
public class TorrentWave extends WaterAbility { public class TorrentWave extends WaterAbility {
@ -140,7 +141,7 @@ public class TorrentWave extends WaterAbility {
} }
if (isTransparent(this.player, block)) { if (isTransparent(this.player, block)) {
final TempBlock tempBlock = new TempBlock(block, Material.WATER, GeneralMethods.getWaterData(0)); final TempBlock tempBlock = new TempBlock(block, Material.WATER);
this.blocks.add(tempBlock); this.blocks.add(tempBlock);
torrentBlocks.add(block); torrentBlocks.add(block);
} else { } else {
@ -178,9 +179,7 @@ public class TorrentWave extends WaterAbility {
private void affect(final Entity entity) { private void affect(final Entity entity) {
final Vector direction = GeneralMethods.getDirection(this.origin, entity.getLocation()); final Vector direction = GeneralMethods.getDirection(this.origin, entity.getLocation());
direction.setY(0); new VelocityBuilder(direction).knockback(this.knockback).knockup(0).apply(entity, this, true, false);
direction.normalize();
entity.setVelocity(entity.getVelocity().clone().add(direction.multiply(this.knockback)));
} }
@Override @Override

View file

@ -28,6 +28,7 @@ import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.command.Commands; import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.TempBlock; import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
import com.projectkorra.projectkorra.waterbending.combo.IceWave; import com.projectkorra.projectkorra.waterbending.combo.IceWave;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth; import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
@ -300,7 +301,7 @@ public class WaterSpoutWave extends WaterAbility {
currentSpeed = this.getNightFactor(this.speed); currentSpeed = this.getNightFactor(this.speed);
} }
this.player.setVelocity(this.player.getEyeLocation().getDirection().normalize().multiply(currentSpeed)); new VelocityBuilder(this.player.getEyeLocation().getDirection()).knockback(currentSpeed).apply(player, this);
for (final Block block : GeneralMethods.getBlocksAroundPoint(this.player.getLocation().add(0, -1, 0), this.waveRadius)) { for (final Block block : GeneralMethods.getBlocksAroundPoint(this.player.getLocation().add(0, -1, 0), this.waveRadius)) {
if (ElementalAbility.isAir(block.getType()) && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) { if (ElementalAbility.isAir(block.getType()) && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) {
if (this.iceWave) { if (this.iceWave) {

View file

@ -22,9 +22,9 @@ import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.BloodAbility; import com.projectkorra.projectkorra.ability.BloodAbility;
import com.projectkorra.projectkorra.attribute.Attribute; import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.avatar.AvatarState; import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
import com.projectkorra.projectkorra.util.DamageHandler; import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.TempPotionEffect; import com.projectkorra.projectkorra.util.TempPotionEffect;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class Bloodbending extends BloodAbility { public class Bloodbending extends BloodAbility {
@ -128,7 +128,6 @@ public class Bloodbending extends BloodAbility {
} }
DamageHandler.damageEntity(this.target, 0, this); DamageHandler.damageEntity(this.target, 0, this);
HorizontalVelocityTracker.remove(this.target);
AirAbility.breakBreathbendingHold(this.target); AirAbility.breakBreathbendingHold(this.target);
TARGETED_ENTITIES.put(this.target, player); TARGETED_ENTITIES.put(this.target, player);
} }
@ -152,9 +151,8 @@ public class Bloodbending extends BloodAbility {
if (location.getWorld().equals(target.getWorld())) { if (location.getWorld().equals(target.getWorld())) {
vector = GeneralMethods.getDirection(location, GeneralMethods.getTargetedLocation(this.player, location.distance(target))); vector = GeneralMethods.getDirection(location, GeneralMethods.getTargetedLocation(this.player, location.distance(target)));
} }
vector.normalize();
entity.setVelocity(vector.multiply(this.knockback)); new VelocityBuilder(vector).knockback(knockback).apply(entity, this, true, false);
new HorizontalVelocityTracker(entity, this.player, 200, this);
} }
this.remove(); this.remove();
this.bPlayer.addCooldown(this); this.bPlayer.addCooldown(this);

View file

@ -214,7 +214,7 @@ public class HealingWaters extends HealingAbility {
private void applyHealing(final Player player) { private void applyHealing(final Player player) {
if (!GeneralMethods.isRegionProtectedFromBuild(player, "HealingWaters", player.getLocation())) { if (!GeneralMethods.isRegionProtectedFromBuild(player, "HealingWaters", player.getLocation())) {
player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 30, this.potionPotency)); player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 50, this.potionPotency));
AirAbility.breakBreathbendingHold(player); AirAbility.breakBreathbendingHold(player);
this.healing = true; this.healing = true;
this.healingSelf = true; this.healingSelf = true;
@ -223,7 +223,7 @@ public class HealingWaters extends HealingAbility {
private void applyHealing(final LivingEntity livingEntity) { private void applyHealing(final LivingEntity livingEntity) {
if (livingEntity.getHealth() < livingEntity.getMaxHealth()) { if (livingEntity.getHealth() < livingEntity.getMaxHealth()) {
livingEntity.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 30, this.potionPotency)); livingEntity.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 50, this.potionPotency));
AirAbility.breakBreathbendingHold(livingEntity); AirAbility.breakBreathbendingHold(livingEntity);
this.healing = true; this.healing = true;
this.healingSelf = false; this.healingSelf = false;