mirror of
https://github.com/TotalFreedomMC/TF-ProjectKorra.git
synced 2024-05-15 17:31:26 +00:00
102112ffdd
## Fixes * Fixed Combos and possibly Passives appearing in `/pk b <Ability>` auto-tabbing. * Fixed Combos not loading properly on certain servers. * Fixed issue with `PreciousStones` by updating to the latest version to resolve API change issues. * Fixed `RapidPunch` damage. * Fixed incorrect summation of chiblocking chance. * Fixed possible issue in PKListener#onPlayerInteraction() * Fixed `Earth.LavaSound`. * Fixed Chi attempting to chiblock targets with any move. * Fixed hitting an entity with `TempArmor` not ignoring armor. * Fixed `Immobilize` config path. ## Additions * Added "Contributing" section to the `README` to help guide active community members. * Added more detail to the `PULL_REQUEST_TEMPLATE` to allow for more uniform pull requests. * Added many new blocks to our ability block interaction. * Added check to combo collisions to discard dead entities. * Added functionality to allow chiblocking abilities to affect all entities. * Added exception handling to the configurable `Sound` options to prevent `IllegalArgumentExcpetions`. * Added sounds and `ActionBar` messages to being Bloodbent, Electrocuted, Immobilized, MetalClipped, and Paralyzed. (Abilities: `Bloodbending`, `Lightning`, `Immobilize`, `MetalClips`, and `Paralyze`) * Added sound and `ActionBar` message for being Chiblocked. * Added interval config option to `RapidPunch`. (time between each punch) ## API Changes * Updated to `Spigot 1.12.1`. * Confirmed to be backward compatible with `Spigot 1.12` and `Spigot 1.11.2`. * Renamed `ElementalAbility#getTransparentMaterial()` to `ElementalAbility#getTransparentMaterials()`. * Converted most `byte`/`int` dependent `Material` logic to use `Material` instead. * `ElementalAbility#getTransparentMaterialSet()` now returns a `HashSet<Material>` instead of a `HashSet<Byte>`. * `ElementalAbility#getTransparentMaterials()` and `GeneralMethods.NON_OPAQUE` now return `Material[]` instead of `Integer[]`. * `GeneralMethods#getTargetedLocation()` now takes a `varargs Material[]` instead of a `varargs Integer[]`. * Removed `ElementalAbility.TRANSPARENT_MATERIAL`. It was outdated and became irrelevent after `GeneralMethods.NON_OPAQUE` was updated. * Removed `Java 7` Travi-CI JDK check. * Updated `pom.xml` to build in `Java 8`. * Added new `MovementHandler` utility class to control entity movement. (currently only capable of stopping movement.
465 lines
11 KiB
Java
465 lines
11 KiB
Java
package com.projectkorra.projectkorra.earthbending.lava;
|
|
|
|
import com.projectkorra.projectkorra.GeneralMethods;
|
|
import com.projectkorra.projectkorra.ability.LavaAbility;
|
|
import com.projectkorra.projectkorra.avatar.AvatarState;
|
|
import com.projectkorra.projectkorra.firebending.FireBlast;
|
|
import com.projectkorra.projectkorra.util.BlockSource;
|
|
import com.projectkorra.projectkorra.util.BlockSource.BlockSourceType;
|
|
import com.projectkorra.projectkorra.util.ClickType;
|
|
import com.projectkorra.projectkorra.util.TempBlock;
|
|
|
|
import org.bukkit.Effect;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.block.Block;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.util.Vector;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
public class LavaSurgeWall extends LavaAbility {
|
|
|
|
private static final Map<Block, Block> AFFECTED_BLOCKS = new ConcurrentHashMap<Block, Block>();
|
|
private static final Map<Block, Player> WALL_BLOCKS = new ConcurrentHashMap<Block, Player>();
|
|
private static final int SURGE_WAVE_RANGE = 20; // TODO: remove this
|
|
|
|
private boolean progressing;
|
|
private boolean settingUp;
|
|
private boolean forming;
|
|
private long time;
|
|
private long interval;
|
|
private long cooldown;
|
|
private double radius;
|
|
private double range;
|
|
private Block sourceBlock;
|
|
private Location location;
|
|
private Location firstDestination;
|
|
private Location targetDestination;
|
|
private Vector firstDirection;
|
|
private Vector targetDirection;
|
|
|
|
public LavaSurgeWall(Player player) {
|
|
super(player);
|
|
|
|
this.interval = 30;
|
|
this.radius = getConfig().getDouble("Abilities.Water.Surge.Wall.Radius");
|
|
this.range = getConfig().getDouble("Abilities.Water.Surge.Wall.Range");
|
|
this.cooldown = GeneralMethods.getGlobalCooldown();
|
|
|
|
LavaSurgeWave wave = getAbility(player, LavaSurgeWave.class);
|
|
if (wave != null && wave.isProgressing()) {
|
|
LavaSurgeWave.launch(player);
|
|
return;
|
|
}
|
|
|
|
if (bPlayer.isAvatarState()) {
|
|
radius = AvatarState.getValue(radius);
|
|
range = AvatarState.getValue(range);
|
|
}
|
|
|
|
if (!bPlayer.canBend(this)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
public boolean prepare() {
|
|
cancelPrevious();
|
|
Block block = BlockSource.getSourceBlock(player, range, BlockSourceType.LAVA, ClickType.LEFT_CLICK);
|
|
if (block != null) {
|
|
sourceBlock = block;
|
|
focusBlock();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void cancelPrevious() {
|
|
LavaSurgeWall lavaWall = getAbility(player, LavaSurgeWall.class);
|
|
if (lavaWall != null) {
|
|
if (lavaWall.progressing) {
|
|
lavaWall.removeLava(lavaWall.sourceBlock);
|
|
} else {
|
|
lavaWall.cancel();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void cancel() {
|
|
remove();
|
|
}
|
|
|
|
private void focusBlock() {
|
|
location = sourceBlock.getLocation();
|
|
}
|
|
|
|
public void moveLava() {
|
|
if (sourceBlock != null) {
|
|
targetDestination = getTargetEarthBlock((int) range).getLocation();
|
|
|
|
if (targetDestination.distanceSquared(location) <= 1) {
|
|
progressing = false;
|
|
targetDestination = null;
|
|
} else {
|
|
progressing = true;
|
|
settingUp = true;
|
|
firstDestination = getToEyeLevel();
|
|
firstDirection = getDirection(sourceBlock.getLocation(), firstDestination);
|
|
targetDirection = getDirection(firstDestination, targetDestination);
|
|
|
|
if (!GeneralMethods.isAdjacentToThreeOrMoreSources(sourceBlock)) {
|
|
sourceBlock.setType(Material.AIR);
|
|
}
|
|
addLava(sourceBlock);
|
|
}
|
|
}
|
|
}
|
|
|
|
private Location getToEyeLevel() {
|
|
Location loc = sourceBlock.getLocation().clone();
|
|
loc.setY(targetDestination.getY());
|
|
return loc;
|
|
}
|
|
|
|
private Vector getDirection(Location location, Location destination) {
|
|
double x1, y1, z1;
|
|
double x0, y0, z0;
|
|
x1 = destination.getX();
|
|
y1 = destination.getY();
|
|
z1 = destination.getZ();
|
|
x0 = location.getX();
|
|
y0 = location.getY();
|
|
z0 = location.getZ();
|
|
return new Vector(x1 - x0, y1 - y0, z1 - z0);
|
|
}
|
|
|
|
@Override
|
|
public void progress() {
|
|
if (!bPlayer.canBendIgnoreCooldowns(this)) {
|
|
if (!forming) {
|
|
breakBlock();
|
|
}
|
|
remove();
|
|
return;
|
|
}
|
|
|
|
if (System.currentTimeMillis() - time >= interval) {
|
|
time = System.currentTimeMillis();
|
|
if (progressing && !player.isSneaking()) {
|
|
remove();
|
|
return;
|
|
}
|
|
|
|
if (!progressing) {
|
|
sourceBlock.getWorld().playEffect(location, Effect.SMOKE, 4, (int) range);
|
|
return;
|
|
}
|
|
|
|
if (forming) {
|
|
ArrayList<Block> blocks = new ArrayList<Block>();
|
|
Location loc = GeneralMethods.getTargetedLocation(player, (int) range, Material.WATER, Material.STATIONARY_WATER, Material.ICE);
|
|
location = loc.clone();
|
|
Vector dir = player.getEyeLocation().getDirection();
|
|
Vector vec;
|
|
Block block;
|
|
|
|
for (double i = 0; i <= radius; i += 0.5) {
|
|
for (double angle = 0; angle < 360; angle += 10) {
|
|
vec = GeneralMethods.getOrthogonalVector(dir.clone(), angle, i);
|
|
block = loc.clone().add(vec).getBlock();
|
|
|
|
if (GeneralMethods.isRegionProtectedFromBuild(player, "LavaSurge", block.getLocation())) {
|
|
continue;
|
|
}
|
|
if (WALL_BLOCKS.containsKey(block)) {
|
|
blocks.add(block);
|
|
} else if (!blocks.contains(block) && (block.getType() == Material.AIR || block.getType() == Material.FIRE || isLavabendable(block))) {
|
|
WALL_BLOCKS.put(block, player);
|
|
addWallBlock(block);
|
|
blocks.add(block);
|
|
FireBlast.removeFireBlastsAroundPoint(block.getLocation(), 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (Block blocki : WALL_BLOCKS.keySet()) {
|
|
if (WALL_BLOCKS.get(blocki) == player && !blocks.contains(blocki)) {
|
|
finalRemoveLava(blocki);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (sourceBlock.getLocation().distanceSquared(firstDestination) < 0.5 * 0.5 && settingUp) {
|
|
settingUp = false;
|
|
}
|
|
|
|
Vector direction;
|
|
if (settingUp) {
|
|
direction = firstDirection;
|
|
} else {
|
|
direction = targetDirection;
|
|
}
|
|
|
|
location = location.clone().add(direction);
|
|
Block block = location.getBlock();
|
|
if (block.getLocation().equals(sourceBlock.getLocation())) {
|
|
location = location.clone().add(direction);
|
|
block = location.getBlock();
|
|
}
|
|
|
|
if (block.getType() != Material.AIR) {
|
|
breakBlock();
|
|
return;
|
|
} else if (!progressing) {
|
|
breakBlock();
|
|
return;
|
|
}
|
|
|
|
addLava(block);
|
|
removeLava(sourceBlock);
|
|
sourceBlock = block;
|
|
if (location.distanceSquared(targetDestination) < 1) {
|
|
removeLava(sourceBlock);
|
|
forming = true;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
private void addWallBlock(Block block) {
|
|
new TempBlock(block, Material.STATIONARY_LAVA, (byte) 8);
|
|
}
|
|
|
|
private void breakBlock() {
|
|
finalRemoveLava(sourceBlock);
|
|
for (Block block : WALL_BLOCKS.keySet()) {
|
|
if (WALL_BLOCKS.get(block) == player) {
|
|
finalRemoveLava(block);
|
|
}
|
|
}
|
|
remove();
|
|
}
|
|
|
|
private void removeLava(Block block) {
|
|
if (block != null) {
|
|
if (AFFECTED_BLOCKS.containsKey(block)) {
|
|
if (!GeneralMethods.isAdjacentToThreeOrMoreSources(block)) {
|
|
TempBlock.revertBlock(block, Material.AIR);
|
|
}
|
|
AFFECTED_BLOCKS.remove(block);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void finalRemoveLava(Block block) {
|
|
if (AFFECTED_BLOCKS.containsKey(block)) {
|
|
TempBlock.revertBlock(block, Material.AIR);
|
|
AFFECTED_BLOCKS.remove(block);
|
|
}
|
|
if (WALL_BLOCKS.containsKey(block)) {
|
|
TempBlock.revertBlock(block, Material.AIR);
|
|
WALL_BLOCKS.remove(block);
|
|
}
|
|
}
|
|
|
|
private void addLava(Block block) {
|
|
if (GeneralMethods.isRegionProtectedFromBuild(player, "LavaSurge", block.getLocation()))
|
|
return;
|
|
if (!TempBlock.isTempBlock(block)) {
|
|
new TempBlock(block, Material.STATIONARY_LAVA, (byte) 8);
|
|
AFFECTED_BLOCKS.put(block, block);
|
|
}
|
|
}
|
|
|
|
public static void moveLava(Player player) {
|
|
LavaSurgeWall wall = getAbility(player, LavaSurgeWall.class);
|
|
if (wall != null) {
|
|
wall.moveLava();
|
|
}
|
|
}
|
|
|
|
public static void form(Player player) {
|
|
if (!hasAbility(player, LavaSurgeWall.class)) {
|
|
new LavaSurgeWave(player);
|
|
return;
|
|
} else if (isLavabendable(player, player.getTargetBlock((HashSet<Material>) null, SURGE_WAVE_RANGE))) {
|
|
new LavaSurgeWave(player);
|
|
return;
|
|
}
|
|
moveLava(player);
|
|
}
|
|
|
|
public static void cleanup() {
|
|
for (Block block : AFFECTED_BLOCKS.keySet()) {
|
|
TempBlock.revertBlock(block, Material.AIR);
|
|
AFFECTED_BLOCKS.remove(block);
|
|
WALL_BLOCKS.remove(block);
|
|
}
|
|
for (Block block : WALL_BLOCKS.keySet()) {
|
|
TempBlock.revertBlock(block, Material.AIR);
|
|
AFFECTED_BLOCKS.remove(block);
|
|
WALL_BLOCKS.remove(block);
|
|
}
|
|
}
|
|
|
|
public static boolean wasBrokenFor(Player player, Block block) {
|
|
LavaSurgeWall wall = getAbility(player, LavaSurgeWall.class);
|
|
if (wall != null) {
|
|
if (wall.sourceBlock == null) {
|
|
return false;
|
|
} else if (wall.sourceBlock.equals(block)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static Map<Block, Block> getAffectedBlocks() {
|
|
return AFFECTED_BLOCKS;
|
|
}
|
|
|
|
public static Map<Block, Player> getWallBlocks() {
|
|
return WALL_BLOCKS;
|
|
}
|
|
|
|
@Override
|
|
public String getName() {
|
|
return "LavaSurgeWall";
|
|
}
|
|
|
|
@Override
|
|
public Location getLocation() {
|
|
return location;
|
|
}
|
|
|
|
@Override
|
|
public long getCooldown() {
|
|
return cooldown;
|
|
}
|
|
|
|
@Override
|
|
public boolean isSneakAbility() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isHarmlessAbility() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean isHiddenAbility() {
|
|
return true;
|
|
}
|
|
|
|
public boolean isProgressing() {
|
|
return progressing;
|
|
}
|
|
|
|
public void setProgressing(boolean progressing) {
|
|
this.progressing = progressing;
|
|
}
|
|
|
|
public boolean isSettingUp() {
|
|
return settingUp;
|
|
}
|
|
|
|
public void setSettingUp(boolean settingUp) {
|
|
this.settingUp = settingUp;
|
|
}
|
|
|
|
public boolean isForming() {
|
|
return forming;
|
|
}
|
|
|
|
public void setForming(boolean forming) {
|
|
this.forming = forming;
|
|
}
|
|
|
|
public long getTime() {
|
|
return time;
|
|
}
|
|
|
|
public void setTime(long time) {
|
|
this.time = time;
|
|
}
|
|
|
|
public long getInterval() {
|
|
return interval;
|
|
}
|
|
|
|
public void setInterval(long interval) {
|
|
this.interval = interval;
|
|
}
|
|
|
|
public double getRadius() {
|
|
return radius;
|
|
}
|
|
|
|
public void setRadius(double radius) {
|
|
this.radius = radius;
|
|
}
|
|
|
|
public double getRange() {
|
|
return range;
|
|
}
|
|
|
|
public void setRange(double range) {
|
|
this.range = range;
|
|
}
|
|
|
|
public Block getSourceBlock() {
|
|
return sourceBlock;
|
|
}
|
|
|
|
public void setSourceBlock(Block sourceBlock) {
|
|
this.sourceBlock = sourceBlock;
|
|
}
|
|
|
|
public Location getFirstDestination() {
|
|
return firstDestination;
|
|
}
|
|
|
|
public void setFirstDestination(Location firstDestination) {
|
|
this.firstDestination = firstDestination;
|
|
}
|
|
|
|
public Location getTargetDestination() {
|
|
return targetDestination;
|
|
}
|
|
|
|
public void setTargetDestination(Location targetDestination) {
|
|
this.targetDestination = targetDestination;
|
|
}
|
|
|
|
public Vector getFirstDirection() {
|
|
return firstDirection;
|
|
}
|
|
|
|
public void setFirstDirection(Vector firstDirection) {
|
|
this.firstDirection = firstDirection;
|
|
}
|
|
|
|
public Vector getTargetDirection() {
|
|
return targetDirection;
|
|
}
|
|
|
|
public void setTargetDirection(Vector targetDirection) {
|
|
this.targetDirection = targetDirection;
|
|
}
|
|
|
|
public void setCooldown(long cooldown) {
|
|
this.cooldown = cooldown;
|
|
}
|
|
|
|
public void setLocation(Location location) {
|
|
this.location = location;
|
|
}
|
|
|
|
}
|