diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemBoss.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemBoss.java new file mode 100644 index 000000000..23c90c70f --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemBoss.java @@ -0,0 +1,47 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard; + +import org.bukkit.Bukkit; +import org.bukkit.Location; + +import mineplex.core.common.util.F; +import mineplex.game.clans.clans.worldevent.WorldEventManager; +import mineplex.game.clans.clans.worldevent.boss.BossWorldEvent; + +public class GolemBoss extends BossWorldEvent +{ + public GolemBoss(WorldEventManager manager) + { + super("Iron Wizard", manager.getBossArenaLocationFinder().getIronWizardCenter(), 30, manager.getBossArenaLocationFinder().getIronWizardPads().getLeft(), manager.getBossArenaLocationFinder().getIronWizardPads().getRight(), manager.getDisguiseManager(), manager.getClans().getProjectile(), manager.getClans().getDamageManager(), manager.getBlockRestore(), manager.getClans().getCondition()); + } + + @Override + protected void customStart() + { + Bukkit.broadcastMessage(F.main(getName(), "The mighty " + getName() + " challenges you to face him!")); + spawnGolem(getCenterLocation()); + announceStart(); + } + + @Override + public String getDeathMessage() + { + return F.main(getName(), "The mighty " + getName() + " has fallen!"); + } + + private GolemCreature spawnGolem(Location location) + { + GolemCreature golemCreature = new GolemCreature(this, location, 3000); + registerCreature(golemCreature); + setBossCreature(golemCreature); + return golemCreature; + } + + @Override + protected void customTick() {} + + @Override + public void customCleanup() {} + + @Override + protected void customStop() {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemCreature.java new file mode 100644 index 000000000..540c7cea0 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemCreature.java @@ -0,0 +1,596 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemBlockHail; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemBlockShot; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemDeadlyTremor; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemEarthquake; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemExplodingAura; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemIronHook; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemMeleeAttack; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemRupture; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemSlam; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemSpike; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class GolemCreature extends EventCreature +{ + private int _lastAbility; + private long _lastWalked; + private Location _standing; + private long _spawnDelay = System.currentTimeMillis(); + private long _reverseWalk; + private Map>, Class[]> _preferredCombos = new HashMap<>(); + private Class> _lastAttack; + private boolean _usedFinalAttack; + private List> _currentAbilities = new ArrayList<>(); + private double _canDeadlyTremor = 225; + private Vector _afkWalk = new Vector(); + private long _lastSlam; + + public GolemCreature(GolemBoss boss, Location location, double maxHealth) + { + super(boss, location, "Iron Wizard", true, 3000, 30, true, IronGolem.class); + + spawnEntity(); + + _preferredCombos.put(GolemEarthquake.class, new Class[] + { + GolemBlockHail.class, GolemRupture.class + }); + _preferredCombos.put(GolemMeleeAttack.class, new Class[] + { + GolemEarthquake.class, GolemRupture.class + }); + _preferredCombos.put(GolemDeadlyTremor.class, new Class[] + { + GolemMeleeAttack.class + }); + _preferredCombos.put(GolemBlockShot.class, new Class[] + { + GolemEarthquake.class + }); + _preferredCombos.put(GolemRupture.class, new Class[] + { + GolemBlockShot.class + }); + _preferredCombos.put(GolemBlockHail.class, new Class[] + { + GolemDeadlyTremor.class + }); + } + + private boolean hasFurther(Map distances, double range) + { + for (Player player : distances.keySet()) + { + if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + + Double dist = distances.get(player); + if (dist >= range) + { + return true; + } + } + + return false; + } + + @Override + protected void spawnCustom() + { + UtilEnt.vegetate(getEntity()); + _standing = getEntity().getLocation(); + } + + @SuppressWarnings("unchecked") + @EventHandler + public void abilityTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (!UtilTime.elapsed(_spawnDelay, 5000)) + { + _standing = getEntity().getLocation(); + return; + } + + Iterator> itel = _currentAbilities.iterator(); + boolean canDoNew = _currentAbilities.size() < 3; + + while (itel.hasNext()) + { + BossAbility ability = itel.next(); + + if (ability.hasFinished()) + { + itel.remove(); + ability.setFinished(); + _lastAbility = 20; + + HandlerList.unregisterAll(ability); + System.out.print("Unregistered golem ability " + ability.getClass().getSimpleName()); + } + else if (!ability.inProgress()) + { + canDoNew = false; + } + } + + if (_lastAbility-- <= 0 && canDoNew && UtilBlock.solid(getEntity().getLocation().getBlock().getRelative(BlockFace.DOWN))) + { + Map>, Integer> weight = new HashMap<>(); + Map dist = new HashMap<>(); + + for (Player player : UtilPlayer.getNearby(getEntity().getLocation(), 50, true)) + { + if (player.hasLineOfSight(getEntity())) + { + dist.put(player, player.getLocation().distance(getEntity().getLocation())); + } + } + + if (!dist.isEmpty()) + { + double hp = getHealthPercent(); + + { // Melee + List players = getPlayers(dist, UtilMath.r(10) == 0 ? 4 : 3); + + if (!players.isEmpty()) + { + if (players.size() >= 4) + { + weight.put(GolemEarthquake.class, 999); + } + else + { + weight.put(GolemMeleeAttack.class, 999); + } + } + } + + if (hasFurther(dist, 15)) + { // Iron Hook + weight.put(GolemIronHook.class, 6); //6 + } + + if (hp < 0.7) + { // Earthquake + List players = getPlayers(dist, 10); + + double score = 0; + + for (Player player : players) + { + score += (8 - dist.get(player)) / 2; + } + + if (players.size() >= 3) + { + score += 7; + } + + if (score > 0) + { + weight.put(GolemEarthquake.class, (int) Math.ceil(score)); + } + } + + { // Wall explode + if (!getPlayers(dist, 20).isEmpty() && getPlayers(dist, 4).isEmpty()) + { + weight.put(GolemSpike.class, 8); + } + } + + { // Block Shot + List players = getPlayers(dist, 30); + + for (Player player : players) + { + if (dist.get(player) > 4) + { + weight.put(GolemBlockShot.class, 6); + break; + } + } + } + + { // Rupture + List players = getPlayers(dist, 30); + + if (!players.isEmpty()) + { + weight.put(GolemRupture.class, (int) Math.min(5, dist.get(players.get(0)))); + } + } + + { // Slam + List players = getPlayers(dist, 30); + + if (!players.isEmpty() && UtilTime.elapsed(_lastSlam, 20000)) + { + weight.put(GolemSlam.class, 6); + } + } + + if (_canDeadlyTremor <= 0) // Deadly Tremor + { + List players = getPlayers(dist, 80); + + for (BossAbility ability : _currentAbilities) + { + if (ability instanceof GolemExplodingAura) + { + players.clear(); + } + } + + if (!players.isEmpty()) + { + weight.put(GolemDeadlyTremor.class, (int) 30); + } + } + + {// Block Hail + List players = getPlayers(dist, 30); + + if (!players.isEmpty()) + { + int we = _lastAttack == GolemEarthquake.class ? 20 : UtilMath.r(15) - 2; + + if (we > 0) + { + weight.put(GolemBlockHail.class, we); + } + } + } + + if (!_usedFinalAttack && getHealth() < 90) + { + _usedFinalAttack = true; + weight.clear(); + + weight.put(GolemExplodingAura.class, 999); + } + + if (_lastAttack != null && _preferredCombos.containsKey(_lastAttack)) + { + weight.remove(_lastAttack); + + for (Class c : _preferredCombos.get(_lastAttack)) + { + if (weight.containsKey(c)) + { + weight.put((Class>)c, weight.get(c) * 4); + } + } + } + + for (BossAbility ability : _currentAbilities) + { + weight.remove(ability.getClass()); + } + + BossAbility ability = null; + + if (!weight.isEmpty()) + { + int i = 0; + + for (Integer entry : weight.values()) + { + i += entry; + } + + for (int a = 0; a < 10; a++) + { + int luckyNumber = UtilMath.r(i); + + for (Entry>, Integer> entry : weight.entrySet()) + { + luckyNumber -= entry.getValue(); + + if (luckyNumber <= 0) + { + try + { + ability = entry.getKey().getConstructor(GolemCreature.class).newInstance(this); + + if (ability.getTarget() == null) + { + ability = null; + } + else + { + break; + } + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + break; + } + } + } + } + + if (ability != null && ability.getTarget() != null) + { + _lastAttack = (Class>) ability.getClass(); + + if (ability instanceof GolemDeadlyTremor) + { + _canDeadlyTremor = 225; + } + else if (ability instanceof GolemSlam) + { + _lastSlam = System.currentTimeMillis(); + } + + Bukkit.getPluginManager().registerEvents(ability, UtilServer.getPlugin()); + + if (DEBUG_MODE) + { + System.out.print("Golem boss is using " + ability.getClass().getSimpleName()); + } + + _currentAbilities.add(ability); + } + + _lastAbility = 10; + } + + _lastAttack = null; + } + + boolean canMove = true; + + for (BossAbility ability : _currentAbilities) + { + try + { + ability.tick(); + } + catch (Exception e) + { + e.printStackTrace(); //Keeps the boss from getting stuck if one of the moves throws an error in progression + } + + if (!ability.canMove()) + { + canMove = false; + } + } + + if (canMove) + { + Player target = null; + double dist = 0; + + for (Player player : UtilPlayer.getNearby(getEntity().getLocation(), 50, true)) + { + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + double d = player.getLocation().distance(getEntity().getLocation()); + + if (d > 1.5 && (d < 7 || d > 15) && (target == null || (d < 50 && dist > d))) + { + target = player; + dist = d; + } + } + + Vector vec = null; + boolean superWalk = false; + + if (target != null) + { + vec = target.getLocation().subtract(getEntity().getLocation()).toVector(); + vec.setY(getEntity().getLocation().getY()); + + double len = vec.length(); + + vec.setX(vec.getX() * (UtilMath.random.nextDouble() / 3D)); + vec.setZ(vec.getZ() * (UtilMath.random.nextDouble() / 3D)); + + vec.multiply(len); + + if (target != null && dist < 8) + { + vec.multiply(-1); + superWalk = true; + } + + if (!UtilAlg.HasSight(getEntity().getLocation(), + getEntity().getLocation().add(vec.clone().normalize().multiply(2)))) + { + _reverseWalk = System.currentTimeMillis(); + } + + if (!UtilTime.elapsed(_reverseWalk, 4000)) + { + vec.multiply(-1); + } + + } + else if (!UtilTime.elapsed(_lastWalked, 7000)) + { + vec = _afkWalk; + } + else if (UtilTime.elapsed(_lastWalked, 12000)) + { + _afkWalk = new Vector(); + + for (int i = 0; i < 10; i++) + { + Vector vector = new Vector(UtilMath.r(20) - 10, 0, UtilMath.r(20) - 10); + + if (UtilAlg.HasSight(getEntity().getLocation(), + getEntity().getLocation().add(vector.clone().normalize().multiply(2)))) + { + vec = _afkWalk = vector; + break; + } + } + + _lastWalked = System.currentTimeMillis(); + } + + if (vec != null) + { + { + UtilEnt.CreatureMoveFast(getEntity(), getEntity().getLocation().add(vec), + (target != null ? 1.8F : 1.1F) + (superWalk ? 0.4F : 0)); + } + } + + _standing = getEntity().getLocation(); + } + else + { + Location l = getEntity().getLocation(); + + _standing.setYaw(l.getYaw()); + _standing.setPitch(l.getPitch()); + _standing.setY(l.getY()); + + getEntity().teleport(_standing); + } + } + + private List getPlayers(final Map map, double maxDist) + { + List list = new ArrayList(); + + for (Player p : map.keySet()) + { + if (map.get(p) <= maxDist) + { + list.add(p); + } + } + + Collections.sort(list, (o1, o2) -> + { + return Double.compare(map.get(o2), map.get(o1)); + }); + + return list; + } + + @EventHandler + public void onGolemDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().equals(getEntity())) + { + event.AddKnockback("Heavy Golem", 0.3); + } + } + + @EventHandler + public void onRangedAttack(CustomDamageEvent event) + { + if (event.GetDamageeEntity().equals(getEntity())) + { + if (event.GetDamageePlayer() != null) + { + if (event.GetProjectile() != null && event.GetProjectile() instanceof Arrow) + { + if (new Random().nextDouble() <= .5) + { + event.SetCancelled("Iron Skin Reflection"); + getEntity().getWorld().playSound(getEntity().getLocation(), Sound.ZOMBIE_METAL, 0.5f, 1.6f); + return; + } + } + + double dist = event.GetDamageePlayer().getLocation().distance(getEntity().getLocation()); + + double maxRange = _usedFinalAttack ? 20 : 45; + + double modifier = (maxRange - dist) / maxRange; + + if (modifier > 0) + { + event.AddMod("Ranged Resistance", 1 - modifier); + } + else + { + event.SetCancelled("Range too far"); + } + } + } + } + + @Override + public void dieCustom() + { + endAbility(); + } + + private void endAbility() + { + for (BossAbility ability : _currentAbilities) + { + ability.setFinished(); + HandlerList.unregisterAll(ability); + } + + _currentAbilities.clear(); + } + + @Override + public void setHealth(double health) + { + _canDeadlyTremor -= getHealth() - health; + super.setHealth(health); + if (getHealth() <= 100 && !_usedFinalAttack) + { + endAbility(); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/BlockHailBlock.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/BlockHailBlock.java new file mode 100644 index 000000000..d837321c9 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/BlockHailBlock.java @@ -0,0 +1,88 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.IronGolem; + +import mineplex.core.common.util.UtilEnt; +import net.minecraft.server.v1_8_R3.DataWatcher; +import net.minecraft.server.v1_8_R3.Entity; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayOutAttachEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving; + +public class BlockHailBlock +{ + private int _block = UtilEnt.getNewEntityId(); + private int _silverfish = UtilEnt.getNewEntityId(); + private Location _location; + private Material _mat; + + public BlockHailBlock(Location loc, Material mat) + { + _location = loc; + _mat = mat; + } + + public PacketPlayOutEntityDestroy getDestroyPacket() + { + return new PacketPlayOutEntityDestroy(new int[] + { + _silverfish, _block + }); + } + + public Location getLocation() + { + return _location; + } + + public Material getMaterial() + { + return _mat; + } + + @SuppressWarnings("deprecation") + public Packet[] getSpawnPackets(IronGolem entity) + { + Packet[] packets = new Packet[3]; + + PacketPlayOutSpawnEntityLiving packet1 = new PacketPlayOutSpawnEntityLiving(); + + DataWatcher watcher = new DataWatcher(null); + watcher.a(0, (byte) 32, Entity.META_ENTITYDATA, (byte) 0); + watcher.a(1, 0, Entity.META_AIR, 0); + + packet1.a = _silverfish; + packet1.b = EntityType.SILVERFISH.getTypeId(); + packet1.c = (int) Math.floor(_location.getX() * 32); + packet1.d = (int) Math.floor(_location.getY() * 32); + packet1.e = (int) Math.floor(_location.getZ() * 32); + packet1.l = watcher; + + packets[0] = packet1; + + PacketPlayOutSpawnEntity packet2 = new PacketPlayOutSpawnEntity(((CraftEntity) entity).getHandle(), 70, _mat.getId()); + + packet2.a = _block; + + packet2.b = (int) Math.floor(_location.getX() * 32); + packet2.c = (int) Math.floor(entity.getLocation().getY() * 32); + packet2.d = (int) Math.floor(_location.getZ() * 32); + + packets[1] = packet2; + + PacketPlayOutAttachEntity packet3 = new PacketPlayOutAttachEntity(); + + packet3.b = _block; + packet3.c = _silverfish; + + packets[2] = packet3; + + return packets; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockHail.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockHail.java new file mode 100644 index 000000000..99c437774 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockHail.java @@ -0,0 +1,475 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilShapes; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.EntityIronGolem; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemBlockHail extends BossAbility +{ + private int _currentBlock; + private int _currentLevel; + private List _fallingBlocks = new ArrayList<>(); + private Map> _floatingBlocks = new HashMap<>(); + private Map _blocks = new HashMap<>(); + private int _levelToReach; + private boolean _spawned; + private List _spawnLocs = new ArrayList<>(); + private Player _target; + private Location _center; + private int _ticks; + + public GolemBlockHail(GolemCreature creature) + { + super(creature); + + _center = getLocation(); + + if (creature.getHealthPercent() > 0.75) + { + _levelToReach = 1; + } + else if (creature.getHealthPercent() > 0.5) + { + _levelToReach = 2; + } + else + { + _levelToReach = 3; + } + + _target = getTarget(); + } + + @Override + public Player getTarget() + { + Player target = null; + double dist = 0; + + if (inProgress()) + { + for (Player player : UtilPlayer.getNearby(_center, 40, true)) + { + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + if (target != null && _blocks.containsKey(player.getName()) && _blocks.get(player.getName()) > 8) + { + continue; + } + + double d = player.getLocation().distance(_center); + + if (target == null || dist > d) + { + target = player; + dist = d; + } + } + } + + return target; + } + + @Override + public boolean canMove() + { + return _spawned && _floatingBlocks.isEmpty(); + } + + @Override + public boolean hasFinished() + { + return _target == null || !_target.isValid() || ((_fallingBlocks.isEmpty() && _spawned) && _ticks >= 8 * 9) + || _center.distance(_target.getLocation()) > 100; + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + Iterator fallingIterator = _fallingBlocks.iterator(); + + while (fallingIterator.hasNext()) + { + FallingBlock cur = fallingIterator.next(); + + if (cur.isDead() || !cur.isValid() || cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + fallingIterator.remove(); + + Block block = cur.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + // Expire + if (cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + cur.remove(); + continue; + } + + cur.remove(); + continue; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) cur).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, + nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) cur.getWorld()).getHandle().getEntities(((CraftEntity) cur).getHandle(), + ((CraftEntity) cur).getHandle().getBoundingBox().a(((CraftEntity) cur).getHandle().motX, + ((CraftEntity) cur).getHandle().motY, ((CraftEntity) cur).getHandle().motZ).grow(2, 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + continue; + + // Creative or Spec + if (ent instanceof Player) + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + continue; + + // float f1 = (float)(nmsEntity.boundingBox.a() * 0.6f); + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + cur.getWorld().playEffect(victim.getEyeLocation().subtract(0, 0.5, 0), Effect.STEP_SOUND, cur.getBlockId()); + { + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) victim, getEntity(), null, + DamageCause.CONTACT, 10 * getBoss().getDifficulty(), true, true, false, "Iron Wizard Block Hail", + "Iron Wizard Block Hail"); + } + + if (victim instanceof Player) + { + getBoss().getEvent().getCondition().Factory().Slow("Iron Wizard Block Hail", (LivingEntity) victim, + getEntity(), 3, 2, false, false, false, false); + } + + fallingIterator.remove(); + cur.remove(); + } + else if (finalObjectPosition != null) + { + Block block = cur.getWorld().getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt( + nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + fallingIterator.remove(); + cur.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + cur.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + @Override + public void setFinished() + { + for (List floatingBlocks : _floatingBlocks.values()) + { + for (BlockHailBlock falling : floatingBlocks) + { + PacketPlayOutEntityDestroy packet = falling.getDestroyPacket(); + + for (Player player : UtilServer.getPlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + } + } + + for (FallingBlock block : _fallingBlocks) + { + block.remove(); + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (inProgress()) + { + for (Player player : UtilPlayer.getNearby(_center, 5, true)) + { + Location loc = player.getLocation(); + + if (Math.abs(loc.getY() - (_center.getY() + 1)) <= 1) + { + loc.setY(_center.getY()); + + if (loc.distance(_center) < 2.8 + (_currentLevel * 0.75)) + { + if (canDamage(player)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getEntity(), null, + DamageCause.CONTACT, 10 * getBoss().getDifficulty(), true, true, false, + "Iron Wizard Protection", "Iron Wizard Protection"); + + loc.getWorld().playEffect(player.getLocation(), Effect.STEP_SOUND, Material.OBSIDIAN.getId()); + loc.getWorld().playEffect(player.getEyeLocation(), Effect.STEP_SOUND, Material.OBSIDIAN.getId()); + } + } + } + } + } + + if (!_spawned) + { + if (_currentBlock >= _spawnLocs.size()) + { + + if (_currentLevel + 1 <= _levelToReach) + { + _currentLevel++; + _currentBlock = 0; + + _spawnLocs = UtilShapes.getDistancedCircle(_center.clone().add(0, 2.8 + (_currentLevel * 0.75), 0), 1.3, + 1 + (_currentLevel * 1.3)); + + for (int i = UtilMath.r(_spawnLocs.size()); i > 0; i--) + { + _spawnLocs.add(_spawnLocs.remove(0)); + } + } + } + + if (_currentBlock < _spawnLocs.size()) + { + if (_ticks % 2 == 0) + { + IronGolem entity = getEntity(); + + Location loc = _spawnLocs.get(_currentBlock++); + + List floatingBlocks = new ArrayList<>(); + + if (_floatingBlocks.containsKey(_currentLevel)) + { + floatingBlocks = _floatingBlocks.get(_currentLevel); + } + else + { + _floatingBlocks.put(_currentLevel, floatingBlocks); + } + + if (loc.getBlock().getType() == Material.AIR && UtilAlg.HasSight(entity.getLocation(), loc)) + { + + BlockHailBlock floating = new BlockHailBlock(loc, Material.STONE); + UtilEnt.CreatureLook(entity, _target); + + floatingBlocks.add(floating); + + Packet[] packets = floating.getSpawnPackets(entity); + + for (Player player : UtilPlayer.getNearby(loc, 100)) + { + UtilPlayer.sendPacket(player, packets); + } + + entity.getWorld().playSound(entity.getLocation(), Sound.DIG_GRASS, 3, 0.9F); + } + + if (_floatingBlocks.size() % 2 == 0) + { + Collections.reverse(floatingBlocks); + } + } + } + else + { + _spawned = true; + _ticks = -20; + } + } + else if (_ticks > 0 && _ticks % 2 == 0 && !_floatingBlocks.isEmpty()) + { + IronGolem entity = getEntity(); + + if (_ticks % 16 == 0) + { + _target = getTarget(); + + if (_target == null) + return; + } + + EntityIronGolem golem = ((CraftIronGolem) entity).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + UtilEnt.CreatureLook(entity, _target); + + BlockHailBlock floatingBlock = null; + + for (int i = 1; i <= _currentLevel; i++) + { + if (_floatingBlocks.containsKey(i) && !_floatingBlocks.get(i).isEmpty()) + { + floatingBlock = _floatingBlocks.get(i).remove(0); + + if (_floatingBlocks.get(i).isEmpty()) + { + _floatingBlocks.remove(i); + } + + break; + } + } + + PacketPlayOutEntityDestroy packet = floatingBlock.getDestroyPacket(); + + for (Player player : UtilServer.getPlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + + Location loc = floatingBlock.getLocation(); + + FallingBlock b = loc.getWorld().spawnFallingBlock(loc, floatingBlock.getMaterial(), (byte) 0); + b.setDropItem(false); + + Vector vec = UtilAlg.calculateVelocity(loc.toVector(), + _target.getLocation().toVector().add(new Vector(UtilMath.r(6 + (_currentLevel * 2)) - (2 + _currentLevel), 0, + UtilMath.r(6 + (_currentLevel * 2)) - (2 + _currentLevel))), + 6); + + b.setVelocity(vec); + + _fallingBlocks.add(b); + + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 3, 0.9F); + + _blocks.put(_target.getName(), _blocks.containsKey(_target.getName()) ? _blocks.get(_target.getName()) + 1 : 1); + } + + List points = new ArrayList<>(); + + for (int i = _currentLevel; i <= _currentLevel; i++) + { + points.addAll(UtilShapes.getDistancedCircle(_center.clone().add(0, 3.3 + (i * 0.75), 0), 0.3, 1 + (i * 1.3))); + } + + for (int i = 0; i < points.size(); i++) + { + if (_spawned || i < _ticks) + { + Location loc = points.get(i); + + UtilParticle.PlayParticle( + ParticleType.BLOCK_DUST.getParticle(_spawned && i < _ticks ? Material.STONE : Material.DIRT, 0), loc, 0, + 0, 0, 0, 0, UtilParticle.ViewDist.LONG, UtilServer.getPlayers()); + } + } + + _ticks++; + } + + @Override + public boolean inProgress() + { + return !_spawned || !_floatingBlocks.isEmpty(); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockShot.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockShot.java new file mode 100644 index 000000000..4f652b4a8 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockShot.java @@ -0,0 +1,442 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.EntityIronGolem; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityVelocity; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemBlockShot extends BossAbility +{ + private Map _blockLoc = new HashMap<>(); + private Map _blockType = new HashMap<>(); + private List _current = new ArrayList<>(); + private Map _preshoot = new HashMap<>(); + private Player _target; + private Map _targetBlock = new HashMap<>(); + private Map _shotAt = new HashMap<>(); + private int _thrown; + private int _tick; + private int _toThrow; + + public GolemBlockShot(GolemCreature creature) + { + super(creature); + + if (creature.getHealthPercent() > 0.75) + { + _toThrow = 3; + } + else if (creature.getHealthPercent() > 0.5) + { + _toThrow = 6; + } + else + { + _toThrow = 9; + } + + _target = getTarget(); + } + + @Override + public boolean canMove() + { + return _current.isEmpty() && _thrown == _toThrow; + } + + @Override + public Player getTarget() + { + Player target = null; + double dist = 0; + + Location loc1 = getLocation(); + Location loc2 = loc1.clone().add(loc1.getDirection().setY(0).normalize()); + + List players = UtilPlayer.getNearby(getLocation(), 40, true); + + for (Player player : players) + { + if (_shotAt.containsKey(player.getUniqueId()) && _shotAt.get(player.getUniqueId()) >= 3) + { + continue; + } + + double dist1 = player.getLocation().distance(loc1); + double dist2 = player.getLocation().distance(loc2); + + double dist3 = dist1 - dist2; + + if (dist3 < 0.6 || dist1 > 30 || (target != null && dist3 < dist)) + { + continue; + } + + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + target = player; + dist = dist3; + } + + return target; + } + + @Override + public boolean hasFinished() + { + return _current.isEmpty() && _preshoot.isEmpty() && (_target == null || _thrown >= _toThrow); + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + Iterator fallingIterator = _current.iterator(); + + while (fallingIterator.hasNext()) + { + FallingBlock cur = fallingIterator.next(); + + if (cur.isDead() || !cur.isValid() || cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + fallingIterator.remove(); + + Block block = cur.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + // Expire + if (cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + cur.remove(); + continue; + } + + cur.remove(); + continue; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) cur).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, + nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) cur.getWorld()).getHandle().getEntities(((CraftEntity) cur).getHandle(), + ((CraftEntity) cur).getHandle().getBoundingBox().a(((CraftEntity) cur).getHandle().motX, + ((CraftEntity) cur).getHandle().motY, ((CraftEntity) cur).getHandle().motZ).grow(2, 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + continue; + + // Creative or Spec + if (ent instanceof Player) + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + continue; + + // float f1 = (float)(nmsEntity.boundingBox.a() * 0.6f); + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + cur.getWorld().playEffect(victim.getEyeLocation().subtract(0, 0.5, 0), Effect.STEP_SOUND, cur.getBlockId()); + + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) victim, getEntity(), null, + DamageCause.CONTACT, 10 * getBoss().getDifficulty(), true, true, false, "Iron Wizard Block Shot", + "Iron Wizard Block Shot"); + + cur.remove(); + fallingIterator.remove(); + + Vector vec = UtilAlg.getTrajectory(getEntity(), victim); + vec.setY(0).normalize(); + + double strength = 1; + + if (!(victim instanceof Player) || !((Player) victim).isBlocking()) + { + strength = 1.3; + } + + UtilAction.velocity(victim, vec, strength, true, 0, 0.2, 1, true); + } + else if (finalObjectPosition != null) + { + Block block = cur.getWorld().getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt( + nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + cur.remove(); + fallingIterator.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + cur.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + @Override + public void setFinished() + { + for (FallingBlock falling : _current) + { + falling.remove(); + } + + int[] ids = new int[_preshoot.size()]; + + int a = 0; + for (int id : _preshoot.keySet()) + { + ids[a++] = id; + } + + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ids); + + for (Player player : Bukkit.getOnlinePlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (_target == null || _target.getLocation().distance(getLocation()) > 30 || !_target.hasLineOfSight(getEntity())) + { + _target = getTarget(); + } + + Entity entity = getEntity(); + + if (_tick++ % 16 == 0 && _target != null && _thrown < _toThrow) + { + _thrown++; + + UtilEnt.CreatureLook(entity, _target); + EntityIronGolem golem = ((CraftIronGolem) entity).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 2, 1); + + Location loc = entity.getLocation(); + loc.setYaw(loc.getYaw() + (UtilMath.r(150) - 75)); + loc.add(loc.getDirection().setY(0).normalize()); + + Block block = loc.getBlock(); + + if (block.getType() == Material.AIR) + { + block = block.getRelative(BlockFace.DOWN); + } + + Material mat = block.getType(); + + if (!UtilBlock.solid(block)) + { + mat = Material.STONE; + } + + int id = UtilEnt.getNewEntityId(); + + _preshoot.put(id, System.currentTimeMillis()); + _blockType.put(id, mat); + _blockLoc.put(id, loc.clone().add(0, 0.6, 0)); + _targetBlock.put(id, _target); + + PacketPlayOutSpawnEntity packet = new PacketPlayOutSpawnEntity(((CraftEntity) entity).getHandle(), 70, mat.getId()); + + packet.a = id; + + packet.b = (int) Math.floor(loc.getX() * 32); + packet.c = (int) Math.floor(loc.getY() * 32); + packet.d = (int) Math.floor(loc.getZ() * 32); + + packet.g = (int) ((0.45) * 8000); + + PacketPlayOutEntityVelocity packet2 = new PacketPlayOutEntityVelocity(id, 0, 0.45D, 0); + + for (Player player : UtilPlayer.getNearby(loc, 70)) + { + UtilPlayer.sendPacket(player, packet, packet2); + } + + _shotAt.put(_target.getUniqueId(), + (_shotAt.containsKey(_target.getUniqueId()) ? _shotAt.get(_target.getUniqueId()) : 0) + 1); + + _target = getTarget(); + } + else + { + Iterator> itel = _preshoot.entrySet().iterator(); + + while (itel.hasNext()) + { + Entry entry = itel.next(); + + if (UtilTime.elapsed(entry.getValue(), 920)) + { + itel.remove(); + + int id = entry.getKey(); + + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(new int[] + { + id + }); + + for (Player player : Bukkit.getOnlinePlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + + Location loc = _blockLoc.get(id); + FallingBlock falling = loc.getWorld().spawnFallingBlock(loc, _blockType.get(id), (byte) 0); + falling.setDropItem(false); + + _current.add(falling); + + Player target = _targetBlock.get(id); + + UtilEnt.CreatureLook(entity, target); + EntityIronGolem golem = ((CraftIronGolem) entity).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 2, 1.2F); + entity.getWorld().playEffect(falling.getLocation(), Effect.STEP_SOUND, falling.getBlockId()); + + Location l = falling.getLocation(); + l.setY(entity.getLocation().getY()); + + Location loc1 = target.getEyeLocation(); + + if (loc1.getY() - l.getY() > 1) + { + loc1.setY(l.getY() + 1); + } + + int dist = (int) Math.ceil(loc1.toVector().setY(0).distance(l.toVector().setY(0))); + + Vector vector = UtilAlg.calculateVelocity(l.toVector(), loc1.toVector(), dist / 13); + + falling.setVelocity(vector); + } + } + } + + if (_thrown >= 3 && !UtilPlayer.getNearby(getLocation(), 10, true).isEmpty()) + { + _thrown = 99; + } + } + + @Override + public boolean inProgress() + { + return _thrown < _toThrow || !_current.isEmpty(); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemCaveIn.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemCaveIn.java new file mode 100644 index 000000000..5656844ad --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemCaveIn.java @@ -0,0 +1,336 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilShapes; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemCaveIn extends BossAbility +{ + private List _blocks = new ArrayList<>(); + private List _fallingBlocks = new ArrayList<>(); + private int _tick; + + public GolemCaveIn(GolemCreature creature) + { + super(creature); + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public Player getTarget() + { + if (getTarget(4) == null) + { + return getTarget(40); + } + + return null; + } + + @Override + public boolean hasFinished() + { + return _tick > 60 && _fallingBlocks.isEmpty(); + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + Iterator fallingIterator = _fallingBlocks.iterator(); + + while (fallingIterator.hasNext()) + { + FallingBlock cur = fallingIterator.next(); + + if (cur.isDead() || !cur.isValid() || cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + fallingIterator.remove(); + + Block block = cur.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + // Expire + if (cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + cur.remove(); + continue; + } + + cur.remove(); + continue; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) cur).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, + nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) cur.getWorld()).getHandle().getEntities(((CraftEntity) cur).getHandle(), + ((CraftEntity) cur).getHandle().getBoundingBox().a(((CraftEntity) cur).getHandle().motX, + ((CraftEntity) cur).getHandle().motY, ((CraftEntity) cur).getHandle().motZ).grow(2, 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + continue; + + // Creative or Spec + if (ent instanceof Player) + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + continue; + + // float f1 = (float)(nmsEntity.boundingBox.a() * 0.6f); + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + cur.getWorld().playEffect(victim.getEyeLocation().subtract(0, 0.5, 0), Effect.STEP_SOUND, cur.getBlockId()); + + if (canDamage(victim)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) victim, getEntity(), null, + DamageCause.CONTACT, 10 * getBoss().getDifficulty(), true, true, false, "Iron Wizard Cave In", + "Iron Wizard Cave In"); + } + + cur.remove(); + fallingIterator.remove(); + } + else if (finalObjectPosition != null) + { + Block block = cur.getWorld().getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt( + nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + cur.remove(); + fallingIterator.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + cur.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + @SuppressWarnings("deprecation") + @Override + public void setFinished() + { + for (FallingBlock block : _fallingBlocks) + { + block.remove(); + } + + for (Block block : _blocks) + { + block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getTypeId()); + block.setType(Material.AIR); + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (_tick++ == 0) + { + Location l = getLocation(); + + List blocks = UtilShapes.getSphereBlocks(l, 3, 3, true); + + for (Location loc : blocks) + { + if (loc.getBlockY() >= l.getBlockY()) + { + Block b = loc.getBlock(); + + if (b.getType() == Material.AIR) + { + _blocks.add(b); + + loc.setY(l.getY() - 1); + + b.setType(loc.getBlock().getType()); + + b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, loc.getBlock().getTypeId()); + } + } + } + } + + if (_tick % 5 == 0) + + { + for (Player player : UtilPlayer.getNearby(getLocation(), 2.5, true)) + { + player.teleport(player.getLocation().add(0, 4, 0)); + UtilAction.velocity(player, new Vector(UtilMath.r(10) - 5, 3, UtilMath.r(10) - 5).normalize()); + } + } + + if (_tick < 200) + + { + Location loc = getLocation(); + loc.setY(loc.getY() + 4); + + for (int i = 0; i < 30; i++) + { + loc.setY(loc.getY() + 1); + Block b = loc.getBlock(); + + if (UtilBlock.solid(b)) + { + break; + } + } + + if (!UtilBlock.solid(loc.getBlock())) + { + return; + } + + List players = UtilPlayer.getNearby(getLocation(), 50, true); + + for (int i = 0; i < players.size() * 2; i++) + { + int dist = UtilMath.r(10); + + if (dist < 3) + { + dist = 2; + } + else if (dist < 5) + { + dist = 5; + } + else + { + dist = 10; + } + + Location l = players.get(UtilMath.r(players.size())).getLocation().add(UtilMath.r(dist * 2) - dist, 0, + UtilMath.r(dist * 2) - dist); + l.setY(loc.getY()); + + Block b = l.getBlock(); + l.subtract(0, 1, 0); + + if (UtilBlock.solid(b)) + { + if (l.getBlock().getType() == Material.AIR) + { + if (UtilAlg.HasSight(l, getLocation().add(0, 4, 0))) + { + FallingBlock block = b.getWorld().spawnFallingBlock(b.getLocation().add(0.5, -1, 0.5), b.getTypeId(), + b.getData()); + + block.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, block.getBlockId()); + block.setDropItem(false); + + _fallingBlocks.add(block); + } + } + } + } + } + + } + + @Override + public boolean inProgress() + { + return true; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemDeadlyTremor.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemDeadlyTremor.java new file mode 100644 index 000000000..d9934e3c9 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemDeadlyTremor.java @@ -0,0 +1,89 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import org.bukkit.Effect; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.recharge.Recharge; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; + +public class GolemDeadlyTremor extends BossAbility +{ + private static final long ATTACK_DURATION = 10000; + private long _start; + + public GolemDeadlyTremor(GolemCreature creature) + { + super(creature); + _start = System.currentTimeMillis(); + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public boolean hasFinished() + { + return UtilTime.elapsed(_start, ATTACK_DURATION); + } + + @Override + public void setFinished() + { + _start = System.currentTimeMillis() - ATTACK_DURATION; + } + + @Override + public void tick() + { + for (Player player : UtilPlayer.getInRadius(getLocation(), 30).keySet()) + { + player.playSound(player.getLocation(), Sound.MINECART_BASE, 0.2f, 0.2f); + + if (UtilEnt.isGrounded(player)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getBoss().getEntity(), null, DamageCause.CUSTOM, (1 + 2 * Math.random()) * getBoss().getDifficulty(), false, false, false, getBoss().getEntity().getName(), "Deadly Tremor"); + + if (Recharge.Instance.use(player, "Deadly Tremor Hit", 400, false, false)) + { + UtilAction.velocity(player, new Vector(Math.random() - 0.5, Math.random() * 0.2, Math.random() - 0.5), + Math.random() * 1 + 1, false, 0, 0.1 + Math.random() * 0.2, 2, true); + } + } + + for (Block block : UtilBlock.getInRadius(player.getLocation(), 5).keySet()) + { + if (Math.random() < 0.98) + continue; + + if (!UtilBlock.solid(block)) + continue; + + if (!UtilBlock.airFoliage(block.getRelative(BlockFace.UP))) + continue; + + player.playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType()); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemEarthquake.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemEarthquake.java new file mode 100644 index 000000000..ae4563a0a --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemEarthquake.java @@ -0,0 +1,168 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Entity; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilServer; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; + +public class GolemEarthquake extends BossAbility +{ + private Location _center; + private float _range; + private int _tick; + private List _damaged = new ArrayList<>(); + private boolean _earthquake; + + public GolemEarthquake(GolemCreature creature) + { + super(creature); + _center = getLocation(); + } + + @Override + public boolean canMove() + { + return !UtilEnt.isGrounded(getEntity()) && _tick > 1; + } + + @Override + public Player getTarget() + { + return getTarget(7); + } + + @Override + public boolean hasFinished() + { + return _range > 19; + } + + @Override + public void setFinished() + { + } + + @Override + public void tick() + { + Entity entity = getEntity(); + + if (_tick == 0) + { + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 4, 0); + + entity.setVelocity(new Vector(0, 1, 0)); + } + else if (!_earthquake) + { + _earthquake = _tick > 10 && UtilEnt.isGrounded(entity); + } + + if (_earthquake) + { + _range += 0.7; + + for (float range = _range - 2; range <= _range; range++) + { + if (range <= 0) + { + continue; + } + + for (int x = -1; x <= 1; x++) + { + for (int z = -1; z <= 1; z++) + { + if ((x != 0) == (z != 0)) + { + continue; + } + + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.DIRT, 0), + _center.clone().add(x * range, 0.1, z * range), (x != 0) ? 0 : (range / 2), 0.1F, + (z != 0) ? 0 : (range / 2), 0, (int) (range * 4), UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + _center.getWorld().playSound(_center, Sound.DIG_STONE, 2, 0.8F); + + HashSet toDamage = new HashSet(); + + Location cornerA = _center.clone().add(-_range, -1, -_range); + Location cornerB = _center.clone().add(_range, 1, _range); + Location cornerA1 = _center.clone().add(-(_range - 1.5), -1, -(_range - 1.5)); + Location cornerB1 = _center.clone().add(_range - 1.5, 1, _range - 1.5); + + for (Player player : Bukkit.getOnlinePlayers()) + { + Location pLoc = player.getLocation(); + + if (_damaged.contains(player.getUniqueId())) + { + continue; + } + + if (!UtilAlg.inBoundingBox(pLoc, cornerA, cornerB)) + { + continue; + } + + if (UtilAlg.inBoundingBox(pLoc, cornerA1, cornerB1)) + { + continue; + } + + toDamage.add(player); + } + + for (Player player : toDamage) + { + _damaged.add(player.getUniqueId()); + + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) player, getEntity(), null, + DamageCause.CONTACT, 14 * getBoss().getDifficulty(), false, true, false, "Iron Wizard Earthquake", + "Iron Wizard Earthquake"); + + getBoss().getEvent().getCondition().Factory().Slow("Earthquake", (LivingEntity) player, getEntity(), 3, 1, false, + false, false, false); + + // Velocity + UtilAction.velocity(player, UtilAlg.getTrajectory2d(getLocation().toVector(), player.getLocation().toVector()), + 1.8, true, 0, 0.5, 0.5, true); + + // Condition + getBoss().getEvent().getCondition().Factory().Falling("Earthquake", player, getEntity(), 10, false, true); + } + } + + _tick++; + } + + @Override + public boolean inProgress() + { + return !_earthquake; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplodingAura.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplodingAura.java new file mode 100644 index 000000000..ff9fe2c67 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplodingAura.java @@ -0,0 +1,400 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.DataWatcher; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayOutAttachEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemExplodingAura extends BossAbility +{ + private Map _blocks = new HashMap<>(); + private Map _blocksLoc = new HashMap<>(); + private List _fallingBlocks = new ArrayList<>(); + private Map _blockMaterial = new HashMap<>(); + private int _tick; + + public GolemExplodingAura(GolemCreature creature) + { + super(creature); + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean hasFinished() + { + return _tick > 20 * 30 && _blocks.isEmpty() && _fallingBlocks.isEmpty(); + } + + @Override + public void setFinished() + { + for (FallingBlock block : _fallingBlocks) + { + block.remove(); + } + + int[] ids = new int[_blocks.size() * 2]; + + int i = 0; + + for (Entry id : _blocks.entrySet()) + { + ids[i] = id.getKey(); + ids[i + 1] = id.getValue(); + + i += 2; + } + + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ids); + + for (Player player : UtilServer.getPlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (_tick < 25 * 25 && getBoss().getHealth() > 30) + { + double angle = (2 * Math.PI) / UtilMath.random.nextDouble(); + double x = 1.7 * Math.cos(angle); + double z = 1.7 * Math.sin(angle); + + Location loc = getLocation().add(x, 1 + (UtilMath.random.nextDouble() * 1.6), z); + + loc.getWorld().playEffect(loc, Effect.STEP_SOUND, Material.DIRT.getId()); + + for (Player player : UtilPlayer.getNearby(getLocation(), 3, true)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getEntity(), null, DamageCause.CONTACT, + 6 * getBoss().getDifficulty(), true, true, false, "Iron Wizard Protection", "Iron Wizard Protection"); + UtilAction.velocity(player, UtilAlg.getTrajectory(getEntity(), player), 1, true, 0.3, 0, 0.3, false); + } + } + + if (_tick < 20 * 30) + { + int key = UtilEnt.getNewEntityId(); + int value = UtilEnt.getNewEntityId(); + + Location loc = null; + + for (int i = 0; i < 30; i++) + { + double angle = (2 * Math.PI) / UtilMath.random.nextDouble(); + double x = 1.7 * Math.cos(angle); + double z = 1.7 * Math.sin(angle); + + loc = getLocation().add(x, 1 + (UtilMath.random.nextDouble() * 1.6), z); + boolean found = false; + + for (Location l : _blocksLoc.values()) + { + if (l.distance(loc) < 0.3) + { + found = true; + break; + } + } + + if (found) + { + loc = null; + } + else + { + break; + } + } + + if (loc != null) + { + _blocks.put(key, value); + _blocksLoc.put(key, loc); + _blockMaterial.put(key, UtilMath.random.nextBoolean() ? Material.DIRT : Material.STONE); + + Packet[] packets = new Packet[3]; + + PacketPlayOutSpawnEntityLiving packet1 = new PacketPlayOutSpawnEntityLiving(); + + DataWatcher watcher = new DataWatcher(null); + watcher.a(0, (byte) 32, net.minecraft.server.v1_8_R3.Entity.META_ENTITYDATA, (byte) 0); + watcher.a(1, 0, net.minecraft.server.v1_8_R3.Entity.META_AIR, 0); + + packet1.a = key; + packet1.b = EntityType.SILVERFISH.getTypeId(); + packet1.c = (int) Math.floor(loc.getX() * 32); + packet1.d = (int) Math.floor((loc.getY() - 0.125) * 32); + packet1.e = (int) Math.floor(loc.getZ() * 32); + packet1.l = watcher; + + packets[0] = packet1; + + PacketPlayOutSpawnEntity packet2 = new PacketPlayOutSpawnEntity(((CraftEntity) getEntity()).getHandle(), 70, + _blockMaterial.get(key).getId()); + + packet2.a = value; + + packet2.b = (int) Math.floor(loc.getX() * 32); + packet2.c = (int) Math.floor(loc.getY() * 32); + packet2.d = (int) Math.floor(loc.getZ() * 32); + + packets[1] = packet2; + + PacketPlayOutAttachEntity packet3 = new PacketPlayOutAttachEntity(); + + packet3.b = value; + packet3.c = key; + + packets[2] = packet3; + + for (Player player : UtilPlayer.getNearby(getLocation(), 70)) + { + UtilPlayer.sendPacket(player, packets); + } + } + } + + if (_tick % 25 == 0) + { + for (int i = 0; i < 3; i++) + getLocation().getWorld().playSound(getLocation(), Sound.DIG_GRASS, 3, 2); + + for (int key : new ArrayList(_blocksLoc.keySet())) + { + + PacketPlayOutEntityDestroy destroyPacket = new PacketPlayOutEntityDestroy(new int[] + { + key, _blocks.remove(key) + }); + + for (Player player : UtilServer.getPlayers()) + { + UtilPlayer.sendPacket(player, destroyPacket); + } + + Location loc = _blocksLoc.remove(key); + + FallingBlock falling = loc.getWorld().spawnFallingBlock(loc, _blockMaterial.remove(key), (byte) 0); + + _fallingBlocks.add(falling); + + Vector vec = UtilAlg.getTrajectory(getLocation().add(0, 1, 0), loc); + + vec.setY(Math.max(0.05, vec.getY())); + + falling.setVelocity(vec); + + loc.getWorld().playEffect(loc, Effect.STEP_SOUND, Material.DIRT.getId()); + } + } + + _tick++; + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + Iterator fallingIterator = _fallingBlocks.iterator(); + + while (fallingIterator.hasNext()) + { + FallingBlock cur = fallingIterator.next(); + + if (cur.isDead() || !cur.isValid() || cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + fallingIterator.remove(); + + Block block = cur.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + // Expire + if (cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + cur.remove(); + continue; + } + + cur.remove(); + continue; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) cur).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, + nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) cur.getWorld()).getHandle().getEntities(((CraftEntity) cur).getHandle(), + ((CraftEntity) cur).getHandle().getBoundingBox().a(((CraftEntity) cur).getHandle().motX, + ((CraftEntity) cur).getHandle().motY, ((CraftEntity) cur).getHandle().motZ).grow(2, 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + { + continue; + } + + // Creative or Spec + if (ent instanceof Player) + { + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + { + continue; + } + } + + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + cur.getWorld().playEffect(victim.getEyeLocation().subtract(0, 0.5, 0), Effect.STEP_SOUND, cur.getBlockId()); + + { + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) victim, getEntity(), null, + DamageCause.CONTACT, 6 * getBoss().getDifficulty(), true, true, false, "Blocky Iron Wizard Aura", + "Blocky Iron Wizard Aura"); + } + + fallingIterator.remove(); + cur.remove(); + + Vector vec = UtilAlg.getTrajectory(getEntity(), victim); + vec.setY(0).normalize(); + + double strength = 1; + + if (!(victim instanceof Player) || !((Player) victim).isBlocking()) + { + strength = 1.3; + } + + UtilAction.velocity(victim, vec, strength, true, 0, 0.2, 1, true); + } + else if (finalObjectPosition != null) + { + Block block = cur.getWorld().getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt( + nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + fallingIterator.remove(); + cur.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + cur.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + @Override + public boolean inProgress() + { + return false; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplosiveBlock.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplosiveBlock.java new file mode 100644 index 000000000..fd76b19e0 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplosiveBlock.java @@ -0,0 +1,590 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Bukkit; +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Item; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +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.itemstack.ItemBuilder; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.DataWatcher; +import net.minecraft.server.v1_8_R3.EntityIronGolem; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayOutAttachEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemExplosiveBlock extends BossAbility +{ + private Map _blocksLocation = new HashMap<>(); + private Location _center; + private int _explosionsLeft; + private FallingBlock _fallingBlock; + private Map _fallingBlocks = new HashMap<>(); + private List _items = new ArrayList<>(); + private int _strength; + private Player _target; + private int _tick; + + public GolemExplosiveBlock(GolemCreature creature, int strength) + { + super(creature); + + _strength = strength; + _center = getLocation().add(0, 3, 0); + _target = getTarget(); + + if (_target != null) + { + UtilEnt.CreatureLook(getEntity(), _target); + } + } + + @Override + public boolean canMove() + { + return _fallingBlock != null; + } + + private int clamp(int value) + { + if (value < -127) + { + return -127; + } + + if (value > 127) + { + return 127; + } + + return value; + } + + @Override + public Player getTarget() + { + HashMap locs = new HashMap(); + + for (Player player : UtilServer.getPlayers()) + { + double dist = player.getLocation().distance(_center); + + if (dist < 30) + { + double score = (dist > 10 ? 30 - dist : 10); + + for (Player p : UtilServer.getPlayers()) + { + if (player.getLocation().distance(p.getLocation()) < 4) + { + score += 7; + } + } + + if (player.hasLineOfSight(getEntity())) + { + score += 10; + } + + locs.put(player, score); + } + } + + Player lowest = null; + + for (Entry entry : locs.entrySet()) + { + if (lowest == null || locs.get(lowest) > locs.get(entry.getKey())) + { + lowest = entry.getKey(); + } + } + + return lowest; + } + + @Override + public boolean hasFinished() + { + return _target == null || (_fallingBlock != null && !_fallingBlock.isValid() && _explosionsLeft == 0); + } + + @EventHandler + public void onDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().equals(getEntity())) + { + if (_tick >= 40 + (40 * _strength) && _tick <= 50 + (40 * _strength)) + { + event.SetCancelled("Iron Wizard charging bomb"); + } + + event.SetKnockback(false); + } + } + + public void onExplode(final Location loc) + { + for (int i = 0; i < _strength * 2; i++) + { + if (i == 0) + { + onSubExplode(loc); + } + else + { + _explosionsLeft++; + + Bukkit.getScheduler().scheduleSyncDelayedTask(UtilServer.getPlugin(), () -> + { + onSubExplode(loc); + _explosionsLeft--; + }, 2 * i); + } + } + } + + public void onSubExplode(Location loc) + { + for (int i = 0; i < 2; i++) + { + Location l = loc.clone().add(UtilMath.r(_strength * 4) - (_strength * 2), UtilMath.r(_strength * 2), + UtilMath.r(_strength * 4) - (_strength * 2)); + + UtilParticle.PlayParticle(ParticleType.LARGE_EXPLODE, l, _strength * 3, 1, _strength * 3, 0, _strength * 4, + ViewDist.LONG, UtilServer.getPlayers()); + } + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_fallingBlock == null) + { + return; + } + + if (_fallingBlock.isDead() + || !_fallingBlock.isValid() + || _fallingBlock.getTicksLived() > 400 + || !_fallingBlock.getWorld().isChunkLoaded(_fallingBlock.getLocation().getBlockX() >> 4, + _fallingBlock.getLocation().getBlockZ() >> 4)) + { + Block block = _fallingBlock.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + _fallingBlock.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, _fallingBlock.getBlockId()); + + // Expire + if (_fallingBlock.getTicksLived() > 400 + || !_fallingBlock.getWorld().isChunkLoaded(_fallingBlock.getLocation().getBlockX() >> 4, + _fallingBlock.getLocation().getBlockZ() >> 4)) + { + _fallingBlock.remove(); + return; + } + + _fallingBlock.remove(); + return; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) _fallingBlock).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) _fallingBlock.getWorld()).getHandle().getEntities( + ((CraftEntity) _fallingBlock).getHandle(), + ((CraftEntity) _fallingBlock).getHandle().getBoundingBox().a(((CraftEntity) _fallingBlock).getHandle().motX, + ((CraftEntity) _fallingBlock).getHandle().motY, ((CraftEntity) _fallingBlock).getHandle().motZ).grow(2, + 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + { + continue; + } + + // Creative or Spec + if (ent instanceof Player) + { + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + { + continue; + } + } + + // float f1 = (float)(nmsEntity.boundingBox.a() * 0.6f); + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + onExplode(victim.getEyeLocation()); + + _fallingBlock.remove(); + } + else if (finalObjectPosition != null) + { + Block block = _fallingBlock.getWorld() + .getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt(nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ + * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + onExplode(block.getLocation().add(0.5, 0.5, 0.5)); + + _fallingBlock.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + _fallingBlock.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + + @Override + public void setFinished() + { + int[] ids = new int[_fallingBlocks.size() * 2]; + + int index = 0; + + for (Entry entry : _fallingBlocks.entrySet()) + { + ids[index] = entry.getKey(); + ids[index + 1] = entry.getValue(); + index += 2; + } + + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ids); + + for (Player player : Bukkit.getOnlinePlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + + for (Item item : _items) + { + item.remove(); + } + + if (_fallingBlock != null) + { + _fallingBlock.remove(); + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + IronGolem entity = getEntity(); + + Iterator itel = _items.iterator(); + + while (itel.hasNext()) + { + Item item = itel.next(); + + Vector vec = item.getVelocity(); + Location loc = item.getLocation(); + + if (item.getTicksLived() > 100 || vec.getY() <= 0 || loc.distance(_center) > loc.add(vec).distance(_center) + || UtilEnt.isGrounded(item)) + { + itel.remove(); + } + } + + // This spawns a floating block + if (_tick >= 20 && _tick % 60 == 0 && _fallingBlocks.size() < _strength) + { + int id = UtilEnt.getNewEntityId(); + int id2 = UtilEnt.getNewEntityId(); + + _fallingBlocks.put(id, id2); + _blocksLocation.put(id, _center.toVector()); + + Packet[] packets = new Packet[3]; + + PacketPlayOutSpawnEntityLiving packet1 = new PacketPlayOutSpawnEntityLiving(); + + DataWatcher watcher = new DataWatcher(null); + watcher.a(0, (byte) 32, net.minecraft.server.v1_8_R3.Entity.META_ENTITYDATA, (byte) 0); + watcher.a(1, 0, net.minecraft.server.v1_8_R3.Entity.META_AIR, 0); + + packet1.a = id; + packet1.b = EntityType.SILVERFISH.getTypeId(); + packet1.c = (int) Math.floor(_center.getX() * 32); + packet1.d = (int) Math.floor((_center.getY() - 0.125) * 32); + packet1.e = (int) Math.floor(_center.getZ() * 32); + packet1.l = watcher; + + packets[0] = packet1; + + PacketPlayOutSpawnEntity packet2 = new PacketPlayOutSpawnEntity(((CraftEntity) entity).getHandle(), 70, + Material.DIRT.getId()); + + packet2.a = id2; + + packet2.b = (int) Math.floor(_center.getX() * 32); + packet2.c = (int) Math.floor(_center.getY() * 32); + packet2.d = (int) Math.floor(_center.getZ() * 32); + + packets[1] = packet2; + + PacketPlayOutAttachEntity packet3 = new PacketPlayOutAttachEntity(); + + packet3.b = id2; + packet3.c = id; + + packets[2] = packet3; + + for (Player player : UtilServer.getPlayers()) + { + if (player.getLocation().distance(_center) < 80) + { + UtilPlayer.sendPacket(player, packets); + } + } + } + + // This spawns a item that flies above the golem's head and disappears + if (UtilMath.r(6) == 0 && _tick < 40 + (_strength * 40)) + { + double angle = ((2 * Math.PI) / 30) * UtilMath.r(30); + double x = 5 * Math.cos(angle); + double z = 5 * Math.sin(angle); + Location loc = _center.clone().add(x, -3, z); + + Material mat = null; + + switch (UtilMath.r(3)) + { + case 0: + mat = Material.DIRT; + break; + case 1: + mat = Material.STONE; + break; + case 2: + mat = Material.COBBLESTONE; + break; + default: + break; + } + + Item item = loc.getWorld().dropItem(loc, new ItemBuilder(mat).setTitle(System.currentTimeMillis() + "").build()); + + item.setPickupDelay(999999); + + Vector vec = UtilAlg.getTrajectory(_center, item.getLocation()); + + vec.normalize().multiply(5); + + item.setVelocity(vec); + + // TODO Fix velocity + + _items.add(item); + } + + // 10 being when items no longer fly in, 0 being when its shot. + int ticksTillFired = (60 + (40 * _strength)) - _tick; + + if (ticksTillFired > 20) + { + int strength = (int) Math.floor(_tick / 20D); + + int nine = 8 - strength; + + if (_tick % nine == 0) + { + _center.getWorld().playSound(_center, Sound.DIG_GRASS, strength + 1, 1F); + } + } + else if (ticksTillFired < 0) + { + if (_tick % 3 == 0) + { + _center.getWorld().playSound(_fallingBlock.getLocation(), Sound.WOOD_CLICK, _strength + 1, 0.4F); + } + } + + // The location the falling blocks need to stick by + Vector blockCenter = _center.toVector(); + + if (ticksTillFired >= 0 && ticksTillFired <= 20) + { + Vector vec = entity.getLocation().add(entity.getLocation().getDirection().setY(0).normalize().multiply(1.2)) + .add(0, 1, 0).toVector(); + + blockCenter = UtilAlg.getTrajectory(_center.toVector(), blockCenter); + vec.multiply(ticksTillFired / 10D); + + _center.getWorld().playSound(_center, Sound.DIG_SNOW, _strength + 1, 0); + } + else if (_fallingBlock != null) + { + blockCenter = _fallingBlock.getLocation().add(0, 0.5, 0).toVector(); + } + + // Move the fake floating blocks + for (Entry entry : _fallingBlocks.entrySet()) + { + int id = entry.getKey(); + Vector vec = _blocksLocation.get(id); + + int x = clamp((int) ((blockCenter.getX() - vec.getX()) * 32) + (UtilMath.r(8) - 4)); + int y = clamp((int) ((blockCenter.getY() - vec.getY()) * 32) + (UtilMath.r(8) - 4)); + int z = clamp((int) ((blockCenter.getZ() - vec.getZ()) * 32) + (UtilMath.r(8) - 4)); + + vec.add(new Vector(x, y, z)); + + PacketPlayOutEntity.PacketPlayOutRelEntityMove packet = new PacketPlayOutEntity.PacketPlayOutRelEntityMove(); + + packet.a = id; + + packet.b = (byte) x; + packet.c = (byte) y; + packet.d = (byte) z; + + for (Player player : UtilServer.getPlayers()) + { + if (player.getLocation().distance(_center) < 70) + { + UtilPlayer.sendPacket(player, packet); + + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + vec.toLocation(_center.getWorld()), 0.7F, 0.7F, 0.7F, 0, 11, ViewDist.NORMAL, player); + } + } + } + + if (ticksTillFired == 0) + { + int id = _fallingBlocks.keySet().iterator().next(); + + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(new int[] + { + id, _fallingBlocks.get(id) + }); + + for (Player player : Bukkit.getOnlinePlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + + _fallingBlocks.remove(id); + + _fallingBlock = _center.getWorld().spawnFallingBlock(_blocksLocation.get(id).toLocation(_center.getWorld()), + Material.STONE, (byte) 0); + + Vector vec1 = _fallingBlock.getLocation().toVector(); + Vector vec2 = _target.getLocation().toVector(); + + Vector vec = UtilAlg.calculateVelocity(vec1, vec2, (int) (vec1.distanceSquared(vec2) / 4)); + + _fallingBlock.setVelocity(vec); + + EntityIronGolem golem = ((CraftIronGolem) entity).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + } + + _tick++; + } + + @Override + public boolean inProgress() + { + return false; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemIronHook.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemIronHook.java new file mode 100644 index 000000000..18c94e4cd --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemIronHook.java @@ -0,0 +1,163 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Sound; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.itemstack.ItemStackFactory; +import mineplex.core.updater.UpdateType; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; + +public class GolemIronHook extends BossAbility +{ + private static final Integer MAX_TARGETS = 3; + private boolean _shot, _complete; + + private List _hooks = new ArrayList<>(); + + public GolemIronHook(GolemCreature creature) + { + super(creature); + _shot = false; + _complete = false; + } + + private int getPosition(Player toAdd, List ordered, Map distances) + { + int position = ordered.size(); + int index = 0; + for (Player player : ordered) + { + if (distances.get(player) < distances.get(toAdd)) + { + position = index; + } + index++; + } + + return position; + } + + private void shoot() + { + IronGolem wizard = getBoss().getEntity(); + List selections = new LinkedList<>(); + List targeted = new ArrayList<>(); + + Map near = UtilPlayer.getInRadius(wizard.getLocation(), 40D); + + for (Player nearby : near.keySet()) + { + if (nearby.getGameMode() == GameMode.CREATIVE || nearby.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + + if (selections.isEmpty()) + { + selections.add(nearby); + } + else + { + selections.add(getPosition(nearby, selections, near), nearby); + } + } + + for (int i = 0; i < MAX_TARGETS; i++) + { + if (i < selections.size()) + { + targeted.add(selections.get(i)); + } + } + + if (targeted.isEmpty()) + { + _complete = true; + setFinished(); + return; + } + + for (Player target : targeted) + { + Item item = wizard.getWorld().dropItem(wizard.getEyeLocation().add(UtilAlg.getTrajectory(wizard, target)), ItemStackFactory.Instance.CreateStack(131)); + UtilAction.velocity(item, UtilAlg.getTrajectory(wizard, target).normalize(), + 2, false, 0, 0.2, 20, false); + + getBoss().getEvent().getProjectileManager().AddThrow(item, getBoss().getEntity(), new IronHook(getBoss().getEvent()), -1, true, true, true, true, + Sound.FIRE_IGNITE, 1.4f, 0.8f, ParticleType.CRIT, UpdateType.TICK, 1f); + + item.getWorld().playSound(item.getLocation(), Sound.IRONGOLEM_THROW, 2f, 0.8f); + _hooks.add(item); + } + } + + @Override + public int getCooldown() + { + return 10; + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public boolean inProgress() + { + return false; + } + + @Override + public boolean hasFinished() + { + return _complete; + } + + @Override + public void setFinished() + { + for (Item hook : _hooks) + { + if (!hook.isDead() && hook.isValid()) + { + getBoss().getEvent().getProjectileManager().deleteThrown(hook); + hook.remove(); + } + } + + _hooks.clear(); + } + + @Override + public void tick() + { + if (_shot) + { + return; + } + shoot(); + _shot = true; + Bukkit.getScheduler().runTaskLater(UtilServer.getPlugin(), () -> + { + _complete = true; + setFinished(); + }, 2 * 20); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemMeleeAttack.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemMeleeAttack.java new file mode 100644 index 000000000..a045429dc --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemMeleeAttack.java @@ -0,0 +1,90 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import org.bukkit.Sound; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.EntityIronGolem; + +public class GolemMeleeAttack extends BossAbility +{ + private boolean _attacked; + + public GolemMeleeAttack(GolemCreature creature) + { + super(creature); + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public int getCooldown() + { + return 20; + } + + @Override + public Player getTarget() + { + return getTarget(4); + } + + @Override + public boolean hasFinished() + { + return _attacked; + } + + @Override + public void setFinished() {} + + @Override + public void tick() + { + _attacked = true; + + for (Player target : UtilPlayer.getNearby(getLocation(), 4, true)) + { + if (target.getVelocity().length() > 0.5) + { + continue; + } + + UtilEnt.CreatureLook(getEntity(), target); + + getBoss().getEvent().getDamageManager().NewDamageEvent(target, getEntity(), null, DamageCause.ENTITY_ATTACK, + 10 * getBoss().getDifficulty(), false, true, false, "Iron Wizard Melee Attack", "Iron Wizard Melee Attack"); + + Vector vec = getLocation().getDirection(); + vec.setY(0).normalize().setY(0.5).multiply(2.4); + + UtilAction.velocity(target, vec); + + getBoss().getEvent().getCondition().Factory().Falling("Iron Wizard Throw", target, getEntity(), 3, false, false); + + target.getWorld().playSound(target.getLocation(), Sound.IRONGOLEM_THROW, 3, 0.9F); + + EntityIronGolem golem = ((CraftIronGolem) getEntity()).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + } + } + + @Override + public boolean inProgress() + { + return _attacked; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRumble.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRumble.java new file mode 100644 index 000000000..d9cb7cc70 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRumble.java @@ -0,0 +1,238 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.Damageable; +import org.bukkit.entity.Entity; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.EntityIronGolem; + +/** + * Rumble is where the golem picks a target then starts playing a animation for a second where its obviously preparing to use it. + * Copy this from Wizards + */ +public class GolemRumble extends BossAbility +{ + private Location _loc; + private int _ticks; + private int _travelled; + private Vector _vec; + private int _width = 1; + private Location _target; + + public GolemRumble(GolemCreature creature) + { + super(creature); + + Player target = getTarget(); + + if (target != null) + { + _target = target.getLocation(); + + UtilEnt.CreatureLook(getEntity(), _target); + } + } + + @Override + public boolean canMove() + { + return _ticks >= 20; + } + + @Override + public boolean hasFinished() + { + return _travelled > 35; + } + + @Override + public void setFinished() {} + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (_ticks++ < 14) + { + IronGolem entity = getEntity(); + EntityIronGolem golem = ((CraftIronGolem) entity).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + + if (_ticks % 2 == 0) + { + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 3, 2F); + } + } + else if (_ticks % 2 == 0) + { + int oldWidth = _width; + + if ((_width <= 3 || _ticks % 4 == 0) && _width <= 6) + { + _width++; + } + + Location newLoc; + boolean validBlock = false; + List current = new ArrayList<>(); + + if (_vec == null) + { + _vec = _target.subtract(getLocation()).toVector().setY(0).normalize(); + _loc = getLocation().subtract(0, 1, 0).getBlock().getLocation().add(0, 0.99, 0); + newLoc = _loc; + current.add(_loc.getBlock()); + + validBlock = true; + } + else + { // Move rumble + newLoc = _loc.clone().add(_vec); + + // Check if the rumble needs to go up or drop a block or two + for (int y : new int[] {0, 1, -1}) + { + for (int a = 1; a <= 2; a++) + { + Block b = newLoc.clone().add(_vec.clone().multiply(a)).getBlock().getRelative(0, y, 0); + + if (UtilBlock.solid(b) && !UtilBlock.solid(b.getRelative(0, 1, 0))) + { + validBlock = true; + newLoc.add(0, y, 0); + + break; + } + } + + if (validBlock) + { + break; + } + } + + for (int width = -_width; width <= _width; width++) + { + if (Math.abs(width) <= oldWidth) + { + Block b = _loc.clone().add(UtilAlg.getRight(_vec).multiply(width)).getBlock(); + + if (!current.contains(b)) + { + current.add(b); + } + } + + if (validBlock) + { + Block b = newLoc.clone().add(UtilAlg.getRight(_vec).multiply(width)).getBlock(); + + if (!current.contains(b)) + { + current.add(b); + + b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getTypeId()); + } + } + } + } + + UtilEnt.CreatureLook(getEntity(), _loc); + + for (Entity entity : getEntity().getWorld().getEntities()) + { + if (entity instanceof Damageable && !UtilPlayer.isSpectator(entity) && entity != getEntity()) + { + Block b = entity.getLocation().getBlock(); + boolean canDamage = false; + + for (int y = -1; y <= 0; y++) + { + if (current.contains(b.getRelative(0, y, 0))) + { + canDamage = true; + break; + } + } + + if (!canDamage) + { + continue; + } + + if (canDamage(entity)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) entity, getEntity(), null, + DamageCause.CONTACT, 8 * getBoss().getDifficulty(), false, true, false, "Iron Wizard Rumble", + "Iron Wizard Rumble"); + } + + UtilAction.velocity(entity, _vec.clone(), 1.5, true, 0, 0.2, 1, true); + + if (entity instanceof Player) + { + getBoss().getEvent().getCondition().Factory().Slow("Rumble", (LivingEntity) entity, getEntity(), 3, 1, + false, false, false, false); + } + } + } + + if (_travelled++ > 35 || !validBlock) + { + _travelled = 100; + } + + _loc = newLoc; + } + } + + public Player getTarget() + { + Player target = null; + double dist = 0; + + for (Player player : UtilPlayer.getNearby(getLocation(), 30, true)) + { + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + double d = player.getLocation().distance(getLocation()); + + if (d > 2 && (target == null || dist > d)) + { + target = player; + dist = d; + } + } + + return target; + } + + @Override + public boolean inProgress() + { + return _ticks < 14; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRupture.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRupture.java new file mode 100644 index 000000000..2ecf4c46b --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRupture.java @@ -0,0 +1,367 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Item; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.inventory.InventoryPickupItemEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import mineplex.core.common.Pair; +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +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.UtilTime; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.EntityIronGolem; + +public class GolemRupture extends BossAbility +{ + private List> _ruptures = new ArrayList<>(); + private Map _ruptureTime = new HashMap<>(); + private List _targetted = new ArrayList<>(); + private int _rupturesLeft; + private int _tick; + private List _items = new ArrayList<>(); + private int _ticksFinished; + + public GolemRupture(GolemCreature creature) + { + super(creature); + + if (creature.getHealthPercent() > 0.75) + { + _rupturesLeft = 2; + } + else if (creature.getHealthPercent() > 0.5) + { + _rupturesLeft = 5; + } + else + { + _rupturesLeft = 10; + } + } + + @Override + public boolean canMove() + { + return false; + } + + @EventHandler + public void HopperPickup(InventoryPickupItemEvent event) + { + if (_items.contains(event.getItem())) + { + event.setCancelled(true); + } + } + + @SuppressWarnings("deprecation") + @EventHandler + public void ItemDestroy(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_items.isEmpty()) + { + return; + } + + Iterator itemIterator = _items.iterator(); + + while (itemIterator.hasNext()) + { + Item item = itemIterator.next(); + + if (item.isDead() || !item.isValid()) + { + item.remove(); + itemIterator.remove(); + } + else if (UtilEnt.isGrounded(item) || item.getTicksLived() > 60) + { + item.getWorld().playEffect(item.getLocation(), Effect.STEP_SOUND, item.getItemStack().getTypeId()); + item.remove(); + itemIterator.remove(); + } + } + } + + @Override + public boolean inProgress() + { + return false; + } + + @Override + public boolean hasFinished() + { + return _rupturesLeft <= 0 && _ruptures.isEmpty() && --_ticksFinished <= 0; + } + + @Override + public void setFinished() + { + for (Item item : _items) + { + item.remove(); + } + } + + @Override + public void tick() + { + Iterator> itel = _ruptures.iterator(); + + while (itel.hasNext()) + { + Pair pair = itel.next(); + + if (pair.getLeft().distance(pair.getRight()) > 0) + { + Vector vec = pair.getRight().toVector().subtract(pair.getLeft().toVector()); + + if (vec.length() > 1) + { + vec = vec.normalize(); + } + + pair.getLeft().add(vec); + } + + if (pair.getLeft().distance(pair.getRight()) < 0.1) + { + if (!_ruptureTime.containsKey(pair.getLeft())) + { + _ruptureTime.put(pair.getLeft(), System.currentTimeMillis()); + } + else if (UtilTime.elapsed(_ruptureTime.get(pair.getLeft()), 150)) + { + itel.remove(); + + explodeRupture(pair.getLeft()); + } + } + } + + if (_tick % 10 == 0 && _rupturesLeft > 0) + { + _rupturesLeft--; + + Location loc = getLocation().add(UtilMath.random.nextFloat() - 0.5, 0, UtilMath.random.nextFloat() - 0.5); + + loc.setY(loc.getBlockY()); + + for (int y = 0; y > -3; y--) + { + if (!UtilBlock.airFoliage(loc.getBlock().getRelative(0, y, 0))) + { + loc.setY(loc.getY() + y); + break; + } + } + + Player player = getTarget(); + + if (player != null) + { + _targetted.add(player.getName()); + + Location target = player.getLocation(); + target.setY(loc.getY()); + + _ruptures.add(Pair.create(loc, target)); + + UtilEnt.CreatureLook(getEntity(), player.getLocation()); + + EntityIronGolem golem = ((CraftIronGolem) getEntity()).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + } + else + { + _rupturesLeft = 0; + } + } + + for (Pair pair : _ruptures) + { + pair.getLeft().getWorld().playSound(pair.getLeft(), Sound.DIG_GRAVEL, 2.5F, 0.9F); + + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.DIRT, 0), + pair.getLeft().clone().add(0, 1.1, 0), 1F, 0, 1F, 0, 70, ViewDist.NORMAL, UtilServer.getPlayers()); + } + } + + _tick++; + } + + @Override + public Player getTarget() + { + Player target = null; + double dist = 0; + + for (Player player : UtilPlayer.getNearby(getLocation(), 30, true)) + { + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + if (_targetted.contains(player.getName())) + { + continue; + } + + double d = player.getLocation().distance(getLocation()); + + if (d < 7) + { + continue; + } + + boolean valid = true; + + for (Pair loc : _ruptures) + { + if (loc.getRight().distance(player.getLocation()) < 1.5) + { + valid = false; + break; + } + } + + if (!valid) + { + continue; + } + + if (target == null || dist > d) + { + target = player; + dist = d; + } + } + + return target; + } + + @SuppressWarnings("deprecation") + private void explodeRupture(Location loc) + { + loc.add(0, 1.1, 0); + loc.setX(loc.getBlockX() + 0.5); + loc.setZ(loc.getBlockZ() + 0.5); + + // Fling + HashMap targets = UtilEnt.getInRadius(loc, 3.5); + for (LivingEntity cur : targets.keySet()) + { + // Velocity + UtilAction.velocity(cur, + UtilAlg.getTrajectory2d(loc.toVector().add(new Vector(0.5, 0, 0.5)), cur.getLocation().toVector()), + 0.8 + 0.8 * targets.get(cur), true, 0, 0.4 + 1.0 * targets.get(cur), 1.4, true); + + // Condition + getBoss().getEvent().getCondition().Factory().Falling("Rupture", cur, getEntity(), 10, false, true); + + // Damage Event + getBoss().getEvent().getDamageManager().NewDamageEvent(cur, getEntity(), null, DamageCause.CUSTOM, + 8 * getBoss().getDifficulty(), false, true, false, "Iron Wizard", "Rupture"); + } + + List blocks = new ArrayList<>(); + + for (int x = -3; x <= 3; x++) + { + for (int z = -3; z <= 3; z++) + { + for (int y = 0; y <= 1; y++) + { + for (int i = 0; i < 2; i++) + { + if (Math.sqrt(x * x + z * z + y * y) <= 3) + { + blocks.add(loc.clone().add(x, y, z).getBlock()); + } + } + } + } + } + + Collections.shuffle(blocks); + + // Blocks + int done = 0; + Iterator itel = blocks.iterator(); + + while (done < 30 && itel.hasNext()) + { + Block block = itel.next(); + + Vector vec = new Vector(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5).normalize(); + + if (!UtilBlock.airFoliage(block)) + { + continue; + } + + // Add Directional + vec.add(UtilAlg.getTrajectory(loc.getBlock().getLocation(), block.getLocation().add(0.5, 0, 0.5))); + + // Add Up + vec.add(new Vector(0, 1.6, 0)); + + vec.normalize(); + + // Scale + vec.multiply(0.1 + 0.3 * Math.random() + 0.6); + + // Block! + Item item = loc.getWorld().dropItem(block.getLocation().add(0.5, 0, 0.5), new ItemStack(Material.DIRT, 0)); + item.setVelocity(vec); + item.setPickupDelay(50000); + _items.add(item); + + // Effect + loc.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, Material.STONE.getId()); + + done++; + } + + _ticksFinished = 20; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSlam.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSlam.java new file mode 100644 index 000000000..c4a5a01ab --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSlam.java @@ -0,0 +1,271 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Item; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.inventory.InventoryPickupItemEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; + +public class GolemSlam extends BossAbility +{ + private List _items = new ArrayList<>(); + private int _ticksFinished; + private int _stage; + private Vector _target; + private int _ticksJumped; + + public GolemSlam(GolemCreature creature) + { + super(creature); + + Player target = getTarget(); + + if (target != null) + { + _target = UtilAlg.calculateVelocity(getLocation().toVector(), + target.getLocation().toVector().setY(getLocation().getY()), 2, getEntity()); + } + } + + @Override + public boolean canMove() + { + return !UtilEnt.isGrounded(getEntity()) && _stage == 1; + } + + @Override + public boolean hasFinished() + { + return _stage == 2 && --_ticksFinished <= 0; + } + + @Override + public void setFinished() + { + for (Item item : _items) + { + item.remove(); + } + } + + @Override + public void tick() + { + Entity entity = getEntity(); + + if (_stage == 0) + { + UtilEnt.CreatureLook(getEntity(), getLocation().add(_target)); + + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 4, 0); + + entity.setVelocity(_target); + _stage++; + } + else if (_stage == 1) + { + _ticksJumped++; + + if (_ticksJumped > 4 && getLocation().subtract(0, 0.2, 0).getBlock().getType() != Material.AIR) + { + explodeRupture(getLocation()); + + _stage = 2; + } + } + } + + @EventHandler + public void HopperPickup(InventoryPickupItemEvent event) + { + if (_items.contains(event.getItem())) + { + event.setCancelled(true); + } + } + + @SuppressWarnings("deprecation") + @EventHandler + public void ItemDestroy(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_items.isEmpty()) + { + return; + } + + Iterator itemIterator = _items.iterator(); + + while (itemIterator.hasNext()) + { + Item item = itemIterator.next(); + + if (item.isDead() || !item.isValid()) + { + item.remove(); + itemIterator.remove(); + } + else if (UtilEnt.isGrounded(item) || item.getTicksLived() > 60) + { + item.getWorld().playEffect(item.getLocation(), Effect.STEP_SOUND, item.getItemStack().getTypeId()); + item.remove(); + itemIterator.remove(); + } + } + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public Player getTarget() + { + Player target = null; + double dist = 0; + + for (Player player : UtilPlayer.getNearby(getLocation(), 30, true)) + { + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + double d = player.getLocation().distance(getLocation()); + + if (d < 10) + { + continue; + } + + if (target == null || dist > d) + { + target = player; + dist = d; + } + } + + return target; + } + + @SuppressWarnings("deprecation") + private void explodeRupture(Location loc) + { + loc.add(0, 1.1, 0); + loc.setX(loc.getBlockX() + 0.5); + loc.setZ(loc.getBlockZ() + 0.5); + + // Fling + Map targets = UtilEnt.getInRadius(loc, 3.5); + for (LivingEntity cur : targets.keySet()) + { + if (cur.equals(getEntity())) + { + continue; + } + + // Velocity + UtilAction.velocity(cur, + UtilAlg.getTrajectory2d(loc.toVector().add(new Vector(0.5, 0, 0.5)), cur.getLocation().toVector()), + 0.8 + 0.8 * targets.get(cur), true, 0, 0.4 + 1.0 * targets.get(cur), 1.4, true); + + // Condition + getBoss().getEvent().getCondition().Factory().Falling("Rupture", cur, getEntity(), 10, false, true); + + // Damage Event + getBoss().getEvent().getDamageManager().NewDamageEvent(cur, getEntity(), null, DamageCause.CUSTOM, + 8 * getBoss().getDifficulty(), false, true, false, "Iron Wizard", "Rupture"); + } + + List blocks = new ArrayList(); + + for (int x = -3; x <= 3; x++) + { + for (int z = -3; z <= 3; z++) + { + for (int y = 0; y <= 1; y++) + { + for (int i = 0; i < 2; i++) + { + if (Math.sqrt(x * x + z * z + y * y) <= 3) + { + blocks.add(loc.clone().add(x, y, z).getBlock()); + } + } + } + } + } + + Collections.shuffle(blocks); + + // Blocks + int done = 0; + Iterator itel = blocks.iterator(); + + while (done < 30 && itel.hasNext()) + { + Block block = itel.next(); + + Vector vec = new Vector(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5).normalize(); + + if (!UtilBlock.airFoliage(block)) + continue; + + // Add Directional + vec.add(UtilAlg.getTrajectory(loc.getBlock().getLocation(), block.getLocation().add(0.5, 0, 0.5))); + + // Add Up + vec.add(new Vector(0, 1.6, 0)); + + vec.normalize(); + + // Scale + vec.multiply(0.1 + 0.3 * Math.random() + 0.6); + + // Block! + Item item = loc.getWorld().dropItem(block.getLocation().add(0.5, 0, 0.5), new ItemStack(Material.DIRT, 0)); + item.setVelocity(vec); + item.setPickupDelay(50000); + _items.add(item); + + // Effect + loc.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, Material.DIRT.getId()); + + done++; + } + + _ticksFinished = 20; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSpike.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSpike.java new file mode 100644 index 000000000..4f5dad106 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSpike.java @@ -0,0 +1,104 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.bukkit.Sound; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; + +public class GolemSpike extends BossAbility +{ + private static final int SPIKE_HEIGHT = 2; + private static final long ATTACK_DURATION = 1000 + (500 * SPIKE_HEIGHT * 2); + private static final long SPIKE_REMAIN = 1000; + private long _start; + private List _spikes; + + public GolemSpike(GolemCreature creature) + { + super(creature); + _start = System.currentTimeMillis(); + _spikes = new ArrayList<>(); + } + + @Override + public int getCooldown() + { + return 15; + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public boolean hasFinished() + { + return UtilTime.elapsed(_start, ATTACK_DURATION) && _spikes.isEmpty(); + } + + @Override + public void setFinished() + { + _start = System.currentTimeMillis() - ATTACK_DURATION; + for (GroundSpike spike : _spikes) + { + spike.finish(); + } + _spikes.clear(); + } + + @Override + public void tick() + { + if (_spikes.isEmpty()) + { + for (Player player : UtilPlayer.getInRadius(getLocation(), 20).keySet()) + { + if (UtilEnt.isGrounded(player)) + { + player.playSound(player.getLocation(), Sound.STEP_STONE, 0.2f, 0.2f); + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getBoss().getEntity(), null, DamageCause.CUSTOM, 5 * getBoss().getDifficulty(), false, false, false, getBoss().getEntity().getName(), "Stone Spike"); + player.teleport(player.getLocation().add(0, SPIKE_HEIGHT, 0)); + UtilAction.velocity(player, player.getLocation().toVector().normalize().add(new Vector(0, 0.02, 0)).normalize()); + _spikes.add(new GroundSpike(player.getLocation().getBlock(), player.getLocation().getBlock().getRelative(0, -1, 0).getType(), new Random().nextInt(SPIKE_HEIGHT) + 2, SPIKE_REMAIN)); + } + } + } + else + { + List toRemove = new ArrayList<>(); + for (GroundSpike spike : _spikes) + { + spike.tick(); + if (spike.isFinished()) + { + toRemove.add(spike); + } + } + for (GroundSpike remove : toRemove) + { + _spikes.remove(remove); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemWallExplode.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemWallExplode.java new file mode 100644 index 000000000..aaebec6d4 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemWallExplode.java @@ -0,0 +1,419 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilShapes; +import mineplex.core.common.util.UtilTime; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemWallExplode extends BossAbility +{ + private Map> _blockWalls = new HashMap<>(); + private List _dontTarget = new ArrayList<>(); + private List _fallingBlocks = new ArrayList<>(); + private int _maxTimes = UtilMath.r(2) + 1; + private int _tick; + private int _timesDone; + private Map _wallTimers = new HashMap<>(); + + public GolemWallExplode(GolemCreature creature) + { + super(creature); + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public int getCooldown() + { + return 20; + } + + private float getMod(int div) + { + return UtilMath.random.nextFloat() / div; + } + + @Override + public Player getTarget() + { + for (Player player : UtilPlayer.getNearby(getLocation(), 15, true)) + { + if (_dontTarget.contains(player.getName())) + { + continue; + } + + if (player.getLocation().distance(getLocation()) <= 4) + { + continue; + } + + return player; + } + + return null; + } + + @Override + public boolean hasFinished() + { + return _wallTimers.isEmpty() && _fallingBlocks.isEmpty() && _timesDone >= _maxTimes; + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + Iterator fallingIterator = _fallingBlocks.iterator(); + + while (fallingIterator.hasNext()) + { + FallingBlock cur = fallingIterator.next(); + + if (cur.isDead() || !cur.isValid() || cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + fallingIterator.remove(); + + Block block = cur.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + // Expire + if (cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + cur.remove(); + continue; + } + + cur.remove(); + continue; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) cur).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, + nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) cur.getWorld()).getHandle().getEntities(((CraftEntity) cur).getHandle(), + ((CraftEntity) cur).getHandle().getBoundingBox().a(((CraftEntity) cur).getHandle().motX, + ((CraftEntity) cur).getHandle().motY, ((CraftEntity) cur).getHandle().motZ).grow(2, 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + continue; + + // Creative or Spec + if (ent instanceof Player) + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + continue; + + // float f1 = (float)(nmsEntity.boundingBox.a() * 0.6f); + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + cur.getWorld().playEffect(victim.getEyeLocation().subtract(0, 0.5, 0), Effect.STEP_SOUND, cur.getBlockId()); + + if (canDamage(victim)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) victim, getEntity(), null, + DamageCause.CONTACT, 10 * getBoss().getDifficulty(), true, true, false, "Iron Wizard Wall Explosion", + "Iron Wizard Wall Explosion"); + } + + cur.remove(); + fallingIterator.remove(); + + Vector vec = cur.getVelocity(); + + UtilAction.velocity(victim, vec, 1.5, true, 0, 0.2, 1, true); + } + else if (finalObjectPosition != null) + { + Block block = cur.getWorld().getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt( + nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + cur.remove(); + fallingIterator.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + cur.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + @Override + public void setFinished() + { + for (FallingBlock block : _fallingBlocks) + { + block.remove(); + } + + for (List list : _blockWalls.values()) + { + for (Block b : list) + { + b.setType(Material.AIR); + } + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (_tick++ % 30 == 0 && _timesDone < _maxTimes) + { + _dontTarget.clear(); + + _timesDone++; + + for (int i = 0; i < 10; i++) + { + Player target = getTarget(); + + if (target == null) + { + if (_dontTarget.isEmpty()) + { + _timesDone = _maxTimes; + } + } + else + { + _dontTarget.add(target.getName()); + + UtilEnt.CreatureLook(getEntity(), target); + + BlockFace face = UtilShapes.getFacing(getLocation().getYaw()); + + if (_wallTimers.containsKey(face)) + { + continue; + } + + ArrayList blocks = new ArrayList(); + + Location loc = getLocation().getBlock().getLocation().add(0.5, 0, 0.5); + + int mul = (face.getModX() != 0 && face.getModZ() != 0) ? 2 : 3; + + loc.add(face.getModX() * mul, 0, face.getModZ() * mul); + + Block b = loc.getBlock(); + + BlockFace sideFace = UtilShapes.getSideBlockFaces(face, true)[0]; + boolean invalid = false; + + for (int mult = -3; mult <= 3; mult++) + { + Block block = b; + + if (Math.abs(mult) < 3) + { + block = block.getRelative(face); + } + + block = block.getRelative(sideFace, mult); + + if (Math.abs(mult) == 3 && face.getModX() != 0 && face.getModZ() != 0) + { + block = block.getRelative(UtilShapes.getSideBlockFaces(face, false)[mult < 0 ? 0 : 1]); + } + + if (!UtilAlg.HasSight(getLocation(), block.getLocation())) + { + invalid = true; + break; + } + + Block under = block.getRelative(0, -1, 0); + + if (!UtilBlock.solid(under)) + { + continue; + } + + for (int y = 0; y <= 1; y++) + { + block = block.getRelative(0, y, 0); + + if (block.getType() != Material.AIR) + { + invalid = true; + break; + } + + blocks.add(block); + } + + if (invalid) + { + break; + } + } + + if (invalid) + { + continue; + } + + for (Block block : blocks) + { + block.setType(block.getWorld().getBlockAt(block.getX(), b.getY() - 1, block.getZ()).getType()); + block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getTypeId()); + } + + _blockWalls.put(face, blocks); + _wallTimers.put(face, System.currentTimeMillis()); + break; + } + } + } + + Iterator>> itel = _blockWalls.entrySet().iterator(); + boolean doExplode = false; + + while (itel.hasNext()) + { + Entry> entry = itel.next(); + BlockFace face = entry.getKey(); + + if (UtilTime.elapsed(_wallTimers.get(face), 1000)) + { + doExplode = true; + itel.remove(); + _wallTimers.remove(face); + + for (Block b : entry.getValue()) + { + FallingBlock block = getEntity().getWorld().spawnFallingBlock(b.getLocation().add(0.5, 0, 0.5), b.getType(), + (byte) 0); + + block.setDropItem(false); + + int index = entry.getValue().indexOf(b); + + BlockFace f = index == 8 || index == 9 ? BlockFace.SELF + : UtilShapes.getSideBlockFaces(face, true)[index > 6 ? 0 : 1]; + + block.setVelocity(new Vector((face.getModX() * 0.6) + (f.getModX() * (0.05 + getMod(10))), 0.2 + getMod(15), + (face.getModZ() * 0.6) + (f.getModZ() * (0.05 + getMod(10))))); + + _fallingBlocks.add(block); + + b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getTypeId()); + b.setType(Material.AIR); + } + } + } + + if (doExplode) + { + onUpdate(new UpdateEvent(UpdateType.TICK)); + } + } + + @Override + public boolean inProgress() + { + return false; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GroundSpike.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GroundSpike.java new file mode 100644 index 000000000..40d2989e3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GroundSpike.java @@ -0,0 +1,122 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.LinkedList; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; + +public class GroundSpike +{ + private Block _initial; + private Material _type; + private int _max, _height; + private long _lastTick, _remain; + private LinkedList _blocks; + private boolean _shrinking, _finished; + + public GroundSpike(Block first, Material type, int maxHeight, long remainDuration) + { + _initial = first; + _type = type; + _height = 0; + _max = maxHeight; + _remain = remainDuration; + _lastTick = System.currentTimeMillis(); + _blocks = new LinkedList<>(); + _shrinking = false; + _finished = false; + } + + @SuppressWarnings("deprecation") + private void raise() + { + if ((_height + 1) < _max) + { + _lastTick = System.currentTimeMillis(); + Block b = _initial.getRelative(0, _height, 0); + for (Player player : UtilServer.getPlayers()) + { + player.sendBlockChange(b.getLocation(), _type, (byte)0); + } + _blocks.add(b); + _height++; + } + else + { + if (UtilTime.elapsed(_lastTick, _remain)) + { + _shrinking = true; + lower(); + } + } + } + + @SuppressWarnings("deprecation") + private void lower() + { + _height = Math.min(_blocks.size() - 1, _height); + if ((_height - 1) >= 0) + { + _lastTick = System.currentTimeMillis(); + for (Player player : UtilServer.getPlayers()) + { + player.sendBlockChange(_blocks.get(_height).getLocation(), Material.AIR, (byte)0); + } + _blocks.remove(_height); + _height--; + } + else + { + finish(); + } + } + + public boolean isFinished() + { + if (!_blocks.isEmpty()) + { + return false; + } + + return _finished; + } + + @SuppressWarnings("deprecation") + public void finish() + { + _finished = true; + for (Block block : _blocks) + { + for (Player player : UtilServer.getPlayers()) + { + player.sendBlockChange(block.getLocation(), Material.AIR, (byte)0); + } + } + _blocks.clear(); + } + + public void tick() + { + if (isFinished()) + { + return; + } + if (!UtilTime.elapsed(_lastTick, 500)) + { + return; + } + + if (_shrinking) + { + lower(); + } + else + { + raise(); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/IronHook.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/IronHook.java new file mode 100644 index 000000000..73ddfce16 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/IronHook.java @@ -0,0 +1,54 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import org.bukkit.block.Block; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.projectile.IThrown; +import mineplex.core.projectile.ProjectileUser; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; + +public class IronHook implements IThrown +{ + private WorldEvent _host; + + public IronHook(WorldEvent event) + { + _host = event; + } + + @Override + public void Collide(LivingEntity target, Block block, ProjectileUser data) + { + data.getThrown().remove(); + + if (!(data.getThrower() instanceof IronGolem)) + return; + + IronGolem wizard = (IronGolem)data.getThrower(); + + if (target == null) + return; + + UtilAction.velocity(target, UtilAlg.getTrajectory(target.getLocation(), wizard.getLocation()), 5, false, 0, 0.7, 1.2, true); + + _host.getCondition().Factory().Falling("Iron Hook", target, wizard, 10, false, true); + + _host.getDamageManager().NewDamageEvent(target, wizard, null, DamageCause.CUSTOM, 5, false, true, false, wizard.getName(), "Iron Hook"); + } + + @Override + public void Idle(ProjectileUser data) + { + data.getThrown().remove(); + } + + @Override + public void Expire(ProjectileUser data) + { + data.getThrown().remove(); + } +} \ No newline at end of file