Fix Cannon TNT firing in the wrong direction and clean up the projectile code, making it more modular.

This commit is contained in:
Ben 2016-04-15 00:43:55 +01:00
parent 29b3f03abf
commit 0a32eed15d
7 changed files with 117 additions and 198 deletions

View File

@ -1480,4 +1480,28 @@ public class UtilBlock
IBlockData ibd = net.minecraft.server.v1_8_R3.Block.getById(type).fromLegacyData(data);
chunk.a(pos, ibd);
}
/**
* @return true if all of the blocks within the specified radius of the specified origin block are boundless ({@link UtilItem#isBoundless}.)
*/
public static boolean boundless(Location origin, double radius)
{
for (Block block : getInRadius(origin, radius).keySet())
{
if (!UtilItem.isBoundless(block.getType()))
{
return false;
}
}
return true;
}
/**
* @return true if there are any non-boundless ({@link UtilItem#isBoundless}) blocks within the specified radius of the specified origin block.
*/
public static boolean boundless(Block origin, double radius)
{
return boundless(origin.getLocation(), radius);
}
}

View File

@ -1,8 +1,6 @@
package mineplex.game.clans.clans.siege.weapon;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map.Entry;
import org.bukkit.Location;
import org.bukkit.Material;
@ -39,7 +37,6 @@ import mineplex.game.clans.clans.ClanInfo;
import mineplex.game.clans.clans.siege.SiegeManager;
import mineplex.game.clans.clans.siege.events.SiegeWeaponExplodeEvent;
import mineplex.game.clans.clans.siege.repository.tokens.SiegeWeaponToken;
import mineplex.game.clans.clans.siege.weapon.projectile.ProjectileAttributes;
import mineplex.game.clans.clans.siege.weapon.projectile.WeaponProjectile;
import mineplex.game.clans.clans.siege.weapon.util.AccessRule;
import mineplex.game.clans.clans.siege.weapon.util.AccessType;
@ -76,8 +73,6 @@ public class Cannon extends SiegeWeapon
_baseDamage = 650;
setProjectileAttributes(new ProjectileAttributes().setPrimedTnt().setDoCrater().craterSize(3).craterChanceOfAir(2.d));
setFireRule(new AccessRule(AccessType.LCLICK_BB, player -> {
if (!isRiding(player))
{
@ -160,8 +155,6 @@ public class Cannon extends SiegeWeapon
_baseDamage = 650;
setProjectileAttributes(new ProjectileAttributes().setPrimedTnt().setDoCrater().craterSize(3).craterChanceOfAir(2.d));
setFireRule(new AccessRule(AccessType.LCLICK_BB, player -> {
if (!isRiding(player))
{
@ -360,12 +353,14 @@ public class Cannon extends SiegeWeapon
}
@Override
public void CustomFire(WeaponProjectile projectile)
protected WeaponProjectile CustomFire(double yawRot, double verticalVel, double horizontalVel)
{
projectile.setLocation(projectile.getLocation().add(.0, .2, .0));
Location location = UtilAlg.moveForward(new Location(_location.getWorld(), _location.getX(), _location.getY() + .2, _location.getZ(), (float) yawRot, (float) 0), 0.35, (float) yawRot, false);
UtilParticle.PlayParticleToAll(ParticleType.LARGE_EXPLODE, projectile.getLocation(), new Vector(0, 0, 0), .1f, 2, ViewDist.MAX);
UtilServer.getServer().getOnlinePlayers().forEach(player -> player.playSound(projectile.getLocation(), Sound.EXPLODE, 1.f, 1.f));
UtilParticle.PlayParticleToAll(ParticleType.LARGE_EXPLODE, location, new Vector(0, 0, 0), .1f, 2, ViewDist.MAX);
UtilServer.getServer().getOnlinePlayers().forEach(player -> player.playSound(location, Sound.EXPLODE, 1.f, 1.f));
return new TntProjectile(this, location, yawRot, verticalVel, horizontalVel);
}
@Override

View File

@ -54,7 +54,6 @@ import mineplex.game.clans.clans.siege.events.LoadSiegeWeaponEvent;
import mineplex.game.clans.clans.siege.events.MountSiegeWeaponEvent;
import mineplex.game.clans.clans.siege.events.SiegeWeaponExplodeEvent;
import mineplex.game.clans.clans.siege.repository.tokens.SiegeWeaponToken;
import mineplex.game.clans.clans.siege.weapon.projectile.ProjectileAttributes;
import mineplex.game.clans.clans.siege.weapon.projectile.WeaponProjectile;
import mineplex.game.clans.clans.siege.weapon.util.AccessRule;
import mineplex.game.clans.clans.siege.weapon.util.AccessType;
@ -138,7 +137,6 @@ public abstract class SiegeWeapon implements Listener
protected int _baseDamage;
protected ProjectileAttributes _projectileAttributes;
protected WeaponProjectile _projectile;
public SiegeWeapon(int maxHealth, String name, SiegeWeaponToken token, ClansManager clansManager, SiegeManager siegeManager)
@ -328,7 +326,7 @@ public abstract class SiegeWeapon implements Listener
_inventory.clear();
CustomFire(_projectile = new WeaponProjectile(this, _location.clone().add(.5, 0, .5), _projectileAttributes, ((ArmorStand) getEntity("WEAPON")).getHeadPose().getY(), vel[0], vel[1]));
_projectile = CustomFire(((ArmorStand) getEntity("WEAPON")).getHeadPose().getY(), vel[0], vel[1]);
}
protected void setFireRule(AccessRule rule)
@ -366,11 +364,6 @@ public abstract class SiegeWeapon implements Listener
_maxAmmunition = maxAmmunition;
}
protected void setProjectileAttributes(ProjectileAttributes projectileAttributes)
{
_projectileAttributes = projectileAttributes;
}
protected boolean isRiding(Player player)
{
return player.equals(getRider());
@ -523,13 +516,13 @@ public abstract class SiegeWeapon implements Listener
protected abstract double[] GetProjectileVelocity();
protected abstract String GetNextState();
protected abstract void FindEntities();
protected abstract WeaponProjectile CustomFire(double yawRot, double verticalVel, double horizontalVel);
protected void CustomTick() { return; }
protected void CustomOnMount(Player player) { return; }
protected void CustomLeftClick(Player player) { return; }
protected void CustomRightClick(Player player) { return; }
protected void CustomCleanup() { return; }
protected void CustomUpdateState(String state) { return; }
protected void CustomFire(WeaponProjectile projectile) { return; }
protected double CustomRotate(double yaw) { return yaw; }
protected boolean CustomDismount(Player player, Entity entity) { return false; }
protected boolean CustomMount(Player player) { return false; }

View File

@ -0,0 +1,63 @@
package mineplex.game.clans.clans.siege.weapon;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.util.Vector;
import mineplex.core.common.util.UtilAlg;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.game.clans.clans.siege.weapon.projectile.WeaponProjectile;
public class TntProjectile extends WeaponProjectile
{
public TntProjectile(SiegeWeapon weapon, Location origin, double yawRot, double yVel, double xMulti)
{
super(weapon, origin, yawRot, yVel, xMulti);
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onTntExplode(EntityExplodeEvent event)
{
if (event.getEntity().equals(_projectileEntity))
{
((TNTPrimed) event.getEntity()).setFuseTicks(60);
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onTntExplode(UpdateEvent event)
{
if (event.getType() != UpdateType.SEC)
{
return;
}
((TNTPrimed) _projectileEntity).setFuseTicks(60);
}
@Override
public Entity spawn()
{
TNTPrimed tnt = _origin.getWorld().spawn(_origin, TNTPrimed.class);
Vector velocity = UtilAlg.getTrajectory(
_origin,
UtilAlg.moveForward(
_origin,
2.,
(float) Math.toDegrees(_yawRot), false))
.multiply(_xMulti)
.setY(_yVel);
tnt.setVelocity(velocity);
return tnt;
}
}

View File

@ -39,14 +39,9 @@ public class Crater implements Listener
private final long _birthTime;
private final int _size;
private final double _airChance;
private final boolean _fire;
private final List<CraterBlock> _blocks;
public Crater(SiegeWeapon weapon, WeaponProjectile projectile, Location origin, int size, double airChance, boolean doFire)
public Crater(SiegeWeapon weapon, WeaponProjectile projectile, Location origin)
{
_weapon = weapon;
_origin = origin;
@ -54,10 +49,6 @@ public class Crater implements Listener
_birthTime = System.currentTimeMillis();
_blocks = new ArrayList<>();
_size = size;
_airChance = airChance;
_fire = doFire;
UtilServer.getPluginManager().registerEvents(this, _weapon.getClans().getPlugin());
createExplosion();

View File

@ -1,75 +0,0 @@
package mineplex.game.clans.clans.siege.weapon.projectile;
import org.bukkit.Material;
public class ProjectileAttributes
{
protected boolean _isFallingBlock;
protected Material _fallingBlockType;
protected byte _fallingBlockData;
protected boolean _isPrimedTnt;
protected boolean _doCrater;
protected int _craterSize;
protected double _craterChanceOfAir;
protected boolean _craterDoFire;
public ProjectileAttributes setFallingBlock()
{
_isFallingBlock = true;
return this;
}
public ProjectileAttributes setFallingBlockType(Material type)
{
_fallingBlockType = type;
return this;
}
public ProjectileAttributes setFallingBlockData(byte data)
{
_fallingBlockData = data;
return this;
}
public ProjectileAttributes setPrimedTnt()
{
_isPrimedTnt = true;
return this;
}
public ProjectileAttributes setDoCrater()
{
_doCrater = true;
return this;
}
public ProjectileAttributes craterSize(int size)
{
_craterSize = size;
return this;
}
public ProjectileAttributes craterDoFire(boolean doFire)
{
_craterDoFire = doFire;
return this;
}
public ProjectileAttributes craterChanceOfAir(double chance)
{
_craterChanceOfAir = chance;
return this;
}
}

View File

@ -23,55 +23,33 @@ import mineplex.core.updater.event.UpdateEvent;
import mineplex.game.clans.clans.siege.events.SiegeWeaponExplodeEvent;
import mineplex.game.clans.clans.siege.weapon.SiegeWeapon;
public class WeaponProjectile implements Listener
public abstract class WeaponProjectile implements Listener
{
private ProjectileAttributes _attributes;
private Location _origin;
private Entity _projectileEntity;
protected Location _origin;
protected Entity _projectileEntity;
private SiegeWeapon _weapon;
protected SiegeWeapon _weapon;
private double _yRot;
private double _xMulti;
private double _yVel;
protected double _yawRot;
protected double _xMulti;
protected double _yVel;
private boolean _dead;
protected boolean _dead;
private Player _shooter;
protected Player _shooter;
public WeaponProjectile(SiegeWeapon weapon, Location origin, ProjectileAttributes attributes, double yRot, double yVel, double xMulti)
public WeaponProjectile(SiegeWeapon weapon, Location origin, double yawRot, double yVel, double xMulti)
{
_shooter = weapon.getRider();
_weapon = weapon;
_origin = origin;
_attributes = attributes;
_yRot = yRot;
_yawRot = yawRot;
_yVel = yVel;
_xMulti = xMulti;
UtilServer.getPluginManager().registerEvents(this, weapon.getClans().getPlugin());
spawn();
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onTntExplode(EntityExplodeEvent event)
{
if (event.getEntity().equals(_projectileEntity))
{
((TNTPrimed) event.getEntity()).setFuseTicks(60);
event.setCancelled(true);
}
}
@EventHandler
public void onBlockFall(EntityChangeBlockEvent event)
{
if (!_dead && event.getEntity().equals(_projectileEntity))
{
die();
event.setCancelled(true);
}
_projectileEntity = spawn();
}
@EventHandler
@ -82,39 +60,30 @@ public class WeaponProjectile implements Listener
return;
}
if (_projectileEntity.isDead())
if (_projectileEntity == null || _projectileEntity.isDead())
{
die();
return;
}
if (_dead || _projectileEntity == null)
if (_projectileEntity.getTicksLived() <= 10)
{
die();
return;
}
((TNTPrimed) _projectileEntity).setFuseTicks(60);
boolean moving = Math.abs(_projectileEntity.getVelocity().getX()) > 0.01 || Math.abs(_projectileEntity.getVelocity().getZ()) > 0.01;
if ((Math.abs(_projectileEntity.getVelocity().getX()) < 0.01
|| Math.abs(_projectileEntity.getVelocity().getZ()) < 0.01)
&& UtilBlock.getInRadius(_projectileEntity.getLocation(), 2)
.keySet()
.stream()
.filter(block -> !UtilItem.isBoundless(block.getType()))
.iterator().hasNext() && _projectileEntity.getTicksLived() >= 10)
// Some rough collision detection. Not perfect, but the best I could conjure up myself.
if (!moving && !UtilBlock.boundless(_projectileEntity.getLocation(), 2))
{
SiegeWeaponExplodeEvent newEvent = new SiegeWeaponExplodeEvent(_weapon, this);
UtilServer.CallEvent(newEvent);
SiegeWeaponExplodeEvent newEvent = UtilServer.CallEvent(new SiegeWeaponExplodeEvent(_weapon, this));
if (!newEvent.isCancelled())
{
new Crater(_weapon, this, _projectileEntity.getLocation(), _attributes._craterSize, _attributes._craterChanceOfAir, _attributes._craterDoFire);
new Crater(_weapon, this, _projectileEntity.getLocation());
UtilServer.getServer().getOnlinePlayers().forEach(player -> player.playSound(_projectileEntity.getLocation(), Sound.EXPLODE, 1.f, 1.f));
}
UtilServer.getServer().getOnlinePlayers().forEach(player -> player.playSound(_projectileEntity.getLocation(), Sound.EXPLODE, 1.f, 1.f));
die();
}
}
@ -147,48 +116,7 @@ public class WeaponProjectile implements Listener
_dead = true;
}
private void spawn()
{
if (_attributes._isFallingBlock)
{
FallingBlock fallingBlock = _origin.getWorld().spawnFallingBlock(_origin, _attributes._fallingBlockType, _attributes._fallingBlockData);
_projectileEntity = fallingBlock;
Vector velocity = UtilAlg.getTrajectory(
_origin,
UtilAlg.moveForward(
_origin,
2.,
(float) Math.toDegrees(_yRot), false))
.multiply(_xMulti)
.setY(_yVel);
fallingBlock.setVelocity(velocity);
}
else if (_attributes._isPrimedTnt)
{
TNTPrimed tnt = _origin.getWorld().spawn(_origin, TNTPrimed.class);
_projectileEntity = tnt;
Vector velocity = UtilAlg.getTrajectory(
_origin,
UtilAlg.moveForward(
_origin,
2.,
(float) Math.toDegrees(_yRot), false))
.multiply(_xMulti)
.setY(_yVel);
tnt.setVelocity(velocity);
}
}
public int getCraterSize()
{
return _attributes._craterSize;
}
public abstract Entity spawn();
public Player getShooter()
{