From 1cdf9d2bba858c51839ae39938433e6f9cc8501f Mon Sep 17 00:00:00 2001 From: AlexTheCoder Date: Thu, 15 Jun 2017 23:10:16 -0400 Subject: [PATCH] Final season 3 world event tweaks (adds skeleton king) --- .../clans/worldevent/WorldEventManager.java | 36 +- .../clans/worldevent/WorldEventType.java | 66 +-- .../boss/BossArenaLocationFinder.java | 24 +- .../clans/worldevent/boss/BossWorldEvent.java | 23 +- .../worldevent/boss/ironwizard/GolemBoss.java | 5 +- .../boss/ironwizard/GolemCreature.java | 7 +- .../boss/skeletonking/SkeletonBoss.java | 64 +++ .../boss/skeletonking/SkeletonCreature.java | 482 ++++++++++++++++++ .../abilities/SkeletonArcherShield.java | 187 +++++++ .../abilities/SkeletonHellishFlood.java | 119 +++++ .../abilities/SkeletonPassive.java | 120 +++++ .../skeletonking/abilities/SkeletonPulse.java | 108 ++++ .../skeletonking/abilities/SkeletonSmite.java | 104 ++++ .../abilities/SkeletonStrike.java | 167 ++++++ .../abilities/SkeletonWraithSummon.java | 231 +++++++++ .../boss/skeletonking/minion/MinionType.java | 34 ++ .../minion/UndeadArcherCreature.java | 234 +++++++++ .../minion/UndeadWarriorCreature.java | 186 +++++++ .../skeletonking/minion/WraithCreature.java | 190 +++++++ .../worldevent/command/WorldEventCommand.java | 2 +- .../clans/worldevent/raid/RaidAltar.java | 4 +- .../clans/worldevent/raid/RaidManager.java | 12 + .../clans/worldevent/raid/RaidWorldEvent.java | 1 + .../worldevent/raid/wither/WitherRaid.java | 2 +- .../challenge/seven/ChallengeSeven.java | 14 + .../raid/wither/creature/magma/HeatingUp.java | 5 +- .../raid/wither/creature/magma/Magmus.java | 1 + .../creature/magma/MagmusCataclysm.java | 17 +- .../raid/wither/creature/magma/MagmusEat.java | 3 +- .../wither/creature/magma/MagmusMeteor.java | 9 +- .../wither/creature/magma/MagmusSmash.java | 2 +- 31 files changed, 2375 insertions(+), 84 deletions(-) create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonBoss.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonCreature.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonArcherShield.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonHellishFlood.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPassive.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPulse.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonSmite.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonStrike.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonWraithSummon.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/MinionType.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadArcherCreature.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadWarriorCreature.java create mode 100644 Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/WraithCreature.java diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventManager.java index b235e1ba3..032d86c2f 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventManager.java @@ -156,19 +156,25 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement private WorldEventType tryStartEvent() { WorldEventType[] types = WorldEventType.values(); - WorldEventType type = types[_random.nextInt(types.length)]; - Location location = _terrainFinder.findAreaInBorderlands(false); - if (location != null) + if (types.length == 0) { - initializeEvent(type.createInstance(this, location, _skillFactory)); - return type; + return null; } else { - // Try again in 5 minutes - _nextEventStart = System.currentTimeMillis() + (5 * 60 * 1000); + WorldEventType type = types[_random.nextInt(types.length)]; + //Location location = _terrainFinder.findAreaInBorderlands(false); + //if (location != null) + { + initializeEvent(type.createInstance(this)); + return type; + } + //else + //{ + // Try again in 5 minutes + //_nextEventStart = System.currentTimeMillis() + (5 * 60 * 1000); + //} } - return null; } private void initializeEvent(WorldEvent event) @@ -181,13 +187,17 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement event.start(); _runningEvents.add(event); } - - public WorldEvent startEventFromName(Location location, String name) + + public WorldEvent startEventFromName(String name) { WorldEventType eventType = WorldEventType.valueOf(name); if (eventType != null) { - WorldEvent event = eventType.createInstance(this, location, _skillFactory); + WorldEvent event = eventType.createInstance(this); + if (event == null) + { + return null; + } initializeEvent(event); return event; } @@ -199,8 +209,8 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement { if (eventType != null) { - Location location = _terrainFinder.findAreaInBorderlands(true); - WorldEvent event = eventType.createInstance(this, location, _skillFactory); + //Location location = _terrainFinder.findAreaInBorderlands(true); + WorldEvent event = eventType.createInstance(this); if (event != null) { initializeEvent(event); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventType.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventType.java index 6ada84c5e..2580c7a9e 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventType.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventType.java @@ -1,11 +1,8 @@ package mineplex.game.clans.clans.worldevent; -import java.lang.reflect.Constructor; - -import org.bukkit.Location; - import mineplex.game.clans.clans.worldevent.api.WorldEvent; -import mineplex.minecraft.game.classcombat.Skill.SkillFactory; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemBoss; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonBoss; public enum WorldEventType { @@ -15,58 +12,34 @@ public enum WorldEventType //IRON_WIZARD("Iron Wizard", GolemBoss.class, 30), //BROOD_MOTHER("Brood Mother", SpiderBoss.class, 30), //SKELETON_KING("Skeleton King", SkeletonBoss.class, 30) + IRON_WIZARD("Iron Wizard", GolemBoss.class, (man) -> + { + return new GolemBoss(man); + }), + SKELETON_KING("Skeleton King", SkeletonBoss.class, (man) -> + { + return new SkeletonBoss(man); + }) ; private String _name; private Class _clazz; - private int _areaNeeded; + private EventCreator _creator; - WorldEventType(String name, Class clazz, int areaNeeded) + WorldEventType(String name, Class clazz, EventCreator creator) { _name = name; _clazz = clazz; - _areaNeeded = areaNeeded; + _creator = creator; } - public int getAreaNeeded() - { - return _areaNeeded; - } - - public WorldEvent createInstance(WorldEventManager eventManager, Location centerLocation, SkillFactory skillFactory) + public WorldEvent createInstance(WorldEventManager eventManager) { WorldEvent worldEvent = null; - try + if (_creator != null) { - for (Constructor con : _clazz.getConstructors()) - { - Class[] classes = con.getParameterTypes(); - - if (classes[0] == WorldEventManager.class) - { - if (classes.length == 3) - { - worldEvent = (WorldEvent) con.newInstance(eventManager, centerLocation, skillFactory); - } - else - { - worldEvent = (WorldEvent) con.newInstance(eventManager, centerLocation); - } - } - else if (classes.length == 4) - { - worldEvent = (WorldEvent) con.newInstance(eventManager.getDamage(), eventManager.getBlockRestore(), eventManager.getClans().getCondition(), centerLocation); - } - else - { - worldEvent = (WorldEvent) con.newInstance(eventManager.getDisguiseManager(), eventManager.getDamage(), eventManager.getBlockRestore(), eventManager.getClans().getCondition(), eventManager.getClans().getProjectile(), centerLocation); - } - } - } - catch (Exception e) - { - e.printStackTrace(); + worldEvent = _creator.createEvent(eventManager); } return worldEvent; @@ -74,6 +47,11 @@ public enum WorldEventType public String getName() { - return this._name; + return _name; + } + + private static interface EventCreator + { + WorldEvent createEvent(WorldEventManager manager); } } \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossArenaLocationFinder.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossArenaLocationFinder.java index 2ed0146e7..a4c6bbc62 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossArenaLocationFinder.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossArenaLocationFinder.java @@ -20,7 +20,7 @@ public class BossArenaLocationFinder public Location getIronWizardCenter() { - return new Location(_world, 0, 0, 0); + return new Location(_world, 1057, 63, -77); } public Pair, List> getIronWizardPads() @@ -28,12 +28,22 @@ public class BossArenaLocationFinder List in = new ArrayList<>(); List out = new ArrayList<>(); + in.add(new Vector(1006, 62, -77)); + in.add(new Vector(1057, 62, -26)); + in.add(new Vector(1108, 62, -77)); + in.add(new Vector(1057, 62, -128)); + + out.add(new Vector(1035, 63, -77)); + out.add(new Vector(1057, 63, -99)); + out.add(new Vector(1079, 63, -77)); + out.add(new Vector(1057, 63, -55)); + return Pair.create(in, out); } public Location getSkeletonKingCenter() { - return new Location(_world, 0, 0, 0); + return new Location(_world, -1043, 58, 159); } public Pair, List> getSkeletonKingPads() @@ -41,6 +51,16 @@ public class BossArenaLocationFinder List in = new ArrayList<>(); List out = new ArrayList<>(); + in.add(new Vector(-1094, 57, 159)); + in.add(new Vector(-1043, 57, 210)); + in.add(new Vector(-992, 57, 159)); + in.add(new Vector(-1043, 57, 108)); + + out.add(new Vector(-1021, 58, 159)); + out.add(new Vector(-1043, 58, 137)); + out.add(new Vector(-1065, 58, 159)); + out.add(new Vector(-1043, 58, 181)); + return Pair.create(in, out); } } \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossWorldEvent.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossWorldEvent.java index dd34361c2..2d872d9f0 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossWorldEvent.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossWorldEvent.java @@ -5,14 +5,18 @@ import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.util.Vector; import mineplex.core.blockrestore.BlockRestore; +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilMath; import mineplex.core.common.util.UtilPlayer; import mineplex.core.common.util.UtilServer; import mineplex.core.disguise.DisguiseManager; +import mineplex.core.itemstack.ItemBuilder; import mineplex.core.projectile.ProjectileManager; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; @@ -21,6 +25,8 @@ import mineplex.game.clans.clans.worldevent.api.EventCreature; import mineplex.game.clans.clans.worldevent.api.EventCreatureDeathEvent; import mineplex.game.clans.clans.worldevent.api.EventState; import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.minecraft.game.classcombat.Skill.ISkill; +import mineplex.minecraft.game.classcombat.Skill.Assassin.Recall; import mineplex.minecraft.game.core.condition.ConditionManager; import mineplex.minecraft.game.core.damage.DamageManager; @@ -38,7 +44,7 @@ public abstract class BossWorldEvent> extends WorldEv super(name, centerLocation, radius, true, disguiseManager, projectileManager, damageManager, blockRestore, conditionManager); _teleportFrom = teleportFrom.stream().map(vec -> vec.toLocation(centerLocation.getWorld())).collect(Collectors.toList()); - _teleportTo = teleportFrom.stream().map(vec -> vec.toLocation(centerLocation.getWorld())).collect(Collectors.toList()); + _teleportTo = teleportTo.stream().map(vec -> vec.toLocation(centerLocation.getWorld())).collect(Collectors.toList()); } public abstract String getDeathMessage(); @@ -72,7 +78,14 @@ public abstract class BossWorldEvent> extends WorldEv { for (Player player : UtilPlayer.getInRadius(from, TELEPORT_PAD_RANGE).keySet()) { - player.teleport(_teleportTo.get(getRandom().nextInt(_teleportTo.size()))); + player.teleport(UtilMath.randomElement(_teleportTo)); + for (ISkill skill : ClansManager.getInstance().getClassManager().Get(player).GetSkills()) + { + if (skill instanceof Recall) + { + ((Recall)skill).Reset(player); + } + } sendMessage(player, "You have teleported inside the arena!"); } } @@ -89,7 +102,11 @@ public abstract class BossWorldEvent> extends WorldEv { Location drop = event.getCreature().getLastKnownLocation(); UtilServer.CallEvent(new BossDeathEvent(this, drop)); - ClansManager.getInstance().runSyncLater(() -> ClansManager.getInstance().getLootManager().dropRare(drop), DELAY_TILL_DROP_REWARD); + ClansManager.getInstance().runSyncLater(() -> + { + ClansManager.getInstance().getLootManager().dropRare(drop); + drop.getWorld().dropItem(drop, new ItemBuilder(Material.IRON_INGOT).setTitle(C.cDRedB + "Old Silver Token").setLore(C.cRed + "This token pulses with an evil aura.").setGlow(true).build()); + }, DELAY_TILL_DROP_REWARD); Bukkit.broadcastMessage(getDeathMessage()); } } 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 index cf729c0ea..2d79eea2d 100644 --- 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 @@ -11,7 +11,7 @@ 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()); + super("Iron Wizard", manager.getBossArenaLocationFinder().getIronWizardCenter(), 50, manager.getBossArenaLocationFinder().getIronWizardPads().getLeft(), manager.getBossArenaLocationFinder().getIronWizardPads().getRight(), manager.getDisguiseManager(), manager.getClans().getProjectile(), manager.getClans().getDamageManager(), manager.getBlockRestore(), manager.getClans().getCondition()); } @Override @@ -19,7 +19,6 @@ public class GolemBoss extends BossWorldEvent { Bukkit.broadcastMessage(F.main(getName(), "The mighty " + getName() + " challenges you to face him!")); spawnGolem(getCenterLocation()); - announceStart(); } @Override @@ -30,7 +29,7 @@ public class GolemBoss extends BossWorldEvent private GolemCreature spawnGolem(Location location) { - GolemCreature golemCreature = new GolemCreature(this, location, 3000); + GolemCreature golemCreature = new GolemCreature(this, location); registerCreature(golemCreature); setBossCreature(golemCreature); return golemCreature; 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 index 540c7cea0..216ede265 100644 --- 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 @@ -59,7 +59,7 @@ public class GolemCreature extends EventCreature private Vector _afkWalk = new Vector(); private long _lastSlam; - public GolemCreature(GolemBoss boss, Location location, double maxHealth) + public GolemCreature(GolemBoss boss, Location location) { super(boss, location, "Iron Wizard", true, 3000, 30, true, IronGolem.class); @@ -146,7 +146,10 @@ public class GolemCreature extends EventCreature _lastAbility = 20; HandlerList.unregisterAll(ability); - System.out.print("Unregistered golem ability " + ability.getClass().getSimpleName()); + if (DEBUG_MODE) + { + System.out.print("Unregistered golem ability " + ability.getClass().getSimpleName()); + } } else if (!ability.inProgress()) { diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonBoss.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonBoss.java new file mode 100644 index 000000000..5c633262b --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonBoss.java @@ -0,0 +1,64 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking; + +import org.bukkit.Bukkit; +import org.bukkit.Location; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilServer; +import mineplex.game.clans.clans.worldevent.WorldEventManager; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.boss.BossWorldEvent; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.MinionType; + +public class SkeletonBoss extends BossWorldEvent +{ + protected boolean canMove = false; + + public SkeletonBoss(WorldEventManager manager) + { + super("Skeleton King", manager.getBossArenaLocationFinder().getIronWizardCenter(), 50, 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 evils of the world have manifested in the form of the " + getName() + "! Become the champion of Light and destroy him!")); + spawnNecromancer(getCenterLocation()); + Bukkit.getScheduler().runTaskLater(UtilServer.getPlugin(), () -> + { + canMove = true; + }, 20 * 3); + } + + public EventCreature spawnMinion(MinionType type, Location location) + { + EventCreature minionCreature = type.getNewInstance(this, location); + if (minionCreature != null) + { + registerCreature(minionCreature); + } + return minionCreature; + } + + private SkeletonCreature spawnNecromancer(Location location) + { + SkeletonCreature necromancerCreature = new SkeletonCreature(this, location); + registerCreature(necromancerCreature); + return necromancerCreature; + } + + @Override + public String getDeathMessage() + { + return F.main(getName(), "The demonic " + getName() + " has been slain!"); + } + + @Override + protected void customTick() {} + + @Override + public void customCleanup(boolean onDisable) {} + + @Override + protected void customStop() {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonCreature.java new file mode 100644 index 000000000..be6ae17e4 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonCreature.java @@ -0,0 +1,482 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.entity.Skeleton.SkeletonType; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.inventory.ItemStack; +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.skeletonking.abilities.SkeletonArcherShield; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities.SkeletonPassive; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities.SkeletonPulse; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities.SkeletonSmite; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities.SkeletonStrike; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities.SkeletonWraithSummon; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.UndeadArcherCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.UndeadWarriorCreature; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class SkeletonCreature extends EventCreature +{ + private List> _currentAbilities = new ArrayList<>(); + private SkeletonPassive _passive; + private int _lastAbility; + private Map, Long> _cooldowns = new HashMap<>(); + private LinkedList _wraithTriggers = new LinkedList<>(); + private List _movePoints = new ArrayList<>(); + private Location _movingTo; + private boolean _moving; + private long _lastMoved; + private long _lastUsedPassive; + public List Archers = new ArrayList<>(); + public List Warriors = new ArrayList<>(); + + public SkeletonCreature(SkeletonBoss boss, Location location) + { + super(boss, location, "Skeleton King", true, 2500, 30, true, Skeleton.class); + + spawnEntity(); + _passive = new SkeletonPassive(this); + _wraithTriggers.add(1500D); + _wraithTriggers.add(1000D); + _wraithTriggers.add(500D); + _wraithTriggers.add(100D); + getEntity().getWorld().setThunderDuration(10000000); + getEntity().getWorld().setThundering(true); + } + + @Override + protected void spawnCustom() + { + UtilEnt.vegetate(getEntity()); + getEntity().setSkeletonType(SkeletonType.WITHER); + getEntity().getEquipment().setItemInHand(new ItemStack(Material.RECORD_6)); //Meridian Scepter + getEntity().getEquipment().setItemInHandDropChance(0.f); + } + + @Override + public void dieCustom() + { + HandlerList.unregisterAll(_passive); + _passive = null; + endAbility(); + getEntity().getWorld().setThunderDuration(0); + getEntity().getWorld().setThundering(false); + } + + private void endAbility() + { + for (BossAbility ability : _currentAbilities) + { + ability.setFinished(); + HandlerList.unregisterAll(ability); + } + + _currentAbilities.clear(); + } + + @EventHandler + public void onTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_passive != null && ((SkeletonBoss)getEvent()).canMove) + { + if (UtilTime.elapsed(_lastUsedPassive, _passive.getCooldown() * 20) || _passive.isProgressing()) + { + _lastUsedPassive = System.currentTimeMillis(); + _passive.tick(); + } + } + + 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;// _currentAbility.getCooldown(); + + HandlerList.unregisterAll(ability); + if (DEBUG_MODE) + { + System.out.print("Unregistered necromancer ability " + ability.getClass().getSimpleName()); + } + + _cooldowns.put(ability.getClass(), System.currentTimeMillis() + (ability.getCooldown() * 1000)); + } + else if (ability.inProgress()) + { + canDoNew = false; + _lastAbility = 20;// _currentAbility.getCooldown(); + } + } + + 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()) + { + {// Pulse & Strike + List players = getPlayers(dist, UtilMath.r(10) == 0 ? 25 : 20); + List near = getPlayers(dist, 5); + + if (!players.isEmpty()) + { + if (!near.isEmpty() && near.size() >= 4 && new Random().nextDouble() <= .45) + { + weight.put(SkeletonPulse.class, 999); + } + else + { + weight.put(SkeletonStrike.class, 6); + } + } + } + {// Smite + List players = getPlayers(dist, 15); + + if (!players.isEmpty()) + { + weight.put(SkeletonSmite.class, 6); + } + } + {//Archer Shield + List players = getPlayers(dist, 20); + double score = 0; + for (Player player : players) + { + score += (18 - dist.get(player)) / 2; + } + if (players.size() >= 4) + { + score += 17; + } + if (score > 0) + { + weight.put(SkeletonArcherShield.class, (int) Math.ceil(score)); + } + } + Double wraithUse = null; + for (Double test : _wraithTriggers) + { + if (wraithUse == null) + { + if (getHealth() <= test) + { + wraithUse = test; + break; + } + } + } + if (wraithUse != null) + {// Wraith Summon + _wraithTriggers.remove(wraithUse); + weight.clear(); + weight.put(SkeletonWraithSummon.class, 999); + } + } + + for (BossAbility ability : _currentAbilities) + { + weight.remove(ability.getClass()); + } + + for (Class c : _cooldowns.keySet()) + { + if (_cooldowns.get(c) > System.currentTimeMillis()) + { + weight.remove(c); + } + } + + if (_moving) + { + Iterator>> trying = weight.keySet().iterator(); + while (trying.hasNext()) + { + Class> abilityClass = trying.next(); + + try + { + BossAbility ability = abilityClass.newInstance(); + if (!ability.canMove()) + { + trying.remove(); + } + } + catch (Exception e) {} + } + } + + BossAbility ability = null; + + if (!weight.isEmpty()) + { + int i = 0; + + for (Integer entry : weight.values()) + { + i += entry; + } + + loop: 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(SkeletonCreature.class).newInstance(this); + + if (ability.getTarget() == null || ability.hasFinished()) + { + ability = null; + } + else + { + break loop; + } + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + break; + } + } + } + } + + if (ability != null && ability.getTarget() != null) + { + + Bukkit.getPluginManager().registerEvents(ability, UtilServer.getPlugin()); + + if (DEBUG_MODE) + { + System.out.print("Necromancer is using " + ability.getClass().getSimpleName()); + } + + _currentAbilities.add(ability); + } + + _lastAbility = 10; + } + + for (BossAbility ability : _currentAbilities) + { + try + { + ability.tick(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + boolean canMove = true; + for (BossAbility ability : _currentAbilities) + { + if (!ability.canMove()) + { + canMove = false; + } + } + if (!((SkeletonBoss)getEvent()).canMove) + { + return; + } + + if (_moving) + { + if (_movingTo == null) + { + _movingTo = selectWalkTarget(); + } + if (UtilMath.offset(getEntity().getLocation(), _movingTo) <= 1.3) + { + _lastMoved = System.currentTimeMillis(); + _movingTo = null; + _moving = false; + return; + } + UtilEnt.LookAt(getEntity(), _movingTo); + Vector walk = UtilAlg.getTrajectory(getEntity().getLocation(), _movingTo); + walk.multiply(walk.length()); + walk.multiply(.2); + getEntity().setVelocity(walk); + } + else + { + if (!UtilTime.elapsed(_lastMoved, 7000) || !canMove) + { + return; + } + _movingTo = selectWalkTarget(); + _moving = true; + } + } + + private Location selectWalkTarget() + { + if (_movePoints.isEmpty()) + { + Location base = getSpawnLocation().clone(); + base.setY(getEntity().getLocation().getY()); + generateWalkPoints(base); + } + Location selected = _movePoints.get(new Random().nextInt(_movePoints.size())); + _movePoints.remove(selected); + + return selected; + } + + private void generateWalkPoints(Location base) + { + _movePoints.add(base.clone().add(5 + UtilMath.random(1, 3), 0, 5 + UtilMath.random(1, 3))); + _movePoints.add(base.clone().add(-5 + UtilMath.random(1, 3), 0, 5 + UtilMath.random(1, 3))); + _movePoints.add(base.clone().add(5 + UtilMath.random(1, 3), 0, -5 + UtilMath.random(1, 3))); + _movePoints.add(base.clone().add(-5 + UtilMath.random(1, 3), 0, -5 + UtilMath.random(1, 3))); + } + + private List getPlayers(Map map, double maxDist) + { + return getPlayers(map, 0, maxDist); + } + + private List getPlayers(final Map map, double minDist, double maxDist) + { + List list = new ArrayList<>(); + + for (Player p : map.keySet()) + { + if (map.get(p) >= minDist && 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 onSkeletonDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + event.SetKnockback(false); + } + } + + @EventHandler + public void noFallDamage(CustomDamageEvent event) + { + if (getEntity() == null) + { + return; + } + + if (event.GetDamageeEntity().getEntityId() != getEntity().getEntityId()) + { + return; + } + + DamageCause cause = event.GetCause(); + + if (cause == DamageCause.FALL) + { + event.SetCancelled("Boss Invulnerability"); + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void protect(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damagee)) + { + if (!(damager instanceof Player)) + { + event.SetCancelled("Allied Attacker"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonArcherShield.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonArcherShield.java new file mode 100644 index 000000000..c4eadb5d4 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonArcherShield.java @@ -0,0 +1,187 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftSkeleton; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +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.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.UndeadArcherCreature; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class SkeletonArcherShield extends BossAbility +{ + private static long ATTACK_DURATION = 10000; + private static long ARROW_DELAY = 100; + private static long ARROW_WARMUP = 2000; + private static double PULL_RANGE = 12; + private long _start; + private long _lastShoot; + private boolean _teleported; + + public SkeletonArcherShield(SkeletonCreature creature) + { + super(creature); + _start = System.currentTimeMillis(); + } + + @Override + public int getCooldown() + { + return 20; + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean inProgress() + { + return false; + } + + @Override + public boolean hasFinished() + { + return UtilTime.elapsed(_start, ATTACK_DURATION); + } + + @Override + public void setFinished() + { + _start = System.currentTimeMillis() - ATTACK_DURATION; + for (UndeadArcherCreature creature : getBoss().Archers) + { + creature.getEntity().remove(); + } + } + + private void run(boolean initial) + { + for (int i = 0; i < getBoss().Archers.size(); i++) + { + Skeleton archer = getBoss().Archers.get(i).getEntity(); + UtilEnt.vegetate(archer); + ((CraftSkeleton)archer).setVegetated(false); + + double lead = i * ((2d * Math.PI)/getBoss().Archers.size()); + + double sizeMod = 2; + + //Orbit + double speed = 10d; + double oX = -Math.sin(getEntity().getTicksLived()/speed + lead) * 2 * sizeMod; + double oY = 0; + double oZ = Math.cos(getEntity().getTicksLived()/speed + lead) * 2 * sizeMod; + + if (initial) + { + archer.teleport(getEntity().getLocation().add(oX, oY, oZ)); + UtilEnt.vegetate(archer); + } + else + { + Location to = getEntity().getLocation().add(oX, oY, oZ); + UtilEnt.LookAt(archer, to); + UtilAction.velocity(archer, UtilAlg.getTrajectory(archer.getLocation(), to), 0.4, false, 0, 0.1, 1, true); + } + } + } + + private void shoot() + { + if (UtilTime.elapsed(_start, ARROW_WARMUP) && UtilTime.elapsed(_lastShoot, ARROW_DELAY)) + { + _lastShoot = System.currentTimeMillis(); + for (UndeadArcherCreature archer : getBoss().Archers) + { + Location spawn = archer.getEntity().getEyeLocation().add(UtilAlg.getTrajectory(getEntity().getEyeLocation(), archer.getEntity().getEyeLocation()).normalize()); + Vector vector = UtilAlg.getTrajectory(getEntity().getEyeLocation(), spawn); + Arrow arrow = archer.getEntity().getWorld().spawnArrow(spawn, vector, 0.6f, 12f); + arrow.setMetadata("SHIELD_SHOT", new FixedMetadataValue(UtilServer.getPlugin(), true)); + arrow.setMetadata("BARBED_ARROW", new FixedMetadataValue(UtilServer.getPlugin(), 10)); + arrow.setShooter(archer.getEntity()); + } + } + } + + @Override + public void tick() + { + if (!_teleported) + { + run(true); + _teleported = true; + for (Player near : UtilPlayer.getInRadius(getEntity().getLocation(), PULL_RANGE).keySet()) + { + Vector velocity = UtilAlg.getTrajectory(near, getEntity()); + UtilAction.velocity(near, velocity, 2, false, 0, 0, 1, true); + near.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 5 * 20, -2)); + for (int i = 0; i < 6; i++) + { + Vector random = new Vector(Math.random() * 4 - 2, Math.random() * 4 - 2, Math.random() * 4 - 2); + + Location origin = getEntity().getLocation().add(0, 1.3, 0); + origin.add(velocity.clone().multiply(10)); + origin.add(random); + + Vector vel = UtilAlg.getTrajectory(origin, getEntity().getLocation().add(0, 1.3, 0)); + vel.multiply(7); + + UtilParticle.PlayParticleToAll(ParticleType.MAGIC_CRIT, origin, (float)vel.getX(), (float)vel.getY(), (float)vel.getZ(), 1, 0, ViewDist.LONG); + } + } + } + else + { + run(false); + shoot(); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().equals(getBoss().getEntity())) + { + if (!hasFinished()) + { + event.SetCancelled("Wraiths Alive"); + } + } + } + + @EventHandler + public void onArrowHit(ProjectileHitEvent event) + { + if (event.getEntity().hasMetadata("SHIELD_SHOT")) + { + Bukkit.getScheduler().runTaskLater(UtilServer.getPlugin(), () -> + { + event.getEntity().remove(); + }, 20L); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonHellishFlood.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonHellishFlood.java new file mode 100644 index 000000000..794e75ada --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonHellishFlood.java @@ -0,0 +1,119 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import org.bukkit.Location; +import org.bukkit.entity.Skeleton; + +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.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonBoss; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.MinionType; + +public class SkeletonHellishFlood extends BossAbility +{ + private static final int WAVE_COUNT = 3; + private static final int WAVE_SIZE = 5; + private static final MinionType[] POSSIBLE_MINIONS = new MinionType[] {MinionType.WARRIOR, MinionType.ARCHER}; + private static final long WAVE_DELAY = 1000; + + private Map _waves = new HashMap<>(); + private long _lastSpawned; + private int _current; + private int _ticks; + + public SkeletonHellishFlood(SkeletonCreature creature) + { + super(creature); + + if (WAVE_COUNT > 0) + { + for (int i = 1; i <= WAVE_COUNT; i++) + { + createWave(i); + } + } + _lastSpawned = System.currentTimeMillis(); + _current = 1; + } + + private void createWave(int number) + { + int length = POSSIBLE_MINIONS.length; + if (length <= 0 || WAVE_SIZE <= 0) + { + return; + } + MinionType[] wave = new MinionType[WAVE_SIZE]; + for (int i = 0; i < WAVE_SIZE; i++) + { + wave[i] = POSSIBLE_MINIONS[new Random().nextInt(length)]; + } + _waves.put("Wave " + number, wave); + } + + @Override + public int getCooldown() + { + return 30; + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public boolean hasFinished() + { + return _waves.isEmpty() && _ticks > ((WAVE_DELAY / 1000) * 20 * (WAVE_COUNT - 1)); + } + + @Override + public void setFinished() + { + _waves.clear(); + _ticks = 60; + } + + @Override + public void tick() + { + _ticks++; + if (UtilTime.elapsed(_lastSpawned, WAVE_DELAY)) + { + if (_current <= WAVE_COUNT) + { + for (MinionType type : _waves.get("Wave " + _current)) + { + Location toSpawn = getLocation().clone(); + toSpawn.add(UtilMath.random(3, 6), 0, UtilMath.random(3, 6)); + + ((SkeletonBoss)getBoss().getEvent()).spawnMinion(type, toSpawn); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, toSpawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, toSpawn, null, 0, 2, ViewDist.MAX); + } + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + _waves.remove("Wave " + _current); + _current++; + _lastSpawned = System.currentTimeMillis(); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPassive.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPassive.java new file mode 100644 index 000000000..20c542b2c --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPassive.java @@ -0,0 +1,120 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.EventHandler; + +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.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.api.EventCreatureDeathEvent; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonBoss; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.MinionType; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.UndeadArcherCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.UndeadWarriorCreature; + +public class SkeletonPassive extends BossPassive +{ + private static final int MAX_ARCHERS = 10; + private static final int MAX_WARRIORS = 8; + private static final long SPAWN_RATE = 5000; + private List _queuedArchers = new ArrayList<>(); + private List _queuedWarriors = new ArrayList<>(); + private long _lastASpawned; + private long _lastWSpawned; + + public SkeletonPassive(SkeletonCreature creature) + { + super(creature); + } + + @Override + public int getCooldown() + { + return 20; + } + + @Override + public boolean isProgressing() + { + return !_queuedArchers.isEmpty() || !_queuedWarriors.isEmpty(); + } + + @Override + public void tick() + { + if (getBoss().Archers.size() < MAX_ARCHERS && _queuedArchers.isEmpty()) + { + for (int i = 0; i < (MAX_ARCHERS - getBoss().Archers.size()); i++) + { + Location spawn = getLocation().clone(); + spawn.add(UtilMath.random(3, 6), 0, UtilMath.random(3, 6)); + _queuedArchers.add(spawn); + } + } + if (getBoss().Warriors.size() < MAX_WARRIORS && _queuedWarriors.isEmpty()) + { + for (int i = 0; i < (MAX_WARRIORS - getBoss().Warriors.size()); i++) + { + Location spawn = getLocation().clone(); + spawn.add(UtilMath.random(3, 6), 0, UtilMath.random(3, 6)); + _queuedWarriors.add(spawn); + } + } + + for (Location animate : _queuedArchers) + { + UtilParticle.PlayParticleToAll(ParticleType.BLOCK_DUST.getParticle(Material.DIRT, 0), + animate.clone().add(0, 0.2, 0), null, 0, 4, ViewDist.NORMAL); + } + for (Location animate : _queuedWarriors) + { + UtilParticle.PlayParticleToAll(ParticleType.BLOCK_DUST.getParticle(Material.DIRT, 0), + animate.clone().add(0, 0.2, 0), null, 0, 4, ViewDist.NORMAL); + } + + if (!_queuedArchers.isEmpty() && UtilTime.elapsed(_lastASpawned, SPAWN_RATE)) + { + _lastASpawned = System.currentTimeMillis(); + Location spawn = _queuedArchers.remove(0); + getBoss().Archers.add((UndeadArcherCreature) ((SkeletonBoss)getBoss().getEvent()).spawnMinion(MinionType.ARCHER, spawn)); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, spawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, spawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + } + if (!_queuedWarriors.isEmpty() && UtilTime.elapsed(_lastWSpawned, SPAWN_RATE)) + { + _lastWSpawned = System.currentTimeMillis(); + Location spawn = _queuedWarriors.remove(0); + getBoss().Warriors.add((UndeadWarriorCreature) ((SkeletonBoss)getBoss().getEvent()).spawnMinion(MinionType.WARRIOR, spawn)); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, spawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, spawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + } + } + + @EventHandler + public void onArcherDeath(EventCreatureDeathEvent event) + { + if (event.getCreature() instanceof UndeadArcherCreature) + { + getBoss().Archers.remove(event.getCreature()); + } + if (event.getCreature() instanceof UndeadWarriorCreature) + { + getBoss().Warriors.remove(event.getCreature()); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPulse.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPulse.java new file mode 100644 index 000000000..db28e1493 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPulse.java @@ -0,0 +1,108 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +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.UtilTime; +import mineplex.core.recharge.Recharge; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; + +public class SkeletonPulse extends BossAbility +{ + private static final long TOTAL_ATTACK_DURATION = 8000; + private static final long TOTAL_ATTACK_PROGRESS = 3000; + private long _start, _lastIncrement; + private int _radius; + private Location _center; + + public SkeletonPulse(SkeletonCreature creature) + { + super(creature); + _start = System.currentTimeMillis(); + _radius = 2; + _lastIncrement = System.currentTimeMillis(); + _center = creature.getEntity().getLocation(); + } + + private int getRadius() + { + return Math.min(8, _radius); + } + + @Override + public int getCooldown() + { + return 7; + } + + @Override + public boolean canMove() + { + return UtilTime.elapsed(_start, TOTAL_ATTACK_PROGRESS); + } + + @Override + public boolean inProgress() + { + return UtilTime.elapsed(_start, TOTAL_ATTACK_PROGRESS); + } + + @Override + public boolean hasFinished() + { + return UtilTime.elapsed(_start, TOTAL_ATTACK_DURATION); + } + + @Override + public void setFinished() + { + _start = System.currentTimeMillis() - TOTAL_ATTACK_DURATION; + } + + @Override + public void tick() + { + if (UtilTime.elapsed(_lastIncrement, 500)) + { + _lastIncrement = System.currentTimeMillis(); + _radius++; + } + + for (double token = 0; token <= (2 * Math.PI); token += .2) + { + double x = getRadius() * Math.cos(token); + double z = getRadius() * Math.sin(token); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, _center.clone().add(x, 1.5, z), null, 0, 1, ViewDist.MAX); + } + + for (Player player : UtilPlayer.getInRadius(getEntity().getLocation(), getRadius()).keySet()) + { + if (player.isDead() || !player.isValid() || !player.isOnline()) + { + continue; + } + if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + if (!Recharge.Instance.use(player, "Pulse Knockback", 400, false, false, false)) + { + continue; + } + + player.playSound(player.getLocation(), Sound.AMBIENCE_THUNDER, 1f, 1f); + UtilAction.velocity(player, UtilAlg.getTrajectory2d(getEntity(), player), 2, false, 0.6, 0, 1.4, true); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonSmite.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonSmite.java new file mode 100644 index 000000000..fc1a23de3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonSmite.java @@ -0,0 +1,104 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import java.math.BigDecimal; + +import org.bukkit.GameMode; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +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.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; + +public class SkeletonSmite extends BossAbility +{ + private static final long TOTAL_ATTACK_DURATION = 8000; + private long _start; + private int _ticks; + private boolean _shot; + + public SkeletonSmite(SkeletonCreature creature) + { + super(creature); + _start = System.currentTimeMillis(); + _ticks = 0; + _shot = false; + } + + @Override + public int getCooldown() + { + return 15; + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public boolean hasFinished() + { + return UtilTime.elapsed(_start, TOTAL_ATTACK_DURATION) && _shot; + } + + @Override + public void setFinished() + { + _start = System.currentTimeMillis() - TOTAL_ATTACK_DURATION; + _shot = true; + } + + @Override + public void tick() + { + if (_shot) + return; + + if (_ticks < (6 * 20)) + { + _ticks++; + double maxHeight = Math.min(_ticks / 20, 6); + int radius = Math.max(6 - (new BigDecimal(_ticks).divide(new BigDecimal(20)).intValue()), 0); + + for (double y = 0; y < maxHeight; y += 0.5) + { + double cos = radius * Math.cos(y); + double sin = radius * Math.sin(y); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation().add(cos, y, sin), null, 0, 1, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation().add(sin, y, cos), null, 0, 1, ViewDist.MAX); + } + } + else + { + _shot = true; + for (Player player : UtilPlayer.getInRadius(getEntity().getLocation(), 15).keySet()) + { + if (player.isDead() || !player.isValid() || !player.isOnline()) + { + continue; + } + if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + + player.getWorld().strikeLightningEffect(player.getLocation()); + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getEntity(), null, DamageCause.LIGHTNING, 15 * getBoss().getDifficulty(), false, true, false, getEntity().getName(), "Lightning Strike"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonStrike.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonStrike.java new file mode 100644 index 000000000..b8588d0b5 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonStrike.java @@ -0,0 +1,167 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +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.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; + +public class SkeletonStrike extends BossAbility +{ + private static final double MAX_RANGE = 25; + private static final Integer MAX_TARGETS = 1; + private boolean _shot; + + public SkeletonStrike(SkeletonCreature creature) + { + super(creature); + _shot = false; + } + + private int getPosition(Player toAdd, LinkedList ordered) + { + int position = ordered.size(); + int index = 0; + for (Player player : ordered) + { + if (player.getHealth() < toAdd.getHealth()) + { + position = index; + return position; + } + index++; + } + + return position; + } + + private List getTargets() + { + Skeleton necromancer = getBoss().getEntity(); + LinkedList selections = new LinkedList<>(); + List targeted = new ArrayList<>(); + + Map near = UtilPlayer.getInRadius(necromancer.getLocation(), MAX_RANGE); + + for (Player nearby : near.keySet()) + { + if (nearby.getGameMode() == GameMode.CREATIVE || nearby.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + + if (selections.isEmpty()) + { + selections.addFirst(nearby); + } + else + { + selections.add(getPosition(nearby, selections), nearby); + } + } + + for (int i = 0; i < MAX_TARGETS; i++) + { + if (i < selections.size()) + { + targeted.add(selections.get(i)); + } + } + + return targeted; + } + + private void shootAt(Player target) + { + double curRange = 0; + boolean canHit = false; + + while (curRange <= MAX_RANGE) + { + Location newTarget = getEntity().getEyeLocation().add(UtilAlg.getTrajectory(getEntity(), target).multiply(curRange)); + + if (!UtilBlock.airFoliage(newTarget.getBlock())) + { + canHit = false; + break; + } + if (UtilMath.offset(newTarget, target.getLocation()) <= 0.9) + { + canHit = true; + break; + } + + curRange += 0.2; + + UtilParticle.PlayParticle(ParticleType.WITCH_MAGIC, newTarget, 0, 0, 0, 0, 1, + ViewDist.MAX, UtilServer.getPlayers()); + + canHit = true; + } + + if (canHit) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(target, getEntity(), null, DamageCause.CUSTOM, 12 * getBoss().getDifficulty(), true, true, false, getEntity().getName(), "Mystical Energy"); + } + } + + @Override + public int getCooldown() + { + return 15; + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public boolean inProgress() + { + return false; + } + + @Override + public boolean hasFinished() + { + return _shot; + } + + @Override + public void setFinished() + { + _shot = true; + } + + @Override + public void tick() + { + if (_shot) + return; + + _shot = true; + + for (Player target : getTargets()) + { + shootAt(target); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonWraithSummon.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonWraithSummon.java new file mode 100644 index 000000000..a8a8a33b3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonWraithSummon.java @@ -0,0 +1,231 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +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.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.api.EventCreatureDeathEvent; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonBoss; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.MinionType; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.WraithCreature; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class SkeletonWraithSummon extends BossAbility +{ + private static final int WRAITH_AMOUNT = 4; + private static final double DISTANCE_FROM_KING = 4; + private static final double FINAL_SKELETON_HEALTH = 100; + private static final double FINAL_WRAITH_MULTIPLIER = 2; + private final int WRAITH_AMOUNT_THIS_USE; + + private Map _wraiths = new HashMap<>(); + private Location[] _spawns; + private int _ticks; + + public SkeletonWraithSummon(SkeletonCreature creature) + { + super(creature); + + _spawns = new Location[] + { + getEntity().getLocation().add(DISTANCE_FROM_KING, 0, DISTANCE_FROM_KING), + getEntity().getLocation().add(DISTANCE_FROM_KING * -1, 0, DISTANCE_FROM_KING), + getEntity().getLocation().add(DISTANCE_FROM_KING, 0, DISTANCE_FROM_KING * -1), + getEntity().getLocation().add(DISTANCE_FROM_KING * -1, 0, DISTANCE_FROM_KING * -1), + getEntity().getLocation().add(DISTANCE_FROM_KING / 2, 0, DISTANCE_FROM_KING / 2), + getEntity().getLocation().add((DISTANCE_FROM_KING / 2) * -1, 0, DISTANCE_FROM_KING / 2), + getEntity().getLocation().add(DISTANCE_FROM_KING / 2, 0, (DISTANCE_FROM_KING / 2) * -1), + getEntity().getLocation().add((DISTANCE_FROM_KING / 2) * -1, 0, (DISTANCE_FROM_KING / 2) * -1) + }; + + if (creature.getHealth() <= FINAL_SKELETON_HEALTH) + { + WRAITH_AMOUNT_THIS_USE = (int)(WRAITH_AMOUNT * FINAL_WRAITH_MULTIPLIER); + } + else + { + WRAITH_AMOUNT_THIS_USE = WRAITH_AMOUNT; + } + } + + private String getNumberString(Integer number) + { + String num = number.toString(); + char last = num.toCharArray()[num.length() - 1]; + + String formatted = number.toString(); + String ending = ""; + + if (last == '1' && !num.equals("1" + last)) + { + ending = "st"; + } + if (last == '2' && !num.equals("1" + last)) + { + ending = "nd"; + } + if (last == '3' && !num.equals("1" + last)) + { + ending = "rd"; + } + if (ending.equals("")) + { + ending = "th"; + } + + return formatted + ending; + } + + private void spawnWraith(Location loc, int number) + { + WraithCreature wraith = (WraithCreature)((SkeletonBoss)getBoss().getEvent()).spawnMinion(MinionType.WRAITH, loc); + _wraiths.put(wraith, getNumberString(number)); + } + + @Override + public int getCooldown() + { + return 0; + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public boolean hasFinished() + { + return _wraiths.isEmpty() && _ticks > 40; + } + + @Override + public void setFinished() + { + for (WraithCreature wraith : _wraiths.keySet()) + { + wraith.remove(); + } + _wraiths.clear(); + _ticks = 41; + } + + @Override + public void tick() + { + if (_ticks == 0) + { + if (WRAITH_AMOUNT > 0) + { + for (int i = 0; i < WRAITH_AMOUNT_THIS_USE; i++) + { + int spawnIndex = i; + if (spawnIndex >= _spawns.length) + { + spawnIndex = spawnIndex % _spawns.length; + } + spawnWraith(_spawns[spawnIndex], i + 1); + } + + for (Player player : UtilPlayer.getInRadius(getEntity().getLocation(), 80).keySet()) + { + if (player.isDead() || !player.isValid() || !player.isOnline()) + { + continue; + } + if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + + player.sendMessage(F.main(getBoss().getEvent().getName(), "You must slay all " + WRAITH_AMOUNT_THIS_USE + " wraiths before continuing to fight the " + getBoss().getEvent().getName() + "!")); + } + } + } + _ticks++; + if (!hasFinished()) + { + int ticks = 10; + int hticks = 40; + boolean up = getEntity().getTicksLived() % (hticks * 2) < hticks; + int tick = getEntity().getTicksLived() % ticks; + double htick = getEntity().getTicksLived() % hticks; + int splits = 4; + + Location loc = getEntity().getLocation().add(0, 2, 0); + + for (double d = tick * (Math.PI * 2 / splits) / ticks; d < Math.PI * 2; d += Math.PI * 2 / splits) + { + Vector v = new Vector(Math.sin(d), 0, Math.cos(d)); + v.normalize().multiply(Math.max(0.2, Math.sin((htick / hticks) * Math.PI) * 1.0)); + v.setY((htick / hticks) * -2); + if (up) v.setY(-2 + 2 * (htick / hticks)); + + Location lloc = loc.clone().add(v); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, lloc, null, 0f, 2, ViewDist.MAX); + } + } + } + + @EventHandler + public void onWraithDie(EventCreatureDeathEvent event) + { + if (event.getCreature() instanceof WraithCreature) + { + String number = _wraiths.remove(event.getCreature()); + if (number != null) + { + double remainPercent = new BigDecimal(_wraiths.size()).divide(new BigDecimal(WRAITH_AMOUNT_THIS_USE)).doubleValue(); + ChatColor remainColor = ChatColor.GREEN; + if (remainPercent < .66) + { + remainColor = ChatColor.YELLOW; + } + if (remainPercent < .33) + { + remainColor = ChatColor.RED; + } + Bukkit.broadcastMessage(F.main(getBoss().getEvent().getName(), "A wraith has been slain!" + " (" + remainColor + _wraiths.size() + "/" + WRAITH_AMOUNT_THIS_USE + C.cGray + ") wraiths remaining!")); + System.out.println(F.main(getBoss().getEvent().getName(), "The " + number + " wraith has been slain!")); + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().equals(getBoss().getEntity())) + { + if (!hasFinished()) + { + event.SetCancelled("Wraiths Alive"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/MinionType.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/MinionType.java new file mode 100644 index 000000000..8d2f779ca --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/MinionType.java @@ -0,0 +1,34 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.minion; + +import org.bukkit.Location; + +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; + +public enum MinionType +{ + WARRIOR(UndeadWarriorCreature.class), + ARCHER(UndeadArcherCreature.class), + WRAITH(WraithCreature.class); + + private Class> _code; + + private MinionType(Class> code) + { + _code = code; + } + + public EventCreature getNewInstance(WorldEvent event, Location spawn) + { + try + { + return _code.getConstructor(WorldEvent.class, Location.class).newInstance(event, spawn); + } + catch (Exception e) + { + e.printStackTrace(); + } + + return null; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadArcherCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadArcherCreature.java new file mode 100644 index 000000000..625b96c0d --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadArcherCreature.java @@ -0,0 +1,234 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.minion; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.EntityTargetLivingEntityEvent; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilServer; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class UndeadArcherCreature extends EventCreature +{ + private static final int BARBED_LEVEL = 1; + private static final int LIFETIME = -1; + + public UndeadArcherCreature(WorldEvent event, Location spawnLocation) + { + super(event, spawnLocation, "Undead Archer", true, 25, 30, true, Skeleton.class); + + spawnEntity(); + } + + @Override + protected void spawnCustom() + { + Skeleton entity = getEntity(); + EntityEquipment eq = entity.getEquipment(); + eq.setItemInHand(new ItemStack(Material.BOW)); + eq.setHelmet(new ItemStack(Material.CHAINMAIL_HELMET)); + eq.setChestplate(new ItemStack(Material.CHAINMAIL_CHESTPLATE)); + eq.setLeggings(new ItemStack(Material.CHAINMAIL_LEGGINGS)); + eq.setBoots(new ItemStack(Material.CHAINMAIL_BOOTS)); + eq.setItemInHandDropChance(0.f); + eq.setHelmetDropChance(0.f); + eq.setChestplateDropChance(0.f); + eq.setLeggingsDropChance(0.f); + eq.setBootsDropChance(0.f); + entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 999999, 0)); + } + + @Override + public void dieCustom() + { + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + return; + } + + if (Math.random() > 0.97) + { + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_HELMET)); + } + + if (Math.random() > 0.97) + { + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_CHESTPLATE)); + } + + if (Math.random() > 0.97) + { + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_LEGGINGS)); + } + + if (Math.random() > 0.97) + { + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_BOOTS)); + } + + if (Math.random() > 0.90) + { + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.BOW)); + } + + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.ARROW, UtilMath.r(12) + 1)); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void bowShoot(EntityShootBowEvent event) + { + if (BARBED_LEVEL == 0) + { + return; + } + + if (!(event.getProjectile() instanceof Arrow)) + { + return; + } + + if (event.getEntity().getEntityId() != getEntity().getEntityId()) + { + return; + } + + event.getProjectile().setMetadata("BARBED_ARROW", new FixedMetadataValue(UtilServer.getPlugin(), 2)); + } + + @EventHandler(priority = EventPriority.HIGH) + public void damage(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + if (event.GetCause() != DamageCause.PROJECTILE) + { + return; + } + + Projectile projectile = event.GetProjectile(); + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(true); + + if (projectile == null) + { + return; + } + + if (!projectile.hasMetadata("BARBED_ARROW")) + { + return; + } + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (!getEntity().equals(damager)) + { + return; + } + + // Level + if (BARBED_LEVEL == 0) + { + return; + } + + Player damageePlayer = event.GetDamageePlayer(); + + if (damageePlayer != null) + { + damageePlayer.setSprinting(false); + } + + // Damage + event.AddMod(damager.getName(), "Barbed Arrows", projectile.getMetadata("BARBED_ARROW").get(0).asDouble(), false); + + // Condition + getEvent().getCondition().Factory().Slow("Barbed Arrows", damagee, damager, (projectile.getVelocity().length() / 3) * (2 + BARBED_LEVEL), 0, false, true, true, true); + } + + @EventHandler + public void clean(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + { + return; + } + + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + remove(); + return; + } + } + + @EventHandler + public void onTarget(EntityTargetLivingEntityEvent event) + { + if (getEntity().equals(event.getEntity())) + { + if (!(event.getTarget() instanceof Player)) + { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void protect(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damagee)) + { + if (!(damager instanceof Player)) + { + event.SetCancelled("Allied Attacker"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadWarriorCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadWarriorCreature.java new file mode 100644 index 000000000..607a2c234 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadWarriorCreature.java @@ -0,0 +1,186 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.minion; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityTargetLivingEntityEvent; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilMath; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class UndeadWarriorCreature extends EventCreature +{ + private static final int LIFETIME = -1; + + public UndeadWarriorCreature(WorldEvent event, Location spawnLocation) + { + super(event, spawnLocation, "Undead Warrior", true, 30, 30, true, Zombie.class); + spawnEntity(); + } + + @Override + protected void spawnCustom() + { + Zombie entity = getEntity(); + EntityEquipment eq = entity.getEquipment(); + eq.setHelmet(new ItemStack(Material.IRON_HELMET)); + eq.setChestplate(new ItemStack(Material.IRON_CHESTPLATE)); + eq.setLeggings(new ItemStack(Material.IRON_LEGGINGS)); + eq.setBoots(new ItemStack(Material.IRON_BOOTS)); + eq.setItemInHand(new ItemStack(Material.STONE_SWORD)); + eq.setHelmetDropChance(0.f); + eq.setChestplateDropChance(0.f); + eq.setLeggingsDropChance(0.f); + eq.setBootsDropChance(0.f); + eq.setItemInHandDropChance(0.f); + entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 999999, 0)); + } + + @Override + public void dieCustom() + { + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + return; + } + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_HELMET)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_CHESTPLATE)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_LEGGINGS)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_BOOTS)); + } + + @EventHandler + public void leap(UpdateEvent event) + { + if (getEntity() == null) + return; + + if (event.getType() != UpdateType.FAST) + return; + + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + remove(); + return; + } + + if (Math.random() < 0.9) + return; + + Zombie zombie = getEntity(); + + if (zombie.getTarget() == null) + return; + + double dist = UtilMath.offset(zombie.getTarget(), zombie); + + if (dist <= 3 || dist > 16) + return; + + + double power = 0.8 + (1.2 * ((dist-3)/13d)); + + //Leap + UtilAction.velocity(zombie, UtilAlg.getTrajectory(zombie, zombie.getTarget()), + power, false, 0, 0.2, 1, true); + + //Effect + zombie.getWorld().playSound(zombie.getLocation(), Sound.ZOMBIE_HURT, 1f, 2f); + } + + @EventHandler + public void onTarget(EntityTargetLivingEntityEvent event) + { + if (getEntity().equals(event.getEntity())) + { + if (!(event.getTarget() instanceof Player)) + { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void attack(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(false); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damager)) + { + if (damagee instanceof Player) + { + ((Player)damagee).setFoodLevel(((Player)damagee).getFoodLevel() - 1); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void protect(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damagee)) + { + if (!(damager instanceof Player)) + { + event.SetCancelled("Allied Attacker"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/WraithCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/WraithCreature.java new file mode 100644 index 000000000..9a9cbcde3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/WraithCreature.java @@ -0,0 +1,190 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.minion; + +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityTargetLivingEntityEvent; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +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.itemstack.ItemBuilder; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class WraithCreature extends EventCreature +{ + private static final int LIFETIME = -1; + + public WraithCreature(WorldEvent event, Location spawnLocation) + { + super(event, spawnLocation, "Wraith", true, 200, 30, true, Zombie.class); + spawnEntity(); + } + + @Override + protected void spawnCustom() + { + Zombie entity = getEntity(); + EntityEquipment eq = entity.getEquipment(); + eq.setHelmet(new ItemStack(Material.SKULL_ITEM, 1, (short)1)); + eq.setChestplate(new ItemBuilder(Material.LEATHER_CHESTPLATE).setColor(Color.BLACK).build()); + eq.setLeggings(new ItemBuilder(Material.LEATHER_LEGGINGS).setColor(Color.BLACK).build()); + eq.setBoots(new ItemBuilder(Material.LEATHER_BOOTS).setColor(Color.BLACK).build()); + eq.setItemInHand(new ItemStack(Material.IRON_SWORD)); + eq.setHelmetDropChance(0.f); + eq.setChestplateDropChance(0.f); + eq.setLeggingsDropChance(0.f); + eq.setBootsDropChance(0.f); + eq.setItemInHandDropChance(0.f); + entity.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 999999, 0)); + entity.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 999999, 0)); + entity.addPotionEffect(new PotionEffect(PotionEffectType.WATER_BREATHING, 999999, 0)); + entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 999999, 1)); + } + + @Override + public void dieCustom() + { + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + return; + } + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_HELMET)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_CHESTPLATE)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_LEGGINGS)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_BOOTS)); + } + + @EventHandler(priority = EventPriority.HIGH) + public void damage(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(false); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damager)) + { + event.AddMult(damager.getName(), "Mystical Darkness", 2, false); + } + } + + @EventHandler + public void blink(UpdateEvent event) + { + if (getEntity() == null) + return; + + if (event.getType() != UpdateType.FAST) + return; + + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + remove(); + return; + } + + if (Math.random() < 0.6) + return; + + Zombie zombie = getEntity(); + + if (zombie.getTarget() == null) + return; + + double dist = UtilMath.offset(zombie.getTarget(), zombie); + + if (dist <= 10 || dist > 25) + return; + + Location teleport = zombie.getTarget().getLocation().add(Math.random() + 1, 0, Math.random() + 1); + if (UtilMath.offset(getSpawnLocation(), teleport) > 30) + { + return; + } + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, zombie.getLocation(), 0, 0, 0, 0, 5, ViewDist.MAX); + zombie.getWorld().playSound(zombie.getLocation(), Sound.ENDERMAN_TELEPORT, 1f, 2f); + zombie.teleport(teleport); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, zombie.getLocation(), 0, 0, 0, 0, 5, ViewDist.MAX); + zombie.getWorld().playSound(zombie.getLocation(), Sound.ENDERMAN_TELEPORT, 1f, 2f); + } + + @EventHandler + public void onTarget(EntityTargetLivingEntityEvent event) + { + if (getEntity().equals(event.getEntity())) + { + if (!(event.getTarget() instanceof Player)) + { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void protect(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damagee)) + { + if (!(damager instanceof Player)) + { + event.SetCancelled("Allied Attacker"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/WorldEventCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/WorldEventCommand.java index 02b3974cf..62e42c6e8 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/WorldEventCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/WorldEventCommand.java @@ -22,7 +22,7 @@ public class WorldEventCommand extends MultiCommandBase @Override protected void Help(Player caller, String[] args) { - UtilPlayer.message(caller, F.help("/" + _aliasUsed + " start ", "Start a World Event where you're standing", Rank.ADMIN)); + UtilPlayer.message(caller, F.help("/" + _aliasUsed + " start ", "Start a World Event", Rank.ADMIN)); UtilPlayer.message(caller, F.help("/" + _aliasUsed + " clear", "Clears all World Events", Rank.ADMIN)); UtilPlayer.message(caller, F.help("/" + _aliasUsed + " random", "Starts a random World Event", Rank.ADMIN)); } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidAltar.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidAltar.java index e185d68e0..0bb876d79 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidAltar.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidAltar.java @@ -78,7 +78,7 @@ public class RaidAltar if (!rejected) { - count++; + count += item.getAmount(); } } @@ -153,10 +153,12 @@ public class RaidAltar { if (item.getAmount() > (amount - removed)) { + removed += (amount - removed); item.setAmount(item.getAmount() - (amount - removed)); } else { + removed += item.getAmount(); player.getInventory().setItem(i, null); } } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidManager.java index 87ccfdfd4..06e29d9de 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidManager.java @@ -7,19 +7,24 @@ import java.util.List; import java.util.Set; import java.util.function.Consumer; +import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitTask; import mineplex.core.MiniPlugin; import mineplex.core.blockrestore.BlockRestore; +import mineplex.core.common.util.C; import mineplex.core.common.util.F; import mineplex.core.common.util.UtilPlayer; import mineplex.core.common.util.UtilServer; import mineplex.core.disguise.DisguiseManager; +import mineplex.core.itemstack.ItemBuilder; import mineplex.core.projectile.ProjectileManager; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; @@ -42,6 +47,13 @@ public class RaidManager extends MiniPlugin super("Raid Manager", plugin); addCommand(new StartRaidCommand(this)); + + { + List items = new ArrayList<>(); + items.add(new ItemStack(Material.BONE, 20)); + items.add(new ItemBuilder(Material.IRON_INGOT).setAmount(2).setTitle(C.cDRedB + "Old Silver Token").setLore(C.cRed + "This token pulses with an evil aura.").setGlow(true).build()); + _altars.add(new RaidAltar(new Location(Bukkit.getWorld("world"), 361, 57, -990).getBlock(), RaidType.CHARLES_WITHERTON, items)); + } } @Override diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidWorldEvent.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidWorldEvent.java index 3705cef86..f3331ad5c 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidWorldEvent.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidWorldEvent.java @@ -269,6 +269,7 @@ public abstract class RaidWorldEvent extends WorldEvent event.getEntity().getActivePotionEffects().forEach(pe -> event.getEntity().removePotionEffect(pe.getType())); event.getEntity().setExp(0); event.getEntity().setLevel(0); + event.getEntity().setFireTicks(-1); event.getEntity().teleport(Spawn.getNorthSpawn()); } } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/WitherRaid.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/WitherRaid.java index 0a19b4fc6..6eb3a4112 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/WitherRaid.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/WitherRaid.java @@ -85,7 +85,7 @@ public class WitherRaid extends RaidWorldEvent { if (_currentChallenge.isComplete()) { - if (_challenges.size() < 6) + if (_challenges.size() < 5) { teleportToAltar(); } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/seven/ChallengeSeven.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/seven/ChallengeSeven.java index f82e86ab0..193a2fb37 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/seven/ChallengeSeven.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/seven/ChallengeSeven.java @@ -25,6 +25,12 @@ import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; import mineplex.game.clans.clans.worldevent.raid.wither.creature.mage.UndeadKnight; import mineplex.game.clans.clans.worldevent.raid.wither.creature.wither.CharlesWitherton; +import mineplex.game.clans.items.ItemType; +import mineplex.game.clans.items.RareItemFactory; +import mineplex.game.clans.items.attributes.weapon.ConqueringAttribute; +import mineplex.game.clans.items.attributes.weapon.FlamingAttribute; +import mineplex.game.clans.items.attributes.weapon.SharpAttribute; +import mineplex.game.clans.items.legendaries.DemonicScythe; public class ChallengeSeven extends RaidChallenge { @@ -91,6 +97,14 @@ public class ChallengeSeven extends RaidChallenge ClansManager.getInstance().getLootManager().dropRare(drop); drop.getWorld().dropItem(drop, new ItemStack(Material.EMERALD, emeralds)); } + RareItemFactory mainFactory = RareItemFactory.begin(ItemType.LEGENDARY).setLegendary(DemonicScythe.class); + if (Math.random() < 0.1) + { + mainFactory.setSuperPrefix(FlamingAttribute.class); + mainFactory.setPrefix(SharpAttribute.class); + mainFactory.setSuffix(ConqueringAttribute.class); + } + _altar.getWorld().dropItem(_altar.clone().add(0, 2, 0), mainFactory.fabricate()); getRaid().getWorldData().getCustomLocs("GATE_FIVE").get(0).getBlock().getRelative(BlockFace.DOWN).setType(Material.OBSIDIAN); getRaid().setForceEnd(System.currentTimeMillis() + UtilTime.convert(2, TimeUnit.MINUTES, TimeUnit.MILLISECONDS)); } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/HeatingUp.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/HeatingUp.java index 78f955916..c421b4b82 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/HeatingUp.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/HeatingUp.java @@ -50,7 +50,10 @@ public class HeatingUp extends Cataclysm _center.getBlock().getRelative(x, -1, z).setType(Material.STONE); } } - ((MagmusMeteor)Magmus.Abilities.get(2)).Disabled = false; + if (Magmus.Abilities.size() > 1 && Magmus.Abilities.get(2) instanceof MagmusMeteor) + { + ((MagmusMeteor)Magmus.Abilities.get(2)).Disabled = false; + } } @Override diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/Magmus.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/Magmus.java index 729499e23..490adbfb0 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/Magmus.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/Magmus.java @@ -36,6 +36,7 @@ public class Magmus extends RaidCreature Abilities.add(new MagmusCataclysm(this)); Abilities.add(new MagmusSmash(this)); Abilities.add(new MagmusMeteor(this)); + Abilities.add(new MagmusEat(this)); } protected ChallengeSix getChallenge() diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusCataclysm.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusCataclysm.java index 604ff9844..1bec42e4c 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusCataclysm.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusCataclysm.java @@ -28,7 +28,7 @@ public class MagmusCataclysm extends BossPassive @Override public int getCooldown() { - return 15; + return 23; } @Override @@ -43,13 +43,16 @@ public class MagmusCataclysm extends BossPassive if (UtilTime.elapsed(_lastUse, getCooldown() * 1000)) { _lastUse = System.currentTimeMillis(); - try + if (!_cataclysms.isEmpty()) { - UtilMath.randomElement(_cataclysms).getConstructor(ChallengeSix.class, Magmus.class).newInstance(getBoss().getChallenge(), getBoss()); - } - catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) - { - e.printStackTrace(); + try + { + UtilMath.randomElement(_cataclysms).getConstructor(ChallengeSix.class, Magmus.class).newInstance(getBoss().getChallenge(), getBoss()); + } + catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) + { + e.printStackTrace(); + } } } } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusEat.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusEat.java index 2fcfef365..f174ced35 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusEat.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusEat.java @@ -48,6 +48,7 @@ public class MagmusEat extends BossPassive { spit(); } + _ticks++; } private void initialEat(Player target) @@ -79,7 +80,7 @@ public class MagmusEat extends BossPassive } if (UtilTime.elapsed(_lastUse, getCooldown() * 1000)) { - Player target = UtilPlayer.getClosest(getLocation(), 3); + Player target = UtilPlayer.getClosest(getLocation(), 7); if (target != null) { initialEat(target); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusMeteor.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusMeteor.java index 5e76ef0de..c0da5fa5b 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusMeteor.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusMeteor.java @@ -43,7 +43,7 @@ public class MagmusMeteor extends BossPassive return; } Player target = UtilMath.randomElement(getBoss().getChallenge().getRaid().getPlayers()); - LargeFireball ball = target.getWorld().spawn(target.getLocation().add(Math.random() * 24 - 12, 32 + Math.random() * 16, Math.random() * 24 - 12), LargeFireball.class); + LargeFireball ball = target.getWorld().spawn(target.getLocation().add(2 * Math.random(), 10 + Math.random() * 16, 2 * Math.random()), LargeFireball.class); EntityLargeFireball eFireball = ((CraftLargeFireball) ball).getHandle(); eFireball.dirX = (Math.random()-0.5)*0.02; @@ -51,8 +51,9 @@ public class MagmusMeteor extends BossPassive eFireball.dirZ = (Math.random()-0.5)*0.02; ball.setShooter(getEntity()); - ball.setYield(2.2f); + ball.setYield(0f); ball.setBounce(false); + ball.setIsIncendiary(false); _shot.add(ball); } @@ -105,12 +106,12 @@ public class MagmusMeteor extends BossPassive if (event.getEntity() instanceof LargeFireball) { LargeFireball ball = (LargeFireball) event.getEntity(); - if (ball.getShooter() instanceof MagmaCube && ((MagmaCube)ball.getShooter()).getEntityId() == getEntity().getEntityId()) + if (_shot.contains(ball)) { _shot.remove(ball); UtilParticle.PlayParticle(ParticleType.EXPLODE, ball.getLocation(), null, 0, 2, ViewDist.MAX, UtilServer.getPlayers()); ball.getWorld().playSound(ball.getLocation(), Sound.EXPLODE, 10, 0); - Player hit = UtilPlayer.getClosest(ball.getLocation(), 0.5); + Player hit = UtilPlayer.getClosest(ball.getLocation(), 3); if (hit != null) { getBoss().getEvent().getDamageManager().NewDamageEvent(hit, getEntity(), ball, DamageCause.PROJECTILE, 4, true, true, false, getEntity().getName(), "Meteor Shower"); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusSmash.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusSmash.java index 2de2bb06d..50eab5b2b 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusSmash.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusSmash.java @@ -30,7 +30,7 @@ public class MagmusSmash extends BossPassive Map targets = UtilPlayer.getInRadius(getLocation(), 5.5d + 0.5 * 5); getBoss().TeleportBackASAP = false; getEntity().setVelocity(new Vector(0, 5, 0)); - UtilServer.runSyncLater(() -> getBoss().TeleportBackASAP = false, 3 * 20); + UtilServer.runSyncLater(() -> getBoss().TeleportBackASAP = true, 3 * 20); for (Player player : targets.keySet()) { getBoss().getEvent().getDamageManager().NewDamageEvent(player, getEntity(), null,