From 3d7a371d1dae24a18478a9511d0f7969d7956728 Mon Sep 17 00:00:00 2001 From: NewGarbo Date: Tue, 26 Jan 2016 20:18:53 +0000 Subject: [PATCH] catapults --- .../mineplex/game/clans/clans/ClanTips.java | 5 + .../game/clans/clans/siege/SiegeManager.java | 44 ++ .../clans/clans/siege/catapult/Catapult.java | 457 ++++++++++++++++++ .../siege/catapult/CatapultProjectile.java | 79 +++ .../clans/siege/catapult/CatapultState.java | 34 ++ .../siege/outpost/CommandSiegeSupplies.java | 6 +- 6 files changed, 624 insertions(+), 1 deletion(-) create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/Catapult.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/CatapultProjectile.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/CatapultState.java diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClanTips.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClanTips.java index 4cf85117f..eb76dfd1b 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClanTips.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClanTips.java @@ -224,6 +224,11 @@ public class ClanTips extends MiniPlugin C.cDAqua + "Cannons", C.cAqua + "A Cannon is a Siege weapon used to infiltrate your enemies bases. NEEDS MORE INFO HERE, I'M NOT GOOD AT THINKING UP STUFF THIS LATE!!!!" }), + MOUNT_CATAPULT( + new String[] { + C.cDAqua + "Meowapult", + C.cAqua + "Congratulations on your new purchase! You are now in possesion, of the one, and only, Meowapult 3000.24! " + C.Italics + "we are not responsible for any injuries caused by the meowapult, or any related products. please stay safe." + }), ; // this is only LinkedList because UtilPlayer.message wants it diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/SiegeManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/SiegeManager.java index a30fa5073..d705844e1 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/SiegeManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/SiegeManager.java @@ -12,6 +12,7 @@ import mineplex.core.common.util.UtilInv; import mineplex.core.common.util.UtilPlayer; import mineplex.game.clans.clans.ClansManager; import mineplex.game.clans.clans.siege.cannon.Cannon; +import mineplex.game.clans.clans.siege.catapult.Catapult; import mineplex.game.clans.clans.siege.outpost.CommandSiegeSupplies; import mineplex.game.clans.clans.siege.outpost.OutpostManager; @@ -45,6 +46,17 @@ public class SiegeManager extends MiniPlugin return; } } + + if (event.getItemInHand().isSimilar(Catapult.CATAPULT_ITEM)) + { + event.setCancelled(true); + + if (trySpawnCatapult(event.getPlayer(), event.getBlock().getLocation())) + { + event.getPlayer().setItemInHand(UtilInv.decrement(event.getPlayer().getItemInHand())); + return; + } + } } public boolean trySpawnCannon(Player player, Location location) @@ -78,4 +90,36 @@ public class SiegeManager extends MiniPlugin _outpostManager.getPlugin().getServer().getPluginManager().registerEvents(cannon, _outpostManager.getPlugin()); } + + public boolean trySpawnCatapult(Player player, Location location) + { + if (!_clans.isInClan(player)) + { + UtilPlayer.message(player, F.main("Clans", "You must be in a Clan to place a catapult.")); + return false; + } + + if (_clans.getClanUtility().isClaimed(location)) + { + UtilPlayer.message(player, F.main("Clans", "A catapult must be placed in unclaimed territory.")); + return false; + } + +// if (!isInOutpostSiegeArea(location, _clans.getClan(player))) +// { +// UtilPlayer.message(player, F.main("Clans", "A cannon must be placed in your own Clan's Outpost.")); +// return false; +// } + + spawnCannon(player, location); + + return true; + } + + public void spawnCatapult(Player player, Location location) + { + Catapult catapult = new Catapult(location, _clans.getClan(player)); + + _outpostManager.getPlugin().getServer().getPluginManager().registerEvents(catapult, _outpostManager.getPlugin()); + } } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/Catapult.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/Catapult.java new file mode 100644 index 000000000..0d0822953 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/Catapult.java @@ -0,0 +1,457 @@ +package mineplex.game.clans.clans.siege.catapult; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftArmorStand; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.event.player.PlayerArmorStandManipulateEvent; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.EulerAngle; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilInv; +import mineplex.core.common.util.UtilItem; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilText; +import mineplex.core.common.util.UtilTextMiddle; +import mineplex.core.common.util.UtilTime; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.ClanInfo; +import mineplex.game.clans.clans.ClansManager; + +public class Catapult implements Listener +{ + public static final ItemStack CATAPULT_ITEM = new ItemBuilder(Material.GOLD_BLOCK, 1).setRawTitle(C.cBlue + "Catapult").setLore(C.cWhite + "AWHHH YEAH!!!").build(); + + public static final int COOLDOWN = 10 * 1000 /* 20 seconds*/; + + public static final int MAX_CHARGES = 3; + public static final int MAX_COBBLE = 1; + + public static final int COBBLE_SLOT = 4; + public static final List CHARGE_SLOTS = Arrays.asList(1, 3, 5, 7); + public static final List EMPTY_SLOTS = Arrays.asList(0, 2, 6, 8); + + private static final double[] VERT_POWER = { 0.9, 1.25631, 1.5382 }; + private static final double[] HORIZ_POWER = { 0.8, 1.1241, 1.34231 }; + + private Location _location; + private CatapultState _state; + + private float _nextYaw; + + // Entity Information + private List _entities; + + private CatapultProjectile _projectile; + + private Inventory _inventory; + + private long _lastFired = -1; + + private ClanInfo _clan; + + public Catapult(Location location, ClanInfo clan) + { + _location = location; + _state = CatapultState.UNLOADED; + + _entities = new ArrayList<>(); + + _inventory = UtilServer.getServer().createInventory(null, InventoryType.DISPENSER, C.cRedB + "Catapult"); + + _clan = clan; + + updateEntities(); + } + + public void cleanup() + { + _entities.forEach(Entity::remove); + + _entities.clear(); + + HandlerList.unregisterAll(this); + } + + private void updateEntities() + { + if (_entities.isEmpty()) + { + ArmorStand armorStand = _location.getWorld().spawn(getArmorStandLocation(), ArmorStand.class); + + UtilEnt.setFakeHead(armorStand, true); + armorStand.teleport(getArmorStandLocation()); + armorStand.setVisible(false); + armorStand.setGravity(false); + armorStand.setHelmet(_state.toItemStack()); + + _entities.add(armorStand); + } + else + { + getArmorStand().setHelmet(_state.toItemStack()); + } + } + + private CraftArmorStand getArmorStand() + { + return (CraftArmorStand) UtilMath.getFirst(_entities); + } + + private Location getArmorStandLocation() + { + return _location.clone().add(.5, -1.1, .5); + } + + private void setState(CatapultState state) + { + _state = state; + updateEntities(); + } + + public void fire() + { + CatapultProjectile projectile = new CatapultProjectile(_location.clone().add(.5, .3, .5), Material.COBBLESTONE); + + _projectile = projectile; + + double vVel = VERT_POWER[getPower() - 1]; + double hMulti = HORIZ_POWER[getPower() - 1]; + + Vector velocity = UtilAlg.getTrajectory( + getArmorStand().getLocation(), + UtilAlg.moveForward( + getArmorStand().getLocation(), + 2., + (float) Math.toDegrees(getArmorStand().getHeadPose().getY()), false)) + .multiply(hMulti) + .setY(vVel); + + projectile.setVelocity(velocity); + + _inventory.setItem(COBBLE_SLOT, UtilInv.decrement(_inventory.getItem(COBBLE_SLOT))); + CHARGE_SLOTS.forEach(_inventory::clear); + + UtilServer.getServer().getOnlinePlayers().forEach(player -> player.playSound(getArmorStandLocation(), Sound.BAT_TAKEOFF, 1.f, 1.f)); + + _lastFired = System.currentTimeMillis(); + } + + @EventHandler + public void onCloseInv(InventoryCloseEvent event) + { + if (!event.getInventory().equals(_inventory)) + { + return; + } + + ClansManager.getInstance().runSyncLater(() -> { + if (event.getPlayer().getInventory().equals(_inventory)) + { + return; + } + + if (canBeFired()) + { + UtilTextMiddle.display("Catapult Ready", "Power Level: " + C.cGreen + UtilText.repeat("▌", getPower()) + C.cRed + UtilText.repeat("▌", MAX_CHARGES - getPower()), 20, 100, 20, (Player) event.getPlayer()); + } + }, 3L); + } + + public void updateProjectile() + { + if (_projectile != null) + { + UtilParticle.PlayParticleToAll(ParticleType.LARGE_SMOKE, _projectile.getLocation().add(0, .5, 0), new Vector(0, 0, 0), .1f, 3, ViewDist.MAX); + + if ((Math.abs(_projectile.getVelocity().getX()) < 0.01 || Math.abs(_projectile.getVelocity().getZ()) < 0.01) && UtilBlock.getInRadius(_projectile.getLocation(), 2).keySet().stream().filter(block -> !UtilItem.isBoundless(block.getType())).iterator().hasNext() && _projectile.getTicksLived() >= 10) + { + //Do Explosion; + UtilServer.getServer().getOnlinePlayers().forEach(player -> player.playSound(_projectile.getLocation(), Sound.EXPLODE, 1.f, 1.f)); + + _projectile.remove(); + _projectile = null; + } + } + } + + private void attemptFire(Player human) + { + if (!_clan.isMember(human)) + { + UtilPlayer.message(human, F.main("Clans", "This catapult is not owned by your Clan.")); + return; + } + + if (canBeFired()) + { + if (System.currentTimeMillis() - _lastFired < COOLDOWN) + { + UtilPlayer.message(human, F.main("Clans", "Catapult is cooling down. (" + F.time(UtilTime.MakeStr(COOLDOWN - (System.currentTimeMillis() - _lastFired)) + C.mBody + ")"))); + return; + } + + fire(); + } + else + { + UtilPlayer.message(human, F.main("Clans", "Catapult is not correctly loaded.")); + human.playSound(human.getLocation(), Sound.CLICK, 1.f, 1.f); + } + } + + private void handleOpenInv(Player player) + { + if (_inventory == null) + { + cleanup(); + return; + } + + if (!_clan.isMember(player)) + { + UtilPlayer.message(player, F.main("Clans", "This catapult is not owned by your Clan.")); + return; + } + + if (!_inventory.getViewers().isEmpty()) + { + UtilPlayer.message(player, F.main("Clans", "Someone is already looking in this catapult.")); + return; + } + + player.openInventory(_inventory); + } + + private int getPower() + { + int power = 0; + + for (int slot : CHARGE_SLOTS) + { + if (_inventory.getItem(slot) != null) + { + power += _inventory.getItem(slot).getAmount(); + } + } + + return power / 4; + } + + private int getCobblestone() + { + return _inventory.getItem(COBBLE_SLOT) != null ? _inventory.getItem(COBBLE_SLOT).getAmount() : 0; + } + + private boolean canBeFired() + { + return getCobblestone() > 0 && getPower() > 0 && _projectile == null; + } + + @EventHandler + public void updateState(UpdateEvent event) + { +// if (event.getType() == UpdateType.FASTEST) +// { +// if (_state == CannonState.LOADED) +// { +// double yaw = getArmorStand().getHeadPose().getY() - 7.75d; +// +// Location loc = new Location(_location.getWorld(), getArmorStand().getLocation().getX() + (0.5 * Math.cos(yaw)), _location.getY() + 1.12, getArmorStand().getLocation().getZ() + (0.5 * Math.sin(yaw))); +// +// loc = UtilAlg.moveForward(loc, 0.1, (float) Math.toDegrees(yaw + 7.75), false); +// +// UtilParticle.PlayParticleToAll(ParticleType.FLAME, loc, new Vector(0, 0, 0), 0.f, 1, ViewDist.MAX); +// } +// } + + if (event.getType() != UpdateType.TICK) + { + return; + } + + CatapultState newState = _inventory.getItem(COBBLE_SLOT) != null ? CatapultState.LOADED : CatapultState.UNLOADED; + + if (_state != newState) + { + setState(newState); + } + + if (!_inventory.getViewers().isEmpty()) + { + checkInv((Player) _inventory.getViewers().get(0)); + } + + updateProjectile(); + } + + public void checkInv(Player human) + { + for (int slot = 0; slot < 9; slot++) + { + ItemStack item = _inventory.getItem(slot); + + if (item == null) + { + continue; + } + + if (slot == COBBLE_SLOT) + { + if (item.getType() != Material.COBBLESTONE) + { + human.getInventory().addItem(item); + _inventory.setItem(slot, null); + } + else + { + if (item.getAmount() > MAX_CHARGES) + { + human.getInventory().addItem(new ItemStack(Material.COBBLESTONE, item.getAmount() - MAX_COBBLE)); + _inventory.setItem(slot, new ItemStack(Material.COBBLESTONE, MAX_COBBLE)); + } + } + } + else if (CHARGE_SLOTS.contains(slot)) + { + if (item.getType() != Material.FIREWORK_CHARGE) + { + human.getInventory().addItem(item); + _inventory.setItem(slot, null); + } + else + { + if (item.getAmount() > MAX_CHARGES) + { + human.getInventory().addItem(new ItemStack(Material.FIREWORK_CHARGE, item.getAmount() - MAX_CHARGES)); + _inventory.setItem(slot, new ItemStack(Material.FIREWORK_CHARGE, MAX_CHARGES)); + } + } + } + else if (EMPTY_SLOTS.contains(slot)) // also classes as just an 'else{}' + { + human.getInventory().addItem(item); + _inventory.setItem(slot, null); + } + } + } + + + @EventHandler + public void onInteract(PlayerInteractAtEntityEvent event) + { + if (_entities.contains(event.getRightClicked())) + { + handleOpenInv(event.getPlayer()); + event.setCancelled(true); + } + } + + @EventHandler + public void onInteract(PlayerInteractEntityEvent event) + { + if (_entities.contains(event.getRightClicked())) + { + handleOpenInv(event.getPlayer()); + event.setCancelled(true); + } + } + + @EventHandler + public void onInteract(PlayerArmorStandManipulateEvent event) + { + if (_entities.contains(event.getRightClicked())) + { + handleOpenInv(event.getPlayer()); + event.setCancelled(true); + } + } + + @EventHandler + public void update(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + ArmorStand armorStand = getArmorStand(); + double standYaw = Math.toDegrees(armorStand.getHeadPose().getY()) % 360; + double riderYaw = _nextYaw; + + // riderYaw = 350 and standYaw = 20 + // dif should be -30 and not 330 + double dif = riderYaw - standYaw; + if (dif > 180) dif -= 360; + if (dif < -180) dif += 360; + + double yaw = standYaw + Math.min(dif / 20.f, 5f); + + Location pos = armorStand.getLocation(); + + pos.setYaw((float) yaw); + + armorStand.teleport(pos); + armorStand.setHeadPose(new EulerAngle(0, Math.toRadians(yaw), 0)); + } + + @EventHandler + public void onDamage(EntityDamageEvent event) + { + if (_entities.contains(event.getEntity())) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onDmg(EntityDamageByEntityEvent event) + { + if (!(event.getDamager() instanceof Player)) + { + return; + } + + if (!_entities.contains(event.getEntity())) + { + return; + } + + if (canBeFired()) + attemptFire((Player) event.getDamager()); + else + _nextYaw = ((Player) event.getDamager()).getLocation().getYaw(); + } +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/CatapultProjectile.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/CatapultProjectile.java new file mode 100644 index 000000000..163cb007a --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/CatapultProjectile.java @@ -0,0 +1,79 @@ +package mineplex.game.clans.clans.siege.catapult; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.ArmorStand; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.EulerAngle; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilServer; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.ClansManager; + +public class CatapultProjectile implements Listener +{ + private ArmorStand _parent; + + public CatapultProjectile(Location location, Material material) + { + _parent = location.getWorld().spawn(location, ArmorStand.class); + + UtilEnt.setFakeHead(_parent, true); + _parent.teleport(location); + _parent.setVisible(false); + _parent.setGravity(false); + _parent.setHelmet(new ItemStack(material)); + + UtilServer.getServer().getPluginManager().registerEvents(this, ClansManager.getInstance().getPlugin()); + } + + @EventHandler + public void update(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_parent == null || _parent.isDead()) + { + return; + } + + _parent.setHeadPose(new EulerAngle(_parent.getHeadPose().getX() + 2.75, _parent.getHeadPose().getY(), _parent.getHeadPose().getZ())); + } + + public void remove() + { + HandlerList.unregisterAll(this); + _parent.remove(); + _parent = null; + } + + public Location getLocation() + { + return _parent.getLocation(); + } + + public Vector getVelocity() + { + return _parent.getVelocity(); + } + + public int getTicksLived() + { + return _parent.getTicksLived(); + } + + public void setVelocity(Vector velocity) + { + _parent.setVelocity(velocity); + } + +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/CatapultState.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/CatapultState.java new file mode 100644 index 000000000..50e9c8fdc --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/catapult/CatapultState.java @@ -0,0 +1,34 @@ +package mineplex.game.clans.clans.siege.catapult; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +public enum CatapultState +{ + UNLOADED(Material.PACKED_ICE, (byte) 0 /* packed ice */), + LOADED(Material.LAPIS_BLOCK, (byte) 0 /* lapis block */); + + private Material _material; + private byte _data; + + CatapultState(Material material, byte data) + { + _material = material; + _data = data; + } + + public byte getData() + { + return _data; + } + + public Material getMaterial() + { + return _material; + } + + public ItemStack toItemStack() + { + return new ItemStack(_material, 1, (short) 0, _data); + } +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/CommandSiegeSupplies.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/CommandSiegeSupplies.java index b2bfedefd..86ed92e0d 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/CommandSiegeSupplies.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/CommandSiegeSupplies.java @@ -8,6 +8,7 @@ import mineplex.core.common.Rank; import mineplex.core.common.util.F; import mineplex.core.common.util.UtilPlayer; import mineplex.game.clans.clans.siege.cannon.Cannon; +import mineplex.game.clans.clans.siege.catapult.Catapult; public class CommandSiegeSupplies extends CommandBase { @@ -21,13 +22,16 @@ public class CommandSiegeSupplies extends CommandBase { ItemStack outpost = new ItemStack(Outpost.OUTPOST_ITEM); ItemStack cannons = new ItemStack(Cannon.CANNON_ITEM); + ItemStack catapults = new ItemStack(Catapult.CATAPULT_ITEM); outpost.setAmount(64); cannons.setAmount(64); + catapults.setAmount(64); caller.getInventory().addItem(outpost); caller.getInventory().addItem(cannons); - + caller.getInventory().addItem(catapults); + UtilPlayer.message(caller, F.main("Clans", "Received supplies for a siege.")); } }