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

View file

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

View file

@ -57,10 +57,11 @@ public class Element {
public static final SubElement SAND = new SubElement("Sand", EARTH);
public static final SubElement LIGHTNING = new SubElement("Lightning", 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[] 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 ElementType type;
@ -101,7 +102,7 @@ public class Element {
this.name = name;
this.type = type;
this.plugin = plugin;
ALL_ELEMENTS.put(name.toLowerCase(), this);
ALL_ELEMENTS.put(name.toLowerCase().replace(" ", ""), this);
}
public String getPrefix() {
@ -146,7 +147,7 @@ public class Element {
if (name == 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.combustion.Combustion;
import com.projectkorra.projectkorra.object.Preset;
import com.projectkorra.projectkorra.object.VelocityTracker;
import com.projectkorra.projectkorra.storage.DBConnection;
import com.projectkorra.projectkorra.util.ActionBar;
import com.projectkorra.projectkorra.util.BlockCacheElement;
@ -157,6 +158,7 @@ public class GeneralMethods {
private static Method getAbsorption;
private static Method setAbsorption;
private static Method getHandle;
public GeneralMethods(final ProjectKorra plugin) {
GeneralMethods.plugin = plugin;
@ -164,6 +166,7 @@ public class GeneralMethods {
try {
getAbsorption = ReflectionHandler.getMethod("EntityHuman", PackageType.MINECRAFT_SERVER, "getAbsorptionHearts");
setAbsorption = ReflectionHandler.getMethod("EntityHuman", PackageType.MINECRAFT_SERVER, "setAbsorptionHearts", Float.class);
getHandle = ReflectionHandler.getMethod("CraftPlayer", PackageType.CRAFTBUKKIT_ENTITY, "getHandle");
} catch (final Exception e) {
e.printStackTrace();
}
@ -464,6 +467,9 @@ public class GeneralMethods {
if (split[0].contains("p")) {
subelements.add(Element.PLANT);
}
if (split[0].contains("r")) {
subelements.add(Element.BLUE_FIRE);
}
if (hasAddon) {
final CopyOnWriteArrayList<String> addonClone = new CopyOnWriteArrayList<String>(Arrays.asList(split[split.length - 1].split(",")));
final long startTime = System.currentTimeMillis();
@ -574,6 +580,10 @@ public class GeneralMethods {
@Deprecated
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 g = 0;
int b = 0;
@ -596,22 +606,9 @@ public class GeneralMethods {
loc.setY(loc.getY() + (Math.random() * 2 - 1) * yOffset);
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);
}
@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) {
int r = 0;
int g = 0;
@ -674,7 +671,7 @@ public class GeneralMethods {
public static float getAbsorbationHealth(final Player player) {
try {
final Object entityplayer = ActionBar.getHandle.invoke(player);
final Object entityplayer = getHandle.invoke(player);
final Object hearts = getAbsorption.invoke(entityplayer);
return (float) hearts;
} catch (final Exception e) {
@ -686,7 +683,7 @@ public class GeneralMethods {
public static void setAbsorbationHealth(final Player player, final float hearts) {
try {
final Object entityplayer = ActionBar.getHandle.invoke(player);
final Object entityplayer = getHandle.invoke(player);
setAbsorption.invoke(entityplayer, hearts);
} catch (final Exception e) {
e.printStackTrace();
@ -1660,15 +1657,16 @@ public class GeneralMethods {
case SKELETON:
case STRAY:
case WITHER_SKELETON:
case WITHER:
case ZOMBIE:
case HUSK:
case ZOMBIE_VILLAGER:
case PIG_ZOMBIE:
case DROWNED:
case ZOMBIE_HORSE:
case SKELETON_HORSE:
case HUSK:
case ZOMBIFIED_PIGLIN:
case ZOMBIE_VILLAGER:
case PHANTOM:
case WITHER:
case SKELETON_HORSE:
case ZOMBIE_HORSE:
case ZOGLIN:
return true;
default:
return false;
@ -1739,9 +1737,15 @@ public class GeneralMethods {
sender.sendMessage(ChatColor.RED + "Reload event cancelled");
return;
}
for (BendingPlayer bPlayer : BendingPlayer.getPlayers().values()) {
savePlayer(bPlayer);
}
if (DBConnection.isOpen()) {
DBConnection.sql.close();
}
GeneralMethods.stopBending();
ConfigManager.defaultConfig.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");
stopPlugin();
}
for (final Player player : Bukkit.getOnlinePlayers()) {
Preset.unloadPreset(player);
GeneralMethods.createBendingPlayer(player.getUniqueId(), player.getName());
PassiveManager.registerPassives(player);
}
plugin.updater.checkUpdate();
ProjectKorra.log.info("Reload complete");
}
@ -2115,6 +2121,9 @@ public class GeneralMethods {
if (bPlayer.hasSubElement(Element.PLANT)) {
subs.append("p");
}
if (bPlayer.hasSubElement(Element.BLUE_FIRE)) {
subs.append("r");
}
boolean hasAddon = false;
for (final Element element : bPlayer.getSubElements()) {
if (Arrays.asList(Element.getAddonSubElements()).contains(element)) {
@ -2297,8 +2306,8 @@ public class GeneralMethods {
CoreAbility.removeAll();
EarthAbility.stopBending();
WaterAbility.stopBending();
FireAbility.stopBending();
VelocityTracker.cancelAll();
TempBlock.removeAll();
TempArmor.revertAll();
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.FluidLevelChangeEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
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.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
@ -76,7 +74,6 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import com.projectkorra.projectkorra.Element.SubElement;
import com.projectkorra.projectkorra.ability.Ability;
import com.projectkorra.projectkorra.ability.AddonAbility;
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.flight.FlightMultiAbility;
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.chiblocking.AcrobatStance;
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.EarthPassive;
import com.projectkorra.projectkorra.earthbending.passive.FerroControl;
import com.projectkorra.projectkorra.event.AbilityStartEvent;
import com.projectkorra.projectkorra.event.EntityBendingDeathEvent;
import com.projectkorra.projectkorra.event.HorizontalVelocityChangeEvent;
import com.projectkorra.projectkorra.event.PlayerChangeElementEvent;
import com.projectkorra.projectkorra.event.PlayerJumpEvent;
import com.projectkorra.projectkorra.firebending.Blaze;
import com.projectkorra.projectkorra.firebending.BlazeArc;
import com.projectkorra.projectkorra.firebending.BlazeRing;
import com.projectkorra.projectkorra.firebending.FireBlast;
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.Illumination;
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.lightning.Lightning;
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.VelocityTracker;
import com.projectkorra.projectkorra.util.AbilityDamageTimestamp;
import com.projectkorra.projectkorra.util.BlockSource;
import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.FlightHandler;
import com.projectkorra.projectkorra.util.FlightHandler.Flight;
import com.projectkorra.projectkorra.util.MovementHandler;
@ -194,8 +192,6 @@ import co.aikar.timings.lib.MCTiming;
public class PKListener implements Listener {
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 ArrayList<UUID> TOGGLED_OUT = new ArrayList<>(); // Stands for toggled = false while logging out.
private static final Map<Player, Integer> JUMPS = new HashMap<>();
@ -221,6 +217,25 @@ public class PKListener implements Listener {
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)
public void onBlockBreak(final BlockBreakEvent event) {
final Block block = event.getBlock();
@ -372,10 +387,6 @@ public class PKListener implements Listener {
if (!event.isCancelled()) {
event.setCancelled(!Torrent.canThaw(block));
}
if (BlazeArc.getIgnitedBlocks().containsKey(block)) {
BlazeArc.removeBlock(block);
}
}
@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)
public void onEntityDamageBlock(final EntityDamageByBlockEvent event) {}
@ -504,15 +506,6 @@ public class PKListener implements Listener {
public void onEntityDamageEvent(final EntityDamageEvent event) {
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 (event.isApplicable(DamageModifier.ARMOR)) {
event.setDamage(DamageModifier.ARMOR, 0);
@ -568,52 +561,63 @@ 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 (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> newDrops = new ArrayList<>();
for (int i = 0; i < drops.size(); i++) {
ItemStack cooked = drops.get(i);
final Material material = drops.get(i).getType();
switch (material) {
case BEEF:
cooked = new ItemStack(Material.COOKED_BEEF);
break;
case SALMON:
cooked = new ItemStack(Material.COOKED_SALMON);
break;
case CHICKEN:
cooked = new ItemStack(Material.COOKED_CHICKEN);
break;
case PORKCHOP:
cooked = new ItemStack(Material.COOKED_PORKCHOP);
break;
case MUTTON:
cooked = new ItemStack(Material.COOKED_MUTTON);
break;
case RABBIT:
cooked = new ItemStack(Material.COOKED_RABBIT);
break;
case COD:
cooked = new ItemStack(Material.COOKED_COD);
break;
default:
break;
}
newDrops.add(cooked);
}
event.getDrops().clear();
event.getDrops().addAll(newDrops);
break;
}
}
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;
}
final List<ItemStack> drops = event.getDrops();
final List<ItemStack> newDrops = new ArrayList<>();
for (int i = 0; i < drops.size(); i++) {
ItemStack cooked = drops.get(i);
final Material material = drops.get(i).getType();
switch (material) {
case BEEF:
cooked = new ItemStack(Material.COOKED_BEEF);
break;
case SALMON:
cooked = new ItemStack(Material.COOKED_SALMON);
break;
case CHICKEN:
cooked = new ItemStack(Material.COOKED_CHICKEN);
break;
case PORKCHOP:
cooked = new ItemStack(Material.COOKED_PORKCHOP);
break;
case MUTTON:
cooked = new ItemStack(Material.COOKED_MUTTON);
break;
case RABBIT:
cooked = new ItemStack(Material.COOKED_RABBIT);
break;
case COD:
cooked = new ItemStack(Material.COOKED_COD);
break;
default:
break;
}
newDrops.add(cooked);
}
event.getDrops().clear();
event.getDrops().addAll(newDrops);
}
@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)
public void onInventoryClick(final InventoryClickEvent event) {
for (final MetalClips clips : CoreAbility.getAbilities(MetalClips.class)) {
@ -768,29 +754,11 @@ public class PKListener implements Listener {
@EventHandler(priority = EventPriority.NORMAL)
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);
}
}
if (event.getAttacker() != null && ProjectKorra.isStatisticsEnabled()) {
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();
}
}
} else {
// Do nothing. TempArmor drops are handled by the EntityDeath event and not PlayerDeath.
}
if (event.getEntity().getKiller() != null) {
if (BENDING_PLAYER_DEATH.containsKey(event.getEntity())) {
String message = ConfigManager.languageConfig.get().getString("DeathMessages.Default");
final String ability = BENDING_PLAYER_DEATH.get(event.getEntity());
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)) {
if (ConfigManager.languageConfig.get().contains("Abilities." + element.getName() + "." + tempAbility + ".HorizontalVelocityDeath")) {
message = ConfigManager.languageConfig.get().getString("Abilities." + element.getName() + "." + tempAbility + ".HorizontalVelocityDeath");
}
} else if (element != null) {
if (element instanceof SubElement) {
element = ((SubElement) element).getParentElement();
}
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);
BENDING_PLAYER_DEATH.remove(event.getEntity());
}
if (event.getEntity().getKiller() == null) {
return;
} else if (!ConfigManager.languageConfig.get().getBoolean("DeathMessages.Enabled")) {
return;
}
AbilityDamageTimestamp adt = AbilityDamageTimestamp.get(event.getEntity());
if (adt == null) {
return;
}
String message = adt.getAbility().getDeathMessage(adt.isVelocityDamage());
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);
event.setDeathMessage(message);
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
@ -1219,56 +1161,6 @@ public class PKListener implements Listener {
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)
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()) {
@ -1962,10 +1854,6 @@ public class PKListener implements Listener {
}
}
public static HashMap<Player, String> getBendingPlayerDeath() {
return BENDING_PLAYER_DEATH;
}
public static List<UUID> getRightClickInteract() {
return RIGHT_CLICK_INTERACT;
}

View file

@ -3,18 +3,15 @@ package com.projectkorra.projectkorra;
import java.util.HashMap;
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.ChatColor;
import org.bukkit.Statistic;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import com.bekvon.bukkit.residence.protection.FlagPermissions;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.util.CollisionInitializer;
import com.projectkorra.projectkorra.ability.util.CollisionManager;
@ -26,7 +23,6 @@ import com.projectkorra.projectkorra.chiblocking.util.ChiblockingManager;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.configuration.ConfigManager;
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.WorldGuardFlag;
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.waterbending.util.WaterbendingManager;
import co.aikar.timings.lib.MCTiming;
import co.aikar.timings.lib.TimingManager;
public class ProjectKorra extends JavaPlugin {
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 WaterbendingManager(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.revertChecker = this.getServer().getScheduler().runTaskTimerAsynchronously(this, new RevertChecker(this), 0, 200);
if (ConfigManager.languageConfig.get().getBoolean("Chat.Branding.AutoAnnouncer.Enabled")) {
@ -103,6 +101,23 @@ public class ProjectKorra extends JavaPlugin {
}
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()) {
PKListener.getJumpStatistics().put(player, player.getStatistic(Statistic.JUMP));

View file

@ -153,4 +153,12 @@ public interface Ability {
* @see BendingPlayer#canBend(CoreAbility)
*/
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

@ -1,10 +1,13 @@
package com.projectkorra.projectkorra.ability;
package com.projectkorra.projectkorra.ability;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Particle.DustOptions;
import org.bukkit.Sound;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
@ -19,6 +22,8 @@ import com.projectkorra.projectkorra.util.ParticleEffect;
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) {
super(player);
}
@ -83,6 +88,12 @@ public abstract class AirAbility extends ElementalAbility {
return ParticleEffect.CLOUD;
} else if (particle.equalsIgnoreCase("smallsmoke")) {
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 {
return ParticleEffect.CLOUD;
}
@ -125,7 +136,18 @@ public abstract class AirAbility extends ElementalAbility {
* @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) {
getAirbendingParticles().display(loc, amount, xOffset, yOffset, 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);
}
}
/**

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");
}
@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) {
final BendingPlayer bPlayer = BendingPlayer.getBendingPlayer(player);
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
*/

View file

@ -1,11 +1,7 @@
package com.projectkorra.projectkorra.ability;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.ChatColor;
import org.bukkit.Location;
@ -14,21 +10,19 @@ import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.projectkorra.projectkorra.BendingPlayer;
import com.projectkorra.projectkorra.Element;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.configuration.ConfigManager;
import com.projectkorra.projectkorra.firebending.BlazeArc;
import com.projectkorra.projectkorra.util.Information;
import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
public abstract class FireAbility extends ElementalAbility {
private static final Map<Location, Information> TEMP_FIRE = new ConcurrentHashMap<Location, Information>();
public FireAbility(final Player player) {
super(player);
}
@ -52,7 +46,7 @@ public abstract class FireAbility extends ElementalAbility {
public void handleCollision(final Collision collision) {
super.handleCollision(collision);
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");
}
/**
* Creates a fire block meant to replace other blocks but reverts when the
* fire dissipates or is destroyed.
*/
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"));
if (TEMP_FIRE.containsKey(loc)) {
info = TEMP_FIRE.get(loc);
} else {
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 static TempBlock createTempFire(Location loc, BendingPlayer bPlayer) {
TempBlock tb = new TempBlock(loc.getBlock(), getFireColor(bPlayer));
tb.setRevertTime(ConfigManager.getConfig().getLong("Properties.Fire.RevertTicks"));
return tb;
}
public static TempBlock createTempFire(Block block, BendingPlayer bPlayer) {
TempBlock tb = new TempBlock(block, getFireColor(bPlayer));
tb.setRevertTime(ConfigManager.getConfig().getLong("Properties.Fire.RevertTicks"));
return tb;
}
public double getDayFactor(final double value) {
@ -113,10 +96,46 @@ public abstract class FireAbility extends ElementalAbility {
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() {
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) {
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) {
ParticleEffect.FLAME.display(loc, amount, xOffset, yOffset, zOffset);
public void playFirebendingParticles(final Location loc, final int amount, final double xOffset, final double yOffset, final double zOffset, final double speed) {
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) {
@ -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;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Effect;
@ -26,13 +27,14 @@ import com.projectkorra.projectkorra.BendingPlayer;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.util.Collision;
import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.earthbending.lava.LavaFlow;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class AirBlast extends AirAbility {
@ -70,8 +72,9 @@ public class AirBlast extends AirAbility {
private Vector direction;
private AirBurst source;
private Random random;
private ArrayList<Block> affectedLevers;
private ArrayList<Entity> affectedEntities;
private Set<Block> affectedLevers;
private Set<Entity> affectedEntities;
private VelocityBuilder velocity;
public AirBlast(final Player player) {
super(player);
@ -116,9 +119,6 @@ public class AirBlast extends AirAbility {
this.setFields();
this.affectedLevers = new ArrayList<>();
this.affectedEntities = new ArrayList<>();
// prevent the airburst related airblasts from triggering doors/levers/buttons.
this.canOpenDoors = false;
this.canPressButtons = false;
@ -151,8 +151,9 @@ public class AirBlast extends AirAbility {
this.isFromOtherOrigin = false;
this.showParticles = true;
this.random = new Random();
this.affectedLevers = new ArrayList<>();
this.affectedEntities = new ArrayList<>();
this.affectedLevers = new HashSet<>();
this.affectedEntities = new HashSet<>();
this.velocity = new VelocityBuilder();
}
private static void playOriginEffect(final Player player) {
@ -198,7 +199,7 @@ public class AirBlast extends AirAbility {
private void advanceLocation() {
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) {
playAirbendingSound(this.location);
@ -244,32 +245,21 @@ public class AirBlast extends AirAbility {
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);
if (Math.abs(entity.getVelocity().dot(push)) > knockback && entity.getVelocity().angle(push) > Math.PI / 3) {
push.normalize().add(entity.getVelocity()).multiply(knockback);
if (Math.abs(entity.getVelocity().dot(push)) > knockback * knockback && entity.getVelocity().angle(push) > Math.PI / 3) {
push.add(entity.getVelocity());
}
GeneralMethods.setVelocity(entity, push);
CoreAbility source = this;
if (this.source != null) {
new HorizontalVelocityTracker(entity, this.player, 200l, this.source);
} else {
new HorizontalVelocityTracker(entity, this.player, 200l, this);
source = this.source;
}
if (this.damage > 0 && entity instanceof LivingEntity && !entity.equals(this.player) && !this.affectedEntities.contains(entity)) {
if (this.source != null) {
DamageHandler.damageEntity(entity, this.damage, this.source);
} else {
DamageHandler.damageEntity(entity, this.damage, this);
}
velocity.direction(push).knockback(knockback).apply(entity, source, true, true);
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) {
@ -278,6 +268,7 @@ public class AirBlast extends AirAbility {
entity.setFireTicks(0);
breakBreathbendingHold(entity);
this.affectedEntities.add(entity);
}
@Override
@ -618,11 +609,11 @@ public class AirBlast extends AirAbility {
this.source = source;
}
public ArrayList<Block> getAffectedLevers() {
public Set<Block> getAffectedLevers() {
return this.affectedLevers;
}
public ArrayList<Entity> getAffectedEntities() {
public Set<Entity> getAffectedEntities() {
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.avatar.AvatarState;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class AirShield extends AirAbility {
@ -38,6 +39,7 @@ public class AirShield extends AirAbility {
private Random random;
private HashMap<Integer, Integer> angles;
private boolean dynamicCooldown;
private VelocityBuilder velocity;
public AirShield(final Player player) {
super(player);
@ -57,6 +59,7 @@ public class AirShield extends AirAbility {
}
this.random = new Random();
this.angles = new HashMap<>();
this.velocity = new VelocityBuilder();
if (this.bPlayer.isAvatarState() && hasAbility(player, AirShield.class) && this.isToggledByAvatarState) {
getAbility(player, AirShield.class).remove();
@ -160,8 +163,7 @@ public class AirShield extends AirAbility {
}
}
velocity.multiply(0.5);
GeneralMethods.setVelocity(entity, velocity);
this.velocity.direction(velocity).knockback(0.5).apply(entity, this);
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.attribute.Attribute;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
import com.projectkorra.projectkorra.util.VelocityBuilder;
import com.projectkorra.projectkorra.waterbending.WaterSpout;
public class AirSuction extends AirAbility {
@ -232,8 +232,7 @@ public class AirSuction extends AirAbility {
push.normalize().add(entity.getVelocity()).multiply(knockback);
}
GeneralMethods.setVelocity(entity, push.normalize().multiply(knockback));
new HorizontalVelocityTracker(entity, this.player, 200l, this);
new VelocityBuilder(push).knockback(knockback).apply(entity, this, true, false);
entity.setFallDistance(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.attribute.Attribute;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class Tornado extends AirAbility {
@ -40,7 +41,8 @@ public class Tornado extends AirAbility {
private double currentRadius;
private Location origin;
private final Random random;
private final Map<Integer, Integer> angles;
private final Map<Integer, Double> angles;
private VelocityBuilder velocity;
public Tornado(final Player player) {
super(player);
@ -55,18 +57,19 @@ public class Tornado extends AirAbility {
this.radius = getConfig().getDouble("Abilities.Air.Tornado.Radius");
this.npcPushFactor = getConfig().getDouble("Abilities.Air.Tornado.NpcPushFactor");
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.currentRadius = this.currentHeight / this.maxHeight * this.radius;
this.currentRadius = 0;
this.random = new Random();
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) {
this.angles.put(i, angle);
angle += 90;
if (angle == 360) {
angle = 0;
angle += 360 / this.numberOfStreams;
if (angle >= 360) {
angle -= 360;
}
}
@ -101,7 +104,7 @@ public class Tornado extends AirAbility {
}
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;
this.currentRadius = timefactor * this.radius;
@ -164,12 +167,8 @@ public class Tornado extends AirAbility {
}
}
final Vector velocity = entity.getVelocity().clone();
velocity.setX(vx);
velocity.setZ(vz);
velocity.setY(vy);
velocity.multiply(timefactor);
GeneralMethods.setVelocity(entity, velocity);
Vector dir = new Vector(vx, vy, vz);
this.velocity.direction(dir).knockback(dir.length() * timefactor).apply(entity, this);
entity.setFallDistance(0);
breakBreathbendingHold(entity);
@ -177,27 +176,34 @@ public class Tornado extends AirAbility {
}
}
for (final int i : this.angles.keySet()) {
double x, y, z, factor;
double angle = this.angles.get(i);
angle = Math.toRadians(angle);
double x, z;
for (double j = 0; j < currentHeight; j += 0.4) {
for (final int i : this.angles.keySet()) {
if (Math.random() < 0.4) {
continue;
}
y = this.origin.getY() + timefactor * i;
factor = i / this.currentHeight;
double angle = this.angles.get(i);
angle = Math.toRadians(angle);
x = this.origin.getX() + timefactor * factor * this.currentRadius * Math.cos(angle);
z = this.origin.getZ() + timefactor * factor * this.currentRadius * Math.sin(angle);
x = this.origin.getX() + (j / this.maxHeight) * this.radius * Math.cos(angle + j);
z = this.origin.getZ() + (j / this.maxHeight) * this.radius * Math.sin(angle + j);
final Location effect = new Location(this.origin.getWorld(), x, y, z);
if (!GeneralMethods.isRegionProtectedFromBuild(this, effect)) {
playAirbendingParticles(effect, this.particleCount);
if (this.random.nextInt(20) == 0) {
playAirbendingSound(effect);
final Location effect = new Location(this.origin.getWorld(), x, origin.getY() + j, z);
if (!GeneralMethods.isRegionProtectedFromBuild(this, effect)) {
playAirbendingParticles(effect, 1, 0.14, 0.14, 0.14);
if (this.random.nextInt(20) == 0) {
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;
}
@ -319,7 +325,7 @@ public class Tornado extends AirAbility {
this.currentRadius = currentRadius;
}
public Map<Integer, Integer> getAngles() {
public Map<Integer, Double> getAngles() {
return this.angles;
}
}

View file

@ -3,7 +3,6 @@ package com.projectkorra.projectkorra.airbending.combo;
import java.util.ArrayList;
import java.util.List;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
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.util.ClickType;
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 {
@ -152,7 +153,7 @@ public class AirSweep extends AirAbility implements ComboAbility {
fs.setDensity(1);
fs.setSpread(0F);
fs.setUseNewParticles(true);
fs.setParticleEffect(getAirbendingParticles());
fs.setParticleEffect(null);
fs.setCollides(false);
fs.runTaskTimer(ProjectKorra.plugin, (long) (i / 2.5), 1L);
this.tasks.add(fs);
@ -187,6 +188,9 @@ public class AirSweep extends AirAbility implements ComboAbility {
return;
}
}
playAirbendingParticles(loc, 1, 0, 0, 0);
if (i % 3 == 0) {
for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(loc, 2.5)) {
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 (this.knockback != 0) {
final Vector force = fstream.getLocation().getDirection();
GeneralMethods.setVelocity(entity, force.clone().multiply(this.knockback));
new HorizontalVelocityTracker(entity, this.player, 200l, this);
new VelocityBuilder(force).knockback(knockback).apply(entity, this, true, false);
entity.setFallDistance(0);
}
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.command.Commands;
import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class Twister extends AirAbility implements ComboAbility {
@ -146,7 +147,7 @@ public class Twister extends AirAbility implements ComboAbility {
continue;
}
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;
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();

View file

@ -281,6 +281,9 @@ public class WhoCommand extends PKCommand {
if (bPlayer.canLightningbend()) {
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)) {
if (bPlayer.canUseSubElement(se)) {
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.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.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.");
@ -235,6 +238,7 @@ public class ConfigManager {
config.addDefault("DeathMessages.Enabled", true);
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.");
@ -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.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.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.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.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.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.");
@ -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.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.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.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}");
@ -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.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.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.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.");
@ -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.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.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.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}");
@ -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.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.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.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}");
@ -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.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.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.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.");
@ -549,11 +557,16 @@ public class ConfigManager {
config.addDefault("Properties.SeaLevel", 62);
config.addDefault("Properties.ChooseCooldown", 0L);
config.addDefault("Properties.MaxPresets", 10);
config.addDefault("Properties.AbilityDamageTimestampDuration", 5000);
config.addDefault("Properties.HorizontalCollisionPhysics.Enabled", true);
config.addDefault("Properties.HorizontalCollisionPhysics.DamageOnBarrierBlock", false);
config.addDefault("Properties.HorizontalCollisionPhysics.WallDamageMinimumDistance", 5.0);
config.addDefault("Properties.HorizontalCollisionPhysics.WallDamageCap", 5.0);
config.addDefault("Properties.Autosave.Interval", 6000);
config.addDefault("Properties.CollisionPhysics.Enabled", true);
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.RespectWorldGuard", true);
@ -900,6 +913,7 @@ public class ConfigManager {
config.addDefault("Abilities.Air.Tornado.Speed", 1);
config.addDefault("Abilities.Air.Tornado.NpcPushFactor", 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.Speed", 0.35);
@ -1317,6 +1331,8 @@ public class ConfigManager {
config.addDefault("Abilities.Earth.EarthPillars.Damage.Value", 2);
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.Arc", 14);
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.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class EarthSmash extends EarthAbility {
@ -76,6 +77,7 @@ public class EarthSmash extends EarthAbility {
private ArrayList<Entity> affectedEntities;
private ArrayList<BlockRepresenter> currentBlocks;
private ArrayList<TempBlock> affectedBlocks;
private VelocityBuilder velocity;
public EarthSmash(final Player player, final ClickType type) {
super(player);
@ -87,6 +89,7 @@ public class EarthSmash extends EarthAbility {
this.affectedEntities = new ArrayList<>();
this.currentBlocks = new ArrayList<>();
this.affectedBlocks = new ArrayList<>();
this.velocity = new VelocityBuilder();
if (type == ClickType.SHIFT_DOWN || type == ClickType.SHIFT_UP && !player.isSneaking()) {
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()))) {
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.
@ -573,7 +577,7 @@ public class EarthSmash extends EarthAbility {
final double damage = this.currentBlocks.size() / 13.0 * this.damage;
DamageHandler.damageEntity(entity, damage, this);
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.command.Commands;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class Ripple extends EarthAbility {
@ -283,9 +284,8 @@ public class Ripple extends EarthAbility {
}
final Vector vector = this.direction.clone();
vector.setY(.5);
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);
}

View file

@ -22,7 +22,6 @@ public class AbilityDamageEntityEvent extends Event implements Cancellable {
private final Entity entity;
private final Ability ability;
private double damage;
private final boolean ignoreArmor;
/**
* Create a new AbilityDamageEntityEvent
@ -31,11 +30,10 @@ public class AbilityDamageEntityEvent extends Event implements Cancellable {
* @param ability The damaging ability
* @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.ability = ability;
this.damage = damage;
this.ignoreArmor = ignoreArmor;
}
/**
@ -74,10 +72,6 @@ public class AbilityDamageEntityEvent extends Event implements Cancellable {
return this.ability;
}
public boolean doesIgnoreArmor() {
return this.ignoreArmor;
}
/**
* 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.HandlerList;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.Ability;
/**
* Called when an entity is killed by
* {@link GeneralMethods#damageEntity(Player player, Entity entity, double damage, String ability)
* GeneralMethods.damageEntity}
* Called when an entity is killed by Bending
*/
public class EntityBendingDeathEvent extends Event {
@ -19,20 +16,16 @@ public class EntityBendingDeathEvent extends Event {
public static final HandlerList handlers = new HandlerList();
private final Entity entity;
private final Ability ability;
private final double damage;
/**
* Creates a new EntityBendingDeathEvent
*
* @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
*/
public EntityBendingDeathEvent(final Entity entity, final double damage, final Ability ability) {
public EntityBendingDeathEvent(final Entity entity, final Ability ability) {
this.entity = entity;
this.ability = ability;
this.damage = damage;
}
/**
@ -59,14 +52,6 @@ public class EntityBendingDeathEvent extends Event {
return this.ability;
}
/**
*
* @return the amount of damage done in the attack that killed the victim
*/
public double getDamage() {
return this.damage;
}
@Override
public HandlerList getHandlers() {
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;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
@ -16,14 +12,12 @@ import com.projectkorra.projectkorra.Element;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
public class BlazeArc extends FireAbility {
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 interval;
@ -53,19 +47,19 @@ public class BlazeArc extends FireAbility {
}
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 (isPlant(block) || isSnow(block)) {
new PlantRegrowth(this.player, block);
}
} else if (block.getType() != Material.FIRE) {
REPLACED_BLOCKS.put(block.getLocation(), block.getState());
}
}
block.setType(Material.FIRE);
IGNITED_BLOCKS.put(block, this.player);
IGNITED_TIMES.put(block, System.currentTimeMillis());
new TempBlock(block, getFireColor()).setRevertTime(DISSIPATE_REMOVE_TIME);
}
@Override
@ -78,7 +72,7 @@ public class BlazeArc extends FireAbility {
this.time = System.currentTimeMillis();
final Block block = this.location.getBlock();
if (block.getType() == Material.FIRE) {
if (isFire(block)) {
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) {
Block top = block;
Block top = GeneralMethods.isSolid(block) ? block.getRelative(BlockFace.UP) : block;
for (int i = 0; i < 2; i++) {
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) {
for (final BlazeArc stream : getAbilities(BlazeArc.class)) {
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
public String getName() {
return "Blaze";
@ -268,18 +218,6 @@ public class BlazeArc extends FireAbility {
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) {
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.avatar.AvatarState;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.firebending.util.FireDamageTimer;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
@ -127,8 +126,8 @@ public class FireBlast extends FireAbility {
}
if (this.showParticles) {
ParticleEffect.FLAME.display(this.location, 6, this.flameRadius, this.flameRadius, this.flameRadius);
ParticleEffect.SMOKE_NORMAL.display(this.location, 3, this.smokeRadius, this.smokeRadius, this.smokeRadius);
playFirebendingParticles(this.location, 12, this.flameRadius, this.flameRadius, this.flameRadius);
ParticleEffect.SMOKE_NORMAL.display(this.location, 2, this.smokeRadius, this.smokeRadius, this.smokeRadius);
}
if (GeneralMethods.checkDiagonalWall(this.location, this.direction)) {
@ -154,27 +153,21 @@ public class FireBlast extends FireAbility {
entity.setFireTicks((int) (this.fireTicks * 20));
DamageHandler.damageEntity(entity, this.damage, this);
AirAbility.breakBreathbendingHold(entity);
new FireDamageTimer(entity, this.player);
this.remove();
}
}
}
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 (canFireGrief()) {
if (isPlant(block) || isSnow(block)) {
new PlantRegrowth(this.player, block);
}
block.setType(Material.FIRE);
block.setType(getFireColor(bPlayer));
} else {
createTempFire(block.getLocation());
}
if (this.dissipate) {
BlazeArc.getIgnitedBlocks().put(block, this.player);
BlazeArc.getIgnitedTimes().put(block, System.currentTimeMillis());
createTempFire(block, bPlayer);
}
}
}
@ -221,6 +214,11 @@ public class FireBlast extends FireAbility {
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();
}

View file

@ -5,7 +5,6 @@ import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
@ -207,7 +206,7 @@ public class FireBlastCharged extends FireAbility {
private void executeFireball() {
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);
if ((new Random()).nextInt(4) == 0) {
playFirebendingSound(this.location);
@ -234,14 +233,7 @@ public class FireBlastCharged extends FireAbility {
private void ignite(final Location location) {
for (final Block block : GeneralMethods.getBlocksAroundPoint(location, this.collisionRadius)) {
if (BlazeArc.isIgnitable(this.player, block)) {
if (block.getType() != Material.FIRE) {
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());
}
createTempFire(block, bPlayer);
}
}
}
@ -282,7 +274,7 @@ public class FireBlastCharged extends FireAbility {
if (!this.launched && !this.charged) {
return;
} 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;
}

View file

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

View file

@ -7,14 +7,16 @@ import java.util.Random;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
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.FireAbility;
import com.projectkorra.projectkorra.airbending.AirSpout;
import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.VelocityBuilder;
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()) {
player.setVelocity(player.getEyeLocation().getDirection().clone().normalize().multiply(this.speed));
if (!canFireGrief()) {
if (ElementalAbility.isAir(block.getType())) {
createTempFire(block.getLocation());
if (ElementalAbility.isAir(block.getType()) && GeneralMethods.isSolid(block.getRelative(BlockFace.DOWN))) {
createTempFire(block, bPlayer);
}
} else if (ElementalAbility.isAir(block.getType())) {
block.setType(Material.FIRE);
block.setType(getFireColor());
}
this.flightHandler.createInstance(player, this.getName());
@ -93,7 +95,7 @@ public class FireJet extends FireAbility {
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);
double timefactor;
@ -103,8 +105,7 @@ public class FireJet extends FireAbility {
timefactor = 1 - (System.currentTimeMillis() - this.time) / (2.0 * this.duration);
}
final Vector velocity = this.player.getEyeLocation().getDirection().clone().normalize().multiply(this.speed * timefactor);
this.player.setVelocity(velocity);
new VelocityBuilder(player.getEyeLocation().getDirection()).knockback(this.speed * timefactor).apply(player, this);
this.player.setFallDistance(0);
}
}

View file

@ -113,7 +113,7 @@ public class FireManipulation extends FireAbility {
this.points.remove(point);
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);
for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(point, 1.2D)) {
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()) {
final Vector direction = this.focalPoint.toVector().subtract(point.toVector());
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);
}
} else {
@ -173,7 +173,7 @@ public class FireManipulation extends FireAbility {
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);
for (final Entity entity : GeneralMethods.getEntitiesAroundPoint(this.shotPoint, 2)) {
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.util.Collision;
import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.firebending.util.FireDamageTimer;
import com.projectkorra.projectkorra.util.ParticleEffect;
public class FireShield extends FireAbility {
@ -129,7 +128,7 @@ public class FireShield extends FireAbility {
ParticleEffect.SMOKE_NORMAL.display(display, 1, 0, 0, 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) {
playFirebendingSound(display);
@ -143,7 +142,7 @@ public class FireShield extends FireAbility {
}
for (final Block testblock : GeneralMethods.getBlocksAroundPoint(this.player.getLocation(), this.shieldRadius)) {
if (testblock.getType() == Material.FIRE) {
if (isFire(testblock)) {
testblock.setType(Material.AIR);
testblock.getWorld().playEffect(testblock.getLocation(), Effect.EXTINGUISH, 0);
}
@ -155,7 +154,6 @@ public class FireShield extends FireAbility {
} else if (entity instanceof LivingEntity) {
if (this.player.getEntityId() != entity.getEntityId() && this.ignite) {
entity.setFireTicks((int) (this.shieldFireTicks * 20));
new FireDamageTimer(entity, this.player);
}
} else if (entity instanceof Projectile) {
entity.remove();
@ -165,7 +163,7 @@ public class FireShield extends FireAbility {
this.location = this.player.getEyeLocation().clone();
final Vector direction = this.location.getDirection();
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) {
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) {
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) {
playFirebendingSound(display);
}
@ -186,7 +184,6 @@ public class FireShield extends FireAbility {
} else if (entity instanceof LivingEntity) {
if (this.player.getEntityId() != entity.getEntityId() && this.ignite) {
entity.setFireTicks((int) (this.discFireTicks * 20));
new FireDamageTimer(entity, this.player);
}
} else if (entity instanceof Projectile) {
entity.remove();

View file

@ -193,9 +193,7 @@ public class HeatControl extends FireAbility {
}
for (final Block block : GeneralMethods.getBlocksAroundPoint(this.player.getLocation(), this.extinguishRadius)) {
final Material material = block.getType();
if (material == Material.FIRE && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) {
if (isFire(block) && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) {
block.setType(Material.AIR);
block.getWorld().playEffect(block.getLocation(), Effect.EXTINGUISH, 0);
}
@ -281,7 +279,7 @@ public class HeatControl extends FireAbility {
}
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);
}

View file

@ -125,7 +125,7 @@ public class Illumination extends FireAbility {
}
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);
}

View file

@ -15,7 +15,6 @@ import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.AirAbility;
import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.firebending.util.FireDamageTimer;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
@ -115,7 +114,6 @@ public class WallOfFire extends FireAbility {
AirAbility.breakBreathbendingHold(entity);
}
entity.setFireTicks((int) (this.fireTicks * 20));
new FireDamageTimer(entity, this.player);
}
private void damage() {
@ -147,7 +145,7 @@ public class WallOfFire extends FireAbility {
if (!this.isTransparent(block)) {
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);
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.ToStringStyle;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.block.Block;
@ -18,8 +16,8 @@ import com.projectkorra.projectkorra.BendingPlayer;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.ability.ElementalAbility;
import com.projectkorra.projectkorra.ability.FireAbility;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.firebending.util.FireDamageTimer;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect;
@ -61,9 +59,9 @@ public class FireComboStream extends BukkitRunnable {
this.checkCollisionCounter = 0;
this.spread = 0;
this.collisionRadius = 2;
this.particleEffect = ParticleEffect.FLAME;
this.player = player;
this.bPlayer = BendingPlayer.getBendingPlayer(player);
this.particleEffect = FireAbility.getFireParticle(bPlayer);
this.coreAbility = coreAbility;
this.direction = direction;
this.speed = speed;
@ -79,12 +77,13 @@ public class FireComboStream extends BukkitRunnable {
this.remove();
return;
}
for (int i = 0; i < this.density; i++) {
if (this.useNewParticles) {
this.particleEffect.display(this.location, 1, this.spread, this.spread, this.spread);
} else {
this.location.getWorld().playEffect(this.location, Effect.MOBSPAWNER_FLAMES, 0, 15);
if (this.useNewParticles) {
if (particleEffect != null) {
this.particleEffect.display(this.location, this.density, this.spread, this.spread, this.spread);
}
} else {
FireAbility.getFireParticle(bPlayer).display(this.location, this.density, this.spread, this.spread, this.spread);
}
if (GeneralMethods.checkDiagonalWall(this.location, this.direction)) {
@ -144,7 +143,6 @@ public class FireComboStream extends BukkitRunnable {
jetBlaze.getAffectedEntities().add(entity);
DamageHandler.damageEntity(entity, this.damage, coreAbility);
entity.setFireTicks((int) (this.fireTicks * 20));
new FireDamageTimer(entity, this.player);
}
} else if (coreAbility.getName().equalsIgnoreCase("FireWheel")) {
final FireWheel fireWheel = CoreAbility.getAbility(this.player, FireWheel.class);
@ -153,7 +151,6 @@ public class FireComboStream extends BukkitRunnable {
fireWheel.getAffectedEntities().add(entity);
DamageHandler.damageEntity(entity, this.damage, coreAbility);
entity.setFireTicks((int) (this.fireTicks * 20));
new FireDamageTimer(entity, this.player);
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.util.ComboManager.AbilityInformation;
import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.firebending.util.FireDamageTimer;
import com.projectkorra.projectkorra.util.ClickType;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.ParticleEffect;
public class FireWheel extends FireAbility implements ComboAbility {
@ -120,7 +118,7 @@ public class FireWheel extends FireAbility implements ComboAbility {
if (topBlock == null || isWater(topBlock)) {
this.remove();
return;
} else if (topBlock.getType() == Material.FIRE) {
} else if (isFire(topBlock)) {
topBlock = topBlock.getRelative(BlockFace.DOWN);
} else if (ElementalAbility.isPlant(topBlock)) {
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)));
tempLoc.add(newDir);
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)) {
@ -148,7 +146,6 @@ public class FireWheel extends FireAbility implements ComboAbility {
this.affectedEntities.add((LivingEntity) entity);
DamageHandler.damageEntity(entity, this.damage, this);
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);
fs.setDensity(1);
fs.setDensity(2);
fs.setSpread(0.9F);
fs.setUseNewParticles(true);
fs.setCollides(false);

View file

@ -6,6 +6,7 @@ import java.util.List;
import com.projectkorra.projectkorra.ability.CoreAbility;
import com.projectkorra.projectkorra.firebending.FireJet;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
@ -498,6 +499,7 @@ public class Lightning extends LightningAbility {
this.cancel();
} else if (this.count == 1) {
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();
return;
}
@ -546,6 +548,7 @@ public class Lightning extends LightningAbility {
}
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.
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;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
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 {
private static boolean initialised = false;
private static Constructor<?> chatSer;
private static Constructor<?> packetChat;
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);
public static void sendActionBar(final String message, final Player... players) {
for (Player player : players) {
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(message));
}
}
}

View file

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

View file

@ -10,6 +10,7 @@ import org.bukkit.scheduler.BukkitRunnable;
import com.projectkorra.projectkorra.Manager;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.object.VelocityTracker;
public class FlightHandler extends Manager {
@ -82,6 +83,11 @@ public class FlightHandler extends Manager {
* @param identifier The ability using Flight
*/
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())) {
final Flight flight = this.INSTANCES.get(player.getUniqueId());
final FlightAbility ability = new FlightAbility(player, identifier, duration);

View file

@ -6,6 +6,7 @@ import org.bukkit.Particle.DustOptions;
import org.bukkit.inventory.ItemStack;
public enum ParticleEffect {
ASH (Particle.ASH),
BARRIER (Particle.BARRIER),
/**
@ -21,7 +22,7 @@ public enum ParticleEffect {
BUBBLE_POP (Particle.BUBBLE_POP),
CLOUD (Particle.CLOUD),
CRIT (Particle.CRIT),
CRIT_MAGIC (Particle.CRIT_MAGIC), @Deprecated MAGIC_CRIT (Particle.CRIT_MAGIC),
CRIT_MAGIC (Particle.CRIT_MAGIC),
CURRENT_DOWN (Particle.CURRENT_DOWN),
DAMAGE_INDICATOR (Particle.DAMAGE_INDICATOR),
DOLPHIN (Particle.DOLPHIN),
@ -30,9 +31,9 @@ public enum ParticleEffect {
DRIP_WATER (Particle.DRIP_WATER),
ENCHANTMENT_TABLE (Particle.ENCHANTMENT_TABLE),
END_ROD (Particle.END_ROD),
EXPLOSION_HUGE (Particle.EXPLOSION_HUGE), @Deprecated HUGE_EXPLOSION (Particle.EXPLOSION_HUGE),
EXPLOSION_LARGE (Particle.EXPLOSION_LARGE), @Deprecated LARGE_EXPLODE (Particle.EXPLOSION_LARGE),
EXPLOSION_NORMAL (Particle.EXPLOSION_NORMAL), @Deprecated EXPLODE (Particle.EXPLOSION_NORMAL),
EXPLOSION_HUGE (Particle.EXPLOSION_HUGE),
EXPLOSION_LARGE (Particle.EXPLOSION_LARGE),
EXPLOSION_NORMAL (Particle.EXPLOSION_NORMAL),
/**
* Applicable data: {@link BlockData}
@ -55,30 +56,32 @@ public enum ParticleEffect {
/**
* Applicable data: {@link DustOptions}
*/
REDSTONE (Particle.REDSTONE), @Deprecated RED_DUST (Particle.REDSTONE),
REDSTONE (Particle.REDSTONE),
SLIME (Particle.SLIME),
SMOKE_NORMAL (Particle.SMOKE_NORMAL), @Deprecated SMOKE (Particle.SMOKE_NORMAL),
SMOKE_LARGE (Particle.SMOKE_LARGE), @Deprecated LARGE_SMOKE (Particle.SMOKE_LARGE),
SMOKE_NORMAL (Particle.SMOKE_NORMAL),
SMOKE_LARGE (Particle.SMOKE_LARGE),
SNOW_SHOVEL (Particle.SNOW_SHOVEL),
SNOWBALL (Particle.SNOWBALL), @Deprecated SNOWBALL_PROOF (Particle.SNOWBALL),
SNOWBALL (Particle.SNOWBALL),
SPELL (Particle.SPELL),
SPELL_INSTANT (Particle.SPELL_INSTANT), @Deprecated INSTANT_SPELL (Particle.SPELL_INSTANT),
SPELL_MOB (Particle.SPELL_MOB), @Deprecated MOB_SPELL (Particle.SPELL_MOB),
SPELL_MOB_AMBIENT (Particle.SPELL_MOB_AMBIENT), @Deprecated MOB_SPELL_AMBIENT (Particle.SPELL_MOB_AMBIENT),
SPELL_WITCH (Particle.SPELL_WITCH), @Deprecated WITCH_SPELL (Particle.SPELL_WITCH),
SPELL_INSTANT (Particle.SPELL_INSTANT),
SPELL_MOB (Particle.SPELL_MOB),
SPELL_MOB_AMBIENT (Particle.SPELL_MOB_AMBIENT),
SPELL_WITCH (Particle.SPELL_WITCH),
SPIT (Particle.SPIT),
SOUL (Particle.SOUL),
SOUL_FLAME (Particle.SOUL_FIRE_FLAME),
SQUID_INK (Particle.SQUID_INK),
SUSPENDED (Particle.SUSPENDED), @Deprecated SUSPEND (Particle.SUSPENDED),
SUSPENDED_DEPTH (Particle.SUSPENDED_DEPTH), @Deprecated DEPTH_SUSPEND (Particle.SUSPENDED_DEPTH),
SUSPENDED (Particle.SUSPENDED),
SUSPENDED_DEPTH (Particle.SUSPENDED_DEPTH),
SWEEP_ATTACK (Particle.SWEEP_ATTACK),
TOTEM (Particle.TOTEM),
TOWN_AURA (Particle.TOWN_AURA),
VILLAGER_ANGRY (Particle.VILLAGER_ANGRY), @Deprecated ANGRY_VILLAGER (Particle.VILLAGER_ANGRY),
VILLAGER_HAPPY (Particle.VILLAGER_HAPPY), @Deprecated HAPPY_VILLAGER (Particle.VILLAGER_HAPPY),
WATER_BUBBLE (Particle.WATER_BUBBLE), @Deprecated BUBBLE (Particle.WATER_BUBBLE),
VILLAGER_ANGRY (Particle.VILLAGER_ANGRY),
VILLAGER_HAPPY (Particle.VILLAGER_HAPPY),
WATER_BUBBLE (Particle.WATER_BUBBLE),
WATER_DROP (Particle.WATER_DROP),
WATER_SPLASH (Particle.WATER_SPLASH), @Deprecated SPLASH (Particle.WATER_SPLASH),
WATER_WAKE (Particle.WATER_WAKE), @Deprecated WAKE (Particle.WATER_WAKE);
WATER_SPLASH (Particle.WATER_SPLASH),
WATER_WAKE (Particle.WATER_WAKE);
Particle particle;
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.ParticleEffect;
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.PhaseChangeType;
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) {
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() {
@ -206,7 +207,7 @@ public class OctopusForm extends WaterAbility {
}
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) {
DamageHandler.damageEntity(entity, this.damage, this);
@ -253,7 +254,7 @@ public class OctopusForm extends WaterAbility {
this.sourceLocation = newBlock.getLocation();
if (!GeneralMethods.isSolid(newBlock)) {
this.source = new TempBlock(newBlock, Material.WATER, GeneralMethods.getWaterData(0));
this.source = new TempBlock(newBlock, Material.WATER);
this.sourceBlock = newBlock;
} else {
this.remove();
@ -266,7 +267,7 @@ public class OctopusForm extends WaterAbility {
this.sourceLocation = newBlock.getLocation();
if (!GeneralMethods.isSolid(newBlock)) {
this.source = new TempBlock(newBlock, Material.WATER, GeneralMethods.getWaterData(0));
this.source = new TempBlock(newBlock, Material.WATER);
this.sourceBlock = newBlock;
} else {
this.remove();
@ -282,7 +283,7 @@ public class OctopusForm extends WaterAbility {
this.source.revertBlock();
}
if (!GeneralMethods.isSolid(newBlock)) {
this.source = new TempBlock(newBlock, Material.WATER, GeneralMethods.getWaterData(0));
this.source = new TempBlock(newBlock, Material.WATER);
this.sourceBlock = newBlock;
}
}
@ -426,7 +427,7 @@ public class OctopusForm extends WaterAbility {
if (!SurgeWave.canThaw(block)) {
SurgeWave.thaw(block);
}
tblock.setType(Material.WATER, GeneralMethods.getWaterData(0));
tblock.setType(Material.WATER);
this.newBlocks.add(tblock);
} else if (this.blocks.contains(tblock)) {
this.newBlocks.add(tblock);
@ -435,7 +436,7 @@ public class OctopusForm extends WaterAbility {
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);
}
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.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
import com.projectkorra.projectkorra.waterbending.util.WaterReturn;
@ -107,7 +108,7 @@ public class SurgeWave extends WaterAbility {
if (GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) {
return;
} else if (!TempBlock.isTempBlock(block)) {
new TempBlock(block, Material.WATER, GeneralMethods.getWaterData(0));
new TempBlock(block, Material.WATER);
this.waveBlocks.put(block, block);
}
}
@ -349,8 +350,7 @@ public class SurgeWave extends WaterAbility {
continue;
}
final Vector dir = direction.clone();
dir.setY(dir.getY() * this.knockup);
GeneralMethods.setVelocity(entity, entity.getVelocity().clone().add(dir.clone().multiply(this.getNightFactor(this.knockback))));
new VelocityBuilder(dir).knockback(this.knockback).knockup(dir.getY() * this.knockup).apply(entity, this, true, canHitSelf);
entity.setFallDistance(0);
if (entity.getFireTicks() > 0) {

View file

@ -8,7 +8,6 @@ import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.Location;
import org.bukkit.Material;
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.ParticleEffect;
import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
import com.projectkorra.projectkorra.waterbending.util.WaterReturn;
@ -207,7 +207,7 @@ public class Torrent extends WaterAbility {
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();
} else {
playFocusWaterEffect(this.sourceBlock);
@ -261,7 +261,7 @@ public class Torrent extends WaterAbility {
this.remove();
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()) {
@ -354,7 +354,7 @@ public class Torrent extends WaterAbility {
final Block block = blockloc.getBlock();
if (!doneBlocks.contains(block) && !GeneralMethods.isRegionProtectedFromBuild(this, blockloc)) {
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);
} else if (!isTransparent(this.player, block)) {
break;
@ -422,7 +422,7 @@ public class Torrent extends WaterAbility {
if (isWater(locBlock)) {
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 {
if (this.layer < this.maxLayer) {
if (this.layer == 0) {
@ -487,7 +487,7 @@ public class Torrent extends WaterAbility {
final Block block = blockLoc.getBlock();
if (!doneBlocks.contains(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);
for (final Entity entity : entities) {
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()))) {
return;
}
VelocityBuilder velocity = new VelocityBuilder(direction);
if (direction.getY() > this.knockup) {
direction.setY(this.knockup);
velocity.knockup(this.knockup);
}
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)) {
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.command.Commands;
import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
import com.projectkorra.projectkorra.waterbending.util.WaterReturn;
public class TorrentWave extends WaterAbility {
@ -140,7 +141,7 @@ public class TorrentWave extends WaterAbility {
}
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);
torrentBlocks.add(block);
} else {
@ -178,9 +179,7 @@ public class TorrentWave extends WaterAbility {
private void affect(final Entity entity) {
final Vector direction = GeneralMethods.getDirection(this.origin, entity.getLocation());
direction.setY(0);
direction.normalize();
entity.setVelocity(entity.getVelocity().clone().add(direction.multiply(this.knockback)));
new VelocityBuilder(direction).knockback(this.knockback).knockup(0).apply(entity, this, true, false);
}
@Override

View file

@ -28,6 +28,7 @@ import com.projectkorra.projectkorra.attribute.Attribute;
import com.projectkorra.projectkorra.command.Commands;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.TempBlock;
import com.projectkorra.projectkorra.util.VelocityBuilder;
import com.projectkorra.projectkorra.waterbending.combo.IceWave;
import com.projectkorra.projectkorra.waterbending.plant.PlantRegrowth;
@ -300,7 +301,7 @@ public class WaterSpoutWave extends WaterAbility {
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)) {
if (ElementalAbility.isAir(block.getType()) && !GeneralMethods.isRegionProtectedFromBuild(this, block.getLocation())) {
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.attribute.Attribute;
import com.projectkorra.projectkorra.avatar.AvatarState;
import com.projectkorra.projectkorra.object.HorizontalVelocityTracker;
import com.projectkorra.projectkorra.util.DamageHandler;
import com.projectkorra.projectkorra.util.TempPotionEffect;
import com.projectkorra.projectkorra.util.VelocityBuilder;
public class Bloodbending extends BloodAbility {
@ -128,7 +128,6 @@ public class Bloodbending extends BloodAbility {
}
DamageHandler.damageEntity(this.target, 0, this);
HorizontalVelocityTracker.remove(this.target);
AirAbility.breakBreathbendingHold(this.target);
TARGETED_ENTITIES.put(this.target, player);
}
@ -152,9 +151,8 @@ public class Bloodbending extends BloodAbility {
if (location.getWorld().equals(target.getWorld())) {
vector = GeneralMethods.getDirection(location, GeneralMethods.getTargetedLocation(this.player, location.distance(target)));
}
vector.normalize();
entity.setVelocity(vector.multiply(this.knockback));
new HorizontalVelocityTracker(entity, this.player, 200, this);
new VelocityBuilder(vector).knockback(knockback).apply(entity, this, true, false);
}
this.remove();
this.bPlayer.addCooldown(this);

View file

@ -214,7 +214,7 @@ public class HealingWaters extends HealingAbility {
private void applyHealing(final Player player) {
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);
this.healing = true;
this.healingSelf = true;
@ -223,7 +223,7 @@ public class HealingWaters extends HealingAbility {
private void applyHealing(final LivingEntity livingEntity) {
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);
this.healing = true;
this.healingSelf = false;