Added EarthSmash

This commit is contained in:
Nathan Braun 2014-12-27 00:29:23 -08:00
parent c465624b32
commit 1a175cb346
9 changed files with 716 additions and 9 deletions

View file

@ -113,6 +113,7 @@ public class AbilityModuleManager {
if (a == StockAbilities.Extraction) metalbendingabilities.add(a.name());
if (a == StockAbilities.MetalClips) metalbendingabilities.add(a.name());
if (a == StockAbilities.MetalClips) shiftabilities.add(a.name());
if (a == StockAbilities.EarthSmash) shiftabilities.add(a.name());
// Earth Sub Abilities
if (a == StockAbilities.MetalClips) earthsubabilities.add(a.name());

View file

@ -18,7 +18,7 @@ public enum StockAbilities {
AvatarState,
// Project Korra
Extraction, MetalClips, Smokescreen, Combustion, LavaFlow, Suffocate, IceBlast, WarriorStance, AcrobatStance;
Extraction, MetalClips, Smokescreen, Combustion, LavaFlow, Suffocate, IceBlast, WarriorStance, AcrobatStance, EarthSmash;
private enum AirbendingAbilities {
AirBlast, AirBubble, AirShield, AirSuction, AirSwipe, Tornado, AirScooter, AirSpout, AirBurst, Suffocate;
@ -30,7 +30,7 @@ public enum StockAbilities {
}
private enum EarthbendingAbilities {
Catapult, RaiseEarth, EarthGrab, EarthTunnel, EarthBlast, Collapse, Tremorsense, EarthArmor, Shockwave, Extraction, MetalClips, LavaFlow;
Catapult, RaiseEarth, EarthGrab, EarthTunnel, EarthBlast, Collapse, Tremorsense, EarthArmor, Shockwave, Extraction, MetalClips, LavaFlow, EarthSmash;
}
private enum FirebendingAbilities {

View file

@ -442,7 +442,7 @@ public class ConfigManager {
config.addDefault("Abilities.Earth.LavaFlow.Enabled", true);
config.addDefault("Abilities.Earth.LavaFlow.Description", "This ability allows an Earthbender to create lava using the Earth around them. To use, simply hold sneak (Default: Shift) to create a lava moat that surrounds you, press sneak again to remove the moat. Left click an Earthbendable block to create a pool of lava after a small delay. Additionally, you can left click at any time to turn lava back into its original state -- Earth.");
config.addDefault("Abilities.Earth.LavFlow.ShiftCooldown", 16000);
config.addDefault("Abilities.Earth.LavaFlow.ShiftCooldown", 16000);
config.addDefault("Abilities.Earth.LavaFlow.ClickLavaCooldown", 10000);
config.addDefault("Abilities.Earth.LavaFlow.ClickLandCooldown", 500);
config.addDefault("Abilities.Earth.LavaFlow.ShiftCleanupDelay", 10000);
@ -463,6 +463,26 @@ public class ConfigManager {
config.addDefault("Abilities.Earth.LavaFlow.AllowNaturalFlow", false);
config.addDefault("Abilities.Earth.LavaFlow.ParticleDensity", 0.33);
config.addDefault("Abilities.Earth.EarthSmash.Enabled", true);
config.addDefault("Abilities.Earth.EarthSmash.Description", "To raise an EarthSmash hold sneak (default: shift) for approximately 1.5 seconds, " +
"then release while aiming at dirt. To grab the EarthSmash aim at the center and hold sneak, " +
"the EarthSmash will follow your mouse. You can shoot the EarthSmash by grabbing onto it and left clicking. " +
"To ride the EarthSmash simply hop ontop of it and hold sneak while aiming in the direction that you wish to go. " +
"Another way to ride an EarthSmash is to grab it with sneak and then right click it. " +
"Use EarthSmash as a defensive shield, a powerful attack, or an advanced means of transportation.");
config.addDefault("Abilities.Earth.EarthSmash.AllowGrab", true);
config.addDefault("Abilities.Earth.EarthSmash.AllowShooting", true);
config.addDefault("Abilities.Earth.EarthSmash.AllowFlight", true);
config.addDefault("Abilities.Earth.EarthSmash.GrabRange", 10);
config.addDefault("Abilities.Earth.EarthSmash.ChargeTime", 1200);
config.addDefault("Abilities.Earth.EarthSmash.Cooldown", 0);
config.addDefault("Abilities.Earth.EarthSmash.ShotRange", 30);
config.addDefault("Abilities.Earth.EarthSmash.Damage", 6);
config.addDefault("Abilities.Earth.EarthSmash.Knockback", 3.5);
config.addDefault("Abilities.Earth.EarthSmash.Knockup", 0.15);
config.addDefault("Abilities.Earth.EarthSmash.FlightSpeed", 0.72);
config.addDefault("Abilities.Earth.EarthSmash.FlightTime", 3000);
// config.addDefault("Abilities.Earth.LavaSurge.Enabled", true);
// config.addDefault("Abilities.Earth.LavaSurge.Description", "LavaSurge is a fundamental move for any Lavabender out there. To use, simply sneak (Default: Shift) while looking at a source of Earth or Lava, then click in a direction. A surge of lava will swiftly travel towards the target you were pointing at, dealing moderate damage, a large knockback, and setting them on fire.");
// config.addDefault("Abilities.Earth.LavaSurge.Damage", 4);

View file

@ -104,6 +104,7 @@ import com.projectkorra.ProjectKorra.earthbending.EarthArmor;
import com.projectkorra.ProjectKorra.earthbending.EarthBlast;
import com.projectkorra.ProjectKorra.earthbending.EarthColumn;
import com.projectkorra.ProjectKorra.earthbending.EarthPassive;
import com.projectkorra.ProjectKorra.earthbending.EarthSmash;
import com.projectkorra.ProjectKorra.earthbending.EarthTunnel;
import com.projectkorra.ProjectKorra.earthbending.LavaFlow;
import com.projectkorra.ProjectKorra.earthbending.MetalClips;
@ -154,6 +155,7 @@ public class Methods {
public static ConcurrentHashMap<Integer, Information> tempair = new ConcurrentHashMap<Integer, Information>();
public static ConcurrentHashMap<String, Long> cooldowns = new ConcurrentHashMap<String, Long>();
public static ArrayList<Block> tempnophysics = new ArrayList<Block>();
public static HashSet<Block> tempNoEarthbending = new HashSet<Block>();
private static Integer[] plantIds = { 6, 18, 31, 32, 37, 38, 39, 40, 59, 81, 83, 86, 99, 100, 103, 104, 105, 106, 111, 161, 175};
public static Integer[] transparentToEarthbending = {0, 6, 8, 9, 10, 11, 30, 31, 32, 37, 38, 39, 40, 50, 51, 59, 78, 83, 106};
@ -1190,6 +1192,9 @@ public class Methods {
if(!valid)
return false;
if(tempNoEarthbending.contains(block))
return false;
if (!isRegionProtectedFromBuild(player, ability,
block.getLocation()))
@ -2022,6 +2027,7 @@ public class Methods {
Shockwave.removeAll();
Tremorsense.removeAll();
LavaFlow.removeAll();
EarthSmash.removeAll();
FreezeMelt.removeAll();
IceSpike.removeAll();

View file

@ -4,13 +4,10 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@ -57,7 +54,6 @@ import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerToggleFlightEvent;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
@ -92,17 +88,17 @@ import com.projectkorra.ProjectKorra.earthbending.EarthBlast;
import com.projectkorra.ProjectKorra.earthbending.EarthColumn;
import com.projectkorra.ProjectKorra.earthbending.EarthGrab;
import com.projectkorra.ProjectKorra.earthbending.EarthPassive;
import com.projectkorra.ProjectKorra.earthbending.EarthSmash;
import com.projectkorra.ProjectKorra.earthbending.EarthTunnel;
import com.projectkorra.ProjectKorra.earthbending.EarthWall;
import com.projectkorra.ProjectKorra.earthbending.Extraction;
import com.projectkorra.ProjectKorra.earthbending.LavaFlow;
import com.projectkorra.ProjectKorra.earthbending.LavaFlow.AbilityType;
import com.projectkorra.ProjectKorra.earthbending.LavaSurge;
import com.projectkorra.ProjectKorra.earthbending.LavaWall;
import com.projectkorra.ProjectKorra.earthbending.LavaWave;
import com.projectkorra.ProjectKorra.earthbending.MetalClips;
import com.projectkorra.ProjectKorra.earthbending.Shockwave;
import com.projectkorra.ProjectKorra.earthbending.Tremorsense;
import com.projectkorra.ProjectKorra.earthbending.LavaFlow.AbilityType;
import com.projectkorra.ProjectKorra.firebending.ArcOfFire;
import com.projectkorra.ProjectKorra.firebending.Combustion;
import com.projectkorra.ProjectKorra.firebending.Cook;
@ -254,6 +250,9 @@ public class PKListener implements Listener {
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
Methods.cooldowns.put(player.getName(), System.currentTimeMillis());
ComboManager.addComboAbility(player, ClickType.RIGHTCLICK);
String ability = Methods.getBoundAbility(player);
if(ability != null && ability.equalsIgnoreCase("EarthSmash"))
new EarthSmash(player, EarthSmash.ClickType.RIGHTCLICK);
}
if (Paralyze.isParalyzed(player) || Bloodbending.isBloodbended(player) || Suffocate.isBreathbent(player)) {
event.setCancelled(true);
@ -505,6 +504,9 @@ public class PKListener implements Listener {
if (abil.equalsIgnoreCase("LavaFlow")) {
new LavaFlow(player,LavaFlow.AbilityType.SHIFT);
}
if (abil.equalsIgnoreCase("EarthSmash")) {
new EarthSmash(player, EarthSmash.ClickType.SHIFT);
}
}
@ -861,6 +863,10 @@ public class PKListener implements Listener {
if (abil.equalsIgnoreCase("LavaFlow")) {
new LavaFlow(player,AbilityType.CLICK);
}
if (abil.equalsIgnoreCase("EarthSmash")) {
new EarthSmash(player, EarthSmash.ClickType.LEFTCLICK);
}
}
if (Methods.isFireAbility(abil)) {
if (Methods.isWeapon(player.getItemInHand().getType()) && !plugin.getConfig().getBoolean("Properties.Fire.CanBendWithWeapons")) {

View file

@ -0,0 +1,650 @@
package com.projectkorra.ProjectKorra.earthbending;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import com.projectkorra.ProjectKorra.BendingPlayer;
import com.projectkorra.ProjectKorra.Methods;
import com.projectkorra.ProjectKorra.ProjectKorra;
import com.projectkorra.ProjectKorra.TempBlock;
import com.projectkorra.ProjectKorra.Ability.AvatarState;
public class EarthSmash {
public static enum ClickType {
LEFTCLICK, RIGHTCLICK, SHIFT;
}
public static enum State {
START, LIFTING, LIFTED, GRABBED, SHOT, FLYING, REMOVED
}
public static ArrayList<EarthSmash> instances = new ArrayList<EarthSmash>();
public static boolean ALLOW_GRAB = ProjectKorra.plugin.getConfig().getBoolean("Abilities.Earth.EarthSmash.AllowGrab");
public static boolean ALLOW_SHOOTING = ProjectKorra.plugin.getConfig().getBoolean("Abilities.Earth.EarthSmash.AllowShooting");
public static boolean ALLOW_FLIGHT = ProjectKorra.plugin.getConfig().getBoolean("Abilities.Earth.EarthSmash.AllowFlight");
public static double GRAB_RANGE = ProjectKorra.plugin.getConfig().getDouble("Abilities.Earth.EarthSmash.GrabRange");
public static double TRAVEL_RANGE = ProjectKorra.plugin.getConfig().getDouble("Abilities.Earth.EarthSmash.ShotRange");
public static double SHOOTING_DAMAGE = ProjectKorra.plugin.getConfig().getDouble("Abilities.Earth.EarthSmash.Damage");
public static double KNOCKBACK_POWER = ProjectKorra.plugin.getConfig().getDouble("Abilities.Earth.EarthSmash.Knockback");
public static double KNOCKUP_POWER = ProjectKorra.plugin.getConfig().getDouble("Abilities.Earth.EarthSmash.Knockup");
public static double FLYING_PLAYER_SPEED = ProjectKorra.plugin.getConfig().getDouble("Abilities.Earth.EarthSmash.FlightSpeed");
public static long CHARGE_TIME = ProjectKorra.plugin.getConfig().getLong("Abilities.Earth.EarthSmash.ChargeTime");
public static long MAIN_COOLDOWN = ProjectKorra.plugin.getConfig().getLong("Abilities.Earth.EarthSmash.Cooldown");
public static long FLYING_REMOVE_TIMER = ProjectKorra.plugin.getConfig().getLong("Abilities.Earth.EarthSmash.FlightTime");
private static int REQUIRED_BENDABLE_BLOCKS = 11;
private static int MAX_BLOCKS_TO_PASS_THROUGH = 3;
private static double GRAB_DETECTION_RADIUS = 2.5;
private static double FLIGHT_DETECTION_RADIUS = 3.8;
private static long SHOOTING_ANIMATION_COOLDOWN = 25;
private static long FLYING_ANIMATION_COOLDOWN = 0;
private static long LIFT_ANIMATION_COOLDOWN = 30;
private Player player;
private BendingPlayer bplayer;
private Block origin;
private Location loc, destination;
private State state = State.START;
private int animCounter, progressCounter;
private long time, delay, cooldown, flightRemove, flightStart;
private double grabbedRange;
private double grabRange, chargeTime, damage, knockback, knockup, flySpeed, shootRange;
private ArrayList<Entity> affectedEntities = new ArrayList<Entity>();
private ArrayList<BlockRepresenter> currentBlocks = new ArrayList<BlockRepresenter>();
private ArrayList<TempBlock> affectedBlocks = new ArrayList<TempBlock>();
public EarthSmash(Player player, ClickType type) {
if(!Methods.hasPermission(player, "EarthSmash"))
return;
this.player = player;
bplayer = Methods.getBendingPlayer(player.getName());
this.time = System.currentTimeMillis();
if(type == ClickType.SHIFT && !player.isSneaking()) {
grabRange = GRAB_RANGE;
chargeTime = CHARGE_TIME;
cooldown = MAIN_COOLDOWN;
damage = SHOOTING_DAMAGE;
knockback = KNOCKBACK_POWER;
knockup = KNOCKUP_POWER;
flySpeed = FLYING_PLAYER_SPEED;
flightRemove = FLYING_REMOVE_TIMER;
shootRange = TRAVEL_RANGE;
if(AvatarState.isAvatarState(player)) {
grabRange = AvatarState.getValue(grabRange);
chargeTime = AvatarState.getValue(chargeTime);
cooldown = 0;
damage = AvatarState.getValue(damage);
knockback = AvatarState.getValue(knockback);
knockup = AvatarState.getValue(knockup);
flySpeed = AvatarState.getValue(flySpeed);
flightRemove = Integer.MAX_VALUE;
shootRange = AvatarState.getValue(shootRange);
}
EarthSmash flySmash = flyingInSmashCheck(player);
if(flySmash != null) {
flySmash.state = State.FLYING;
flySmash.player = player;
flySmash.flightStart = System.currentTimeMillis();
return;
}
EarthSmash grabbedSmash = aimingAtSmashCheck(player, State.LIFTED);
if(grabbedSmash == null)
grabbedSmash = aimingAtSmashCheck(player, State.SHOT);
if(grabbedSmash != null) {
grabbedSmash.state = State.GRABBED;
grabbedSmash.grabbedRange = grabbedSmash.loc.distance(player.getEyeLocation());
grabbedSmash.player = player;
return;
}
}
else if(type == ClickType.LEFTCLICK && player.isSneaking()) {
for(EarthSmash smash : instances) {
if(smash.state == State.GRABBED && smash.player == player) {
smash.state = State.SHOT;
smash.destination = player.getEyeLocation().clone().add
(player.getEyeLocation().getDirection().normalize().multiply(TRAVEL_RANGE));
smash.loc.getWorld().playEffect(smash.loc, Effect.GHAST_SHOOT, 0, 10);
}
}
return;
}
else if(type == ClickType.RIGHTCLICK && player.isSneaking()) {
EarthSmash grabbedSmash = aimingAtSmashCheck(player, State.GRABBED);
if(grabbedSmash != null) {
player.teleport(grabbedSmash.loc.clone().add(0, 2, 0));
grabbedSmash.state = State.FLYING;
grabbedSmash.player = player;
grabbedSmash.flightStart = System.currentTimeMillis();
}
return;
}
else {
return;
}
instances.add(this);
}
public void progress() {
progressCounter++;
if(state == State.START || state == State.FLYING || state == State.GRABBED) {
if(player.isDead() || !player.isOnline()) {
remove();
return;
}
}
else if(state == State.START) {
String ability = Methods.getBoundAbility(player);
if(ability == null || !ability.equalsIgnoreCase("EarthSmash") || bplayer.isOnCooldown("earthsmashmain")) {
remove();
return;
}
}
else if(state == State.START || state == State.FLYING || state == State.GRABBED) {
if(!Methods.canBend(player.getName(), "EarthSmash")) {
remove();
return;
}
}
if(state == State.START && progressCounter > 1) {
if(!player.isSneaking()) {
if(System.currentTimeMillis() - time > chargeTime) {
origin = Methods.getEarthSourceBlock(player, grabRange);
if(origin == null){
remove();
return;
}
bplayer.addCooldown("earthsmashmain", cooldown);
loc = origin.getLocation();
state = State.LIFTING;
}
else {
remove();
return;
}
}
else if(System.currentTimeMillis() - time > chargeTime) {
player.getWorld().playEffect(player.getEyeLocation(), Effect.SMOKE,
Methods.getIntCardinalDirection(player.getEyeLocation().getDirection()), 3);
}
}
else if(state == State.LIFTING) {
if(System.currentTimeMillis() - delay >= LIFT_ANIMATION_COOLDOWN) {
delay = System.currentTimeMillis();
animateLift();
}
}
else if(state == State.GRABBED) {
if(player.isSneaking()) {
revert();
Location oldLoc = loc.clone();
loc = player.getEyeLocation().add(
player.getEyeLocation().getDirection().normalize().multiply(grabbedRange));
//Check to make sure the new location is available to move to
for(Block block : getBlocks())
if(block.getType() != Material.AIR && !Methods.isTransparentToEarthbending(player, block)) {
loc = oldLoc;
break;
}
Methods.removeSpouts(loc, 2, player);
draw();
return;
}
else {
state = State.LIFTED;
return;
}
}
else if(state == State.SHOT) {
if(System.currentTimeMillis() - delay >= SHOOTING_ANIMATION_COOLDOWN) {
delay = System.currentTimeMillis();
if(Methods.isRegionProtectedFromBuild(player, "EarthSmash", loc)) {
remove();
return;
}
revert();
loc.add(Methods.getDirection(loc, destination).normalize().multiply(1));
if(loc.distanceSquared(destination) < 4) {
remove();
return;
}
// If an earthsmash runs into too many blocks we should remove it
int badBlocksFound = 0;
for(Block block : getBlocks())
if(block.getType() != Material.AIR &&
(!Methods.isTransparentToEarthbending(player, block) || block.getType() == Material.WATER || block.getType() == Material.STATIONARY_WATER))
badBlocksFound++;
if(badBlocksFound > MAX_BLOCKS_TO_PASS_THROUGH) {
remove();
return;
}
Methods.removeSpouts(loc, 2, player);
shootingCollisionDetection();
draw();
smashToSmashCollisionDetection();
}
return;
}
else if(state == State.FLYING) {
if(!player.isSneaking()){
remove();
return;
}
else if(System.currentTimeMillis() - delay >= FLYING_ANIMATION_COOLDOWN)
{
delay = System.currentTimeMillis();
if(Methods.isRegionProtectedFromBuild(player, "EarthSmash", loc)) {
remove();
return;
}
revert();
destination = player.getEyeLocation().clone().add
(player.getEyeLocation().getDirection().normalize().multiply(TRAVEL_RANGE));
Vector direction = Methods.getDirection(loc, destination).normalize();
List<Entity> entities = Methods.getEntitiesAroundPoint(loc.clone().add(0,2,0), FLIGHT_DETECTION_RADIUS);
if(entities.size() == 0){
remove();
return;
}
for(Entity entity : entities)
entity.setVelocity(direction.clone().multiply(flySpeed));
//These values tend to work well when dealing with a person aiming upward or downward.
if(direction.getY() < -0.35)
loc = player.getLocation().clone().add(0,-3.2,0);
else if(direction.getY() > 0.35)
loc = player.getLocation().clone().add(0,-1.7,0);
else
loc = player.getLocation().clone().add(0,-2.2,0);
draw();
}
if(System.currentTimeMillis() - flightStart > flightRemove){
remove();
return;
}
}
}
public void animateLift()
{
/**
* Begins animating the EarthSmash from the ground. The lift animation consists
* of 3 steps, and each one has to design the shape in the ground that removes the
* earthbendable material. We also need to make sure that there is a clear path for
* the EarthSmash to rise, and that there is enough earthbendable material for it to be created.
*/
if(animCounter < 4) {
revert();
loc.add(0,1,0);
//Remove the blocks underneath the rising smash
if(animCounter == 0) {
//Check all of the blocks and make sure that they can be removed AND make sure there is enough dirt
int totalBendableBlocks = 0;
for(int x = -1; x <= 1; x++)
for(int y = -2; y <= -1; y++)
for(int z = -1; z <= 1; z++) {
Block block = loc.clone().add(x,y,z).getBlock();
if(Methods.isRegionProtectedFromBuild(player, "EarthSmash", block.getLocation())) {
remove();
return;
}
if(isEarthbendableMaterial(block.getType()))
totalBendableBlocks++;
}
if(totalBendableBlocks < REQUIRED_BENDABLE_BLOCKS) {
remove();
return;
}
//Make sure there is a clear path upward otherwise remove
for(int y = 0; y <= 3; y++) {
Block tempBlock = loc.clone().add(0,y,0).getBlock();
if(!Methods.isTransparentToEarthbending(player, tempBlock) && tempBlock.getType() != Material.AIR) {
remove();
return;
}
}
//Design what this EarthSmash looks like by using BlockRepresenters
Location tempLoc = loc.clone().add(0,-2,0);
for(int x = -1; x <= 1; x++)
for(int y = -1; y <= 1; y++)
for(int z = -1; z <= 1; z++)
if((Math.abs(x) + Math.abs(y) + Math.abs(z)) % 2 == 0) {
Block block = tempLoc.clone().add(x,y,z).getBlock();
currentBlocks.add(new BlockRepresenter(x, y, z, selectMaterialForRepresenter(block.getType()), block.getData()));
}
//Remove the design of the second level of removed dirt
for(int x = -1; x <= 1; x++)
for(int z = -1; z <= 1; z++) {
if((Math.abs(x) + Math.abs(z)) % 2 == 1) {
Block block = loc.clone().add(x,-2,z).getBlock();
if(isEarthbendableMaterial(block.getType()))
Methods.addTempAirBlock(block);
}
//Remove the first level of dirt
Block block = loc.clone().add(x,-1,z).getBlock();
if(isEarthbendableMaterial(block.getType()))
Methods.addTempAirBlock(block);
}
/*
* We needed to calculate all of the blocks based on the location being 1 above the initial
* bending block, however we want to animate it starting from the original bending block.
* We must readjust the location back to what it originally was.
*/
loc.add(0,-1,0);
}
//Move any entities that are above the rock
List<Entity> entities = Methods.getEntitiesAroundPoint(loc, 2.5);
for(Entity entity : entities) {
org.bukkit.util.Vector velocity = entity.getVelocity();
entity.setVelocity(velocity.add(new Vector(0,0.36,0)));
}
loc.getWorld().playEffect(loc, Effect.GHAST_SHOOT, 0, 7);
draw();
}
else {
state = State.LIFTED;
}
animCounter++;
}
public void draw() {
/**
* Redraws the blocks for this instance of EarthSmash.
*/
for(BlockRepresenter blockRep : currentBlocks) {
Block block = loc.clone().add(blockRep.getX(),blockRep.getY(),blockRep.getZ()).getBlock();
if(player != null && Methods.isTransparentToEarthbending(player,block)) {
affectedBlocks.add(new TempBlock(block, blockRep.getType(), blockRep.getData()));
Methods.tempNoEarthbending.add(block);
}
}
}
public void revert() {
checkRemainingBlocks();
for(int i = 0; i < affectedBlocks.size(); i++) {
TempBlock tblock = affectedBlocks.get(i);
Methods.tempNoEarthbending.remove(tblock.getBlock());
tblock.revertBlock();
affectedBlocks.remove(i);
i--;
}
}
public void checkRemainingBlocks() {
/**
* Checks to see which of the blocks are still attached to the
* EarthSmash, remember that blocks can be broken or used in other abilities
* so we need to double check and remove any that are not still attached.
*
* Also when we remove the blocks from instances, movedearth, or tempair
* we should do it on a delay because tempair takes a couple seconds before
* the block shows up in that map.
*/
for(int i = 0; i < currentBlocks.size(); i++) {
BlockRepresenter brep = currentBlocks.get(i);
final Block block = loc.clone().add(brep.getX(), brep.getY(), brep.getZ()).getBlock();
// Check for grass because sometimes the dirt turns into grass.
if(block.getType() != brep.getType()
&& (block.getType() != Material.GRASS)
&& (block.getType() != Material.COBBLESTONE)) {
currentBlocks.remove(i);
i--;
}
}
}
public void remove() {
state = State.REMOVED;
revert();
instances.remove(this);
}
public List<Block> getBlocks() {
/**
* Gets the blocks surrounding the EarthSmash's loc.
* This method ignores the blocks that should be Air, and only returns the ones that are dirt.
*/
List<Block> blocks = new ArrayList<Block>();
for(int x = -1; x <= 1; x++)
for(int y = -1; y <= 1; y++)
for(int z = -1; z <= 1; z++)
if((Math.abs(x) + Math.abs(y) + Math.abs(z)) % 2 == 0) //Give it the cool shape
blocks.add(loc.getWorld().getBlockAt(loc.clone().add(x,y,z)));
return blocks;
}
public List<Block> getBlocksIncludingInner() {
/**
* Gets the blocks surrounding the EarthSmash's loc.
* This method returns all the blocks surrounding the loc, including dirt and air.
*/
List<Block> blocks = new ArrayList<Block>();
for(int x = -1; x <= 1; x++)
for(int y = -1; y <= 1; y++)
for(int z = -1; z <= 1; z++)
blocks.add(loc.getWorld().getBlockAt(loc.clone().add(x,y,z)));
return blocks;
}
public static Material selectMaterial(Material mat) {
/**
* Switches the Sand Material and Gravel to SandStone and stone respectively,
* since gravel and sand cannot be bent due to gravity.
*/
if(mat == Material.SAND) return Material.SANDSTONE;
else if(mat == Material.GRAVEL) return Material.STONE;
else return mat;
}
public Material selectMaterialForRepresenter(Material mat) {
Material tempMat = selectMaterial(mat);
Random rand = new Random();
if(!isEarthbendableMaterial(tempMat)) {
if(currentBlocks.size() < 1)
return Material.DIRT;
else
return currentBlocks.get(rand.nextInt(currentBlocks.size())).getType();
}
return tempMat;
}
private EarthSmash aimingAtSmashCheck(Player player, State reqState) {
/**
* Determines if a player is trying to grab an EarthSmash.
* A player is trying to grab an EarthSmash if they are staring at it and holding shift.
*/
if(!ALLOW_GRAB)
return null;
@SuppressWarnings("deprecation")
List<Block> blocks = player.getLineOfSight(Methods.getTransparentEarthbending(), (int) Math.round(grabRange));
for(EarthSmash smash : instances) {
if(reqState == null || smash.state == reqState)
for(Block block : blocks)
if(block.getLocation().distanceSquared(smash.loc) <= Math.pow(GRAB_DETECTION_RADIUS, 2))
return smash;
}
return null;
}
public void shootingCollisionDetection() {
/**
* This method handles any collision between an EarthSmash and the surrounding entities,
* the method only applies to earthsmashes that have already been shot.
*/
List<Entity> entities = Methods.getEntitiesAroundPoint(loc, FLIGHT_DETECTION_RADIUS);
for(Entity entity : entities)
if(entity instanceof LivingEntity
&& entity != player
&& !affectedEntities.contains(entity)) {
affectedEntities.add(entity);
double damage = currentBlocks.size() / 13 * this.damage;
Methods.damageEntity(player, entity, damage);
Vector travelVec = Methods.getDirection(loc, entity.getLocation());
entity.setVelocity(travelVec.setY(knockup).normalize().multiply(knockback));
}
}
public void smashToSmashCollisionDetection() {
/**
* EarthSmash to EarthSmash collision can only happen when one of the Smashes have
* been shot by a player. If we find out that one of them have collided then we want to return
* since a smash can only remove 1 at a time.
*/
for(int i = 0; i < instances.size(); i++) {
EarthSmash smash = instances.get(i);
if(smash.loc != null) {
if(smash != this && smash.loc.distanceSquared(loc) < Math.pow(FLIGHT_DETECTION_RADIUS, 2)) {
smash.remove();
remove();
i-=2;
return;
}
}
}
}
private static EarthSmash flyingInSmashCheck(Player player) {
/**
* Determines whether or not a player is trying to fly ontop of an EarthSmash.
* A player is considered "flying" if they are standing ontop of the earthsmash and holding shift.
*/
if(!ALLOW_FLIGHT)
return null;
for(EarthSmash smash : instances) {
//Check to see if the player is standing on top of the smash.
if(smash.state == State.LIFTED)
if(smash.loc.clone().add(0,2,0).distanceSquared(player.getLocation()) <= Math.pow(FLIGHT_DETECTION_RADIUS, 2))
return smash;
}
return null;
}
public static boolean isEarthbendableMaterial(Material mat) {
for (String s : ProjectKorra.plugin.getConfig().getStringList("Properties.Earth.EarthbendableBlocks")) {
if (mat == Material.getMaterial(s))
return true;
}
return false;
}
public static void progressAll() {
for(int i = 0; i < instances.size(); i++)
instances.get(i).progress();
}
public static void removeAll() {
for(int i = 0; i < instances.size(); i++) {
instances.get(i).remove();
i--;
}
}
public class BlockRepresenter {
/**
* A BlockRepresenter is used to keep track of each of
* the individual types of blocks that are attached to an EarthSmash.
* Without the representer then an EarthSmash can only be made up of 1 material
* at a time. For example, an ESmash that is entirely dirt, coalore, or sandstone.
* Using the representer will allow all the materials to be mixed together.
*/
private int x, y, z;
private Material type;
private byte data;
public BlockRepresenter(int x, int y, int z, Material type, byte data) {
this.x = x;
this.y = y;
this.z = z;
this.type = type;
this.data = data;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getZ() {
return z;
}
public Material getType() {
return type;
}
public byte getData() {
return data;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setZ(int z) {
this.z = z;
}
public void setType(Material type) {
this.type = type;
}
public void setData(byte data) {
this.data = data;
}
public String toString() {
return x + ", " + y + ", " + z + ", " + type.toString();
}
}
public class Pair<F, S> {
private F first; //first member of pair
private S second; //second member of pair
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
public void setFirst(F first) {
this.first = first;
}
public void setSecond(S second) {
this.second = second;
}
public F getFirst() {
return first;
}
public S getSecond() {
return second;
}
}
}

View file

@ -27,5 +27,6 @@ public class EarthbendingManager implements Runnable {
MetalClips.progressAll();
LavaSurge.progressAll();
LavaFlow.progressAll();
EarthSmash.progressAll();
}
}

View file

@ -375,6 +375,28 @@ Abilities:
DownwardFlow: 4
AllowNaturalFlow: false
ParticleDensity: 0.33
EarthSmash:
Enabled: true
Description: 'To raise an EarthSmash hold sneak (default: shift) for approximately
1.5 seconds, then release while aiming at dirt. To grab the EarthSmash aim
at the center and hold sneak, the EarthSmash will follow your mouse. You can
shoot the EarthSmash by grabbing onto it and left clicking. To ride the EarthSmash
simply hop ontop of it and hold sneak while aiming in the direction that you
wish to go. Another way to ride an EarthSmash is to grab it with sneak and
then right click it. Use EarthSmash as a defensive shield, a powerful attack,
or an advanced means of transportation.'
AllowGrab: true
AllowShooting: true
AllowFlight: true
GrabRange: 10
ChargeTime: 1200
Cooldown: 0
ShotRange: 30
Damage: 6
Knockback: 3.5
Knockup: 0.15
FlightSpeed: 0.72
FlightTime: 3000
RaiseEarth:
Enabled: true
Description: "To use, simply left-click on an earthbendable block. A column of earth will shoot upwards from that location. Anything in the way of the column will be brought up with it, leaving talented benders the ability to trap brainless entities up there. Additionally, simply sneak (default shift) looking at an earthbendable block. A wall of earth will shoot upwards from that location. Anything in the way of the wall will be brought up with it."

View file

@ -108,6 +108,7 @@ permissions:
bending.earth.grapplinghook: true
bending.ability.LavaSurge: true
bending.ability.LavaFlow: true
bending.ability.EarthSmash: true
bending.fire:
default: true
description: Grants access to all firebending abilities.