From 311751cc390ece412cbd2888af9a5002a1ea3a0e Mon Sep 17 00:00:00 2001 From: xADudex Date: Thu, 13 Oct 2016 04:40:05 +0200 Subject: [PATCH] Pumpkin's Revenge (#237) * Initial Commit * Update * Bunch of new stuff * Fixed fletcher arrow typo * Added reward pet, fixed typo, tweaked lose cinematic * Lots of tweaks and fixes with QA * Cleaning up a little code * Removed debug message on prince death * Added nighttime to halloween game lobby maps * Tweaked spawn rates and mob caps * Typo * Tweaked texts, cleaned import and cleared all mobs from boss cinematic * Fixed creepers not getting properly removed during boss cinematic * Reward typo * Fixed rare NPE * Typos * Tweaked mini zombie * Typo * Prevent zombie from spawning minis after being removed * Tweaked wave announcements + formated WaveVictory * Changed color of prince tag + formated ZombieSpawner * Fixed (another) rare NPE * Tweaked boss wave cinematic --- .../core/common/animation/AnimationPoint.java | 6 + .../core/common/animation/Animator.java | 11 +- .../core/common/animation/AnimatorEntity.java | 5 + .../common/animation/AnimatorFactory.java | 48 ++ .../mineplex/core/common/util/UtilEnt.java | 111 ++- .../mineplex/core/common/util/UtilFuture.java | 2 +- .../mineplex/core/common/util/UtilPlayer.java | 80 +- .../core/common/util/UtilReflection.java | 33 + .../src/mineplex/core/game/GameDisplay.java | 1 + .../src/mineplex/mapparser/GameType.java | 1 + .../src/nautilus/game/arcade/GameType.java | 2 + .../game/games/halloween/Halloween.java | 189 +++-- .../game/games/halloween/HalloweenAudio.java | 4 +- .../game/games/halloween/NamedAudio.java | 8 + .../halloween/creatures/CreatureBase.java | 72 +- .../games/halloween/kits/KitRobinHood.java | 4 +- .../game/games/halloween/kits/KitThor.java | 2 +- .../game/games/halloween/waves/WaveBase.java | 112 ++- .../games/halloween/waves/WaveVictory.java | 9 +- .../game/games/halloween2016/Crypt.java | 139 ++++ .../games/halloween2016/Halloween2016.java | 715 ++++++++++++++++++ .../games/halloween2016/PumpkinPlant.java | 107 +++ .../halloween2016/creatures/CryptBreaker.java | 256 +++++++ .../halloween2016/creatures/MobBlaze.java | 23 + .../halloween2016/creatures/MobCreeper.java | 83 ++ .../halloween2016/creatures/MobGiant.java | 190 +++++ .../creatures/MobMiniZombie.java | 70 ++ .../halloween2016/creatures/MobPigZombie.java | 72 ++ .../creatures/MobPrinceGuard.java | 236 ++++++ .../creatures/MobPumpkinPrince.java | 478 ++++++++++++ .../halloween2016/creatures/MobPumpling.java | 97 +++ .../creatures/MobSkeletonArcher.java | 53 ++ .../halloween2016/creatures/MobWitch.java | 295 ++++++++ .../halloween2016/creatures/MobZombie.java | 32 + .../creatures/MobZombieSpawner.java | 75 ++ .../tutorial/TutorialHalloween2016.java | 44 ++ .../tutorial/TutorialPhaseHalloween.java | 67 ++ .../game/games/halloween2016/wave/Wave1.java | 46 ++ .../game/games/halloween2016/wave/Wave2.java | 56 ++ .../game/games/halloween2016/wave/Wave3.java | 68 ++ .../game/games/halloween2016/wave/Wave4.java | 56 ++ .../game/games/halloween2016/wave/Wave5.java | 84 ++ .../games/halloween2016/wave/WaveBase.java | 46 ++ .../games/halloween2016/wave/WaveBoss.java | 253 +++++++ .../games/halloween2016/wave/WaveVictory.java | 52 ++ .../game/arcade/kit/perks/PerkFletcher.java | 10 +- .../arcade/kit/perks/PerkHammerThrow.java | 2 +- .../arcade/managers/NextBestGameManager.java | 2 + .../lobby/current/NewGameLobbyManager.java | 6 + 49 files changed, 4290 insertions(+), 123 deletions(-) create mode 100644 Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimatorFactory.java create mode 100644 Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilReflection.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/NamedAudio.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/Crypt.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/Halloween2016.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/PumpkinPlant.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/CryptBreaker.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobBlaze.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobCreeper.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobGiant.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobMiniZombie.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPigZombie.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPrinceGuard.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPumpkinPrince.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPumpling.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobSkeletonArcher.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobWitch.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobZombie.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobZombieSpawner.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/tutorial/TutorialHalloween2016.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/tutorial/TutorialPhaseHalloween.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave1.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave2.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave3.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave4.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave5.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveBase.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveBoss.java create mode 100644 Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveVictory.java diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimationPoint.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimationPoint.java index 82d819295..a02e78796 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimationPoint.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimationPoint.java @@ -33,6 +33,12 @@ public class AnimationPoint return _tick; } + @Override + public String toString() + { + return "AnimationPoint[tick" + _tick + ", motion:[" + _move + "], dir:[" + _dir + "]]"; + } + @Override public boolean equals(Object obj) { diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/Animator.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/Animator.java index 2e2461fda..335f327a4 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/Animator.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/Animator.java @@ -1,5 +1,6 @@ package mineplex.core.common.animation; +import java.util.Collection; import java.util.HashSet; import java.util.PriorityQueue; import java.util.Set; @@ -36,6 +37,11 @@ public abstract class Animator _plugin = plugin; } + public void addPoints(Collection points) + { + for(AnimationPoint p : points) _points.add(p); + } + public void addPoint(AnimationPoint point) { _points.add(point); } @@ -48,7 +54,9 @@ public abstract class Animator * @return Returns a cloned list of the animator points for this instance. */ public Set getSet() { - return new HashSet(_points); + Set set = new HashSet<>(); + set.addAll(_points); + return set; } /** @@ -110,6 +118,7 @@ public abstract class Animator prev.setDirection(_prev.getDirection()); double diff = ((double)_tick-_prev.getTick())/(_next.getTick()-_prev.getTick()); + if(!Double.isFinite(diff)) diff = 0; prev.add(next.clone().subtract(prev).toVector().multiply(diff)); Vector dirDiff = _next.getDirection().subtract(prev.getDirection()); diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimatorEntity.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimatorEntity.java index d418a337c..9f4aa27c6 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimatorEntity.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimatorEntity.java @@ -35,5 +35,10 @@ public class AnimatorEntity extends Animator @Override protected void finish(Location loc) {} + + public Entity getEntity() + { + return _ent; + } } diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimatorFactory.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimatorFactory.java new file mode 100644 index 000000000..8f23274c0 --- /dev/null +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/animation/AnimatorFactory.java @@ -0,0 +1,48 @@ +package mineplex.core.common.animation; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Location; +import org.bukkit.util.Vector; + +/** + * A small factory class to build animations using location inputs with embedded directions. It then calculates the vector difference + * between the locations in an ordered fashion when building the list. + */ +public class AnimatorFactory +{ + + private Map _locations = new HashMap<>(); + + public void addLocation(Location loc, int tick) + { + _locations.put(tick, loc.clone()); + } + + public List getBuildList(Location base) + { + List list = new ArrayList<>(); + + Iterator> it = _locations.entrySet().stream() + .sorted((e1, e2) + -> Integer.compare(e1.getKey(), e2.getKey()) + ) + .iterator(); + + while(it.hasNext()) + { + Entry e = it.next(); + Vector diff = e.getValue().clone().subtract(base).toVector(); + + list.add(new AnimationPoint(e.getKey(), diff, e.getValue().getDirection())); + } + + return list; + } + +} diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilEnt.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilEnt.java index 0e78782db..712eacdf4 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilEnt.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilEnt.java @@ -1,6 +1,7 @@ package mineplex.core.common.util; import java.lang.reflect.Field; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -132,6 +133,53 @@ public class UtilEnt } + /** + * See {@link #getEntitiesInsideEntity(Entity, List)} + * Uses all players in the same world as the entity as input + */ + public static List getPlayersInsideEntity(Entity ent) + { + return getEntitiesInsideEntity(ent, ent.getWorld().getPlayers()); + } + + /** + * See {@link #getEntitiesInsideEntity(Entity, List)} + * Uses all entities in the same world as the entity as input + */ + public static List getEntitiesInsideEntity(Entity ent) + { + return getEntitiesInsideEntity(ent, ent.getWorld().getEntities()); + } + + /** + * See {@link #getEntitiesInsideEntity(Entity, List)} + * Auto cast to list of players + */ + public static List getPlayersInsideEntity(Entity ent, List players) + { + return getEntitiesInsideEntity(ent, players); + } + + /** + * Returns entities which are inside the provided entity's boundingbox + * @param ent The entity to check inside + * @param entities List of entities to check + * @return Returns a sublist of entities which are inside the entity's boundingbox + */ + public static List getEntitiesInsideEntity(Entity ent, List entities) + { + AxisAlignedBB box = ((CraftEntity)ent).getHandle().getBoundingBox(); + + List list = new ArrayList<>(); + + for(T e : entities) + { + AxisAlignedBB box2 = ((CraftEntity)e).getHandle().getBoundingBox(); + if(box2.b(box)) list.add(e); + } + return list; + } + public static void Vegetate(Entity entity) { Vegetate(entity, false); @@ -345,6 +393,35 @@ public class UtilEnt } } + /** + * Set whether this entity should be ticked normally when far away. By default entities are only ticked once every 20 ticks + * when they are outside the activation range. + * + * Default ranges are calculated in a AABB fashion from their closest player: + * animalActivationRange = 32 + * monsterActivationRange = 32 + * miscActivationRange = 16 + * + * Entities that are unaffected by range (always active): + * Players, Projectiles, Enderdragon, Wither, Fireballs, Lightning strikes, TNT, Ender Crystals and Fireworks. + * + * You can make entities which are by default active (Projectiles etc) not load when far away + * or make entities that are not active by default (mobs, animals etc) load when far away + */ + public static void setTickWhenFarAway(Entity ent, boolean loadWhenFar) + { + try + { + Field state = net.minecraft.server.v1_8_R3.Entity.class.getDeclaredField("defaultActivationState"); + state.setAccessible(true); + state.setBoolean(((CraftEntity)ent).getHandle(), loadWhenFar); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + public static String getName(Entity ent) { if (ent == null) @@ -578,6 +655,16 @@ public class UtilEnt return false; } + public static float getStepHeight(Entity ent) + { + return ((CraftEntity)ent).getHandle().S; + } + + public static void setStepHeight(Entity ent, float stepHeight) + { + ((CraftEntity)ent).getHandle().S = stepHeight; + } + public static boolean isGrounded(Entity ent) { @@ -813,6 +900,18 @@ public class UtilEnt return true; } + + /** + * Returns true if the entity got a path that will lead it closer to the current navigation path finding target. + * It will return false, it it is as close as it can get. Using this got an advantage compared to distance checking, as the target + * might be inside blocks, leaving the entity unable to get any closer. + * @param ent The entity to check + * @return Returns whether the entity can walk any closer to the current navigation target. + */ + public static boolean canEntityWalkCloserToNavigationTarget(Creature ent) + { + return ((CraftCreature)ent).getHandle().getNavigation().m(); + } public static int getNewEntityId() { @@ -887,7 +986,17 @@ public class UtilEnt { ((CraftEntity)ent).getHandle().setSize((float) width, (float)height); } - + + public static double getHeight(Entity ent) + { + return ((CraftEntity)ent).getHandle().length; + } + + public static double getWidth(Entity ent) + { + return ((CraftEntity)ent).getHandle().width; + } + public static void SetMetadata(Entity entity, String key, Object value) { entity.setMetadata(key, new FixedMetadataValue(UtilServer.getPlugin(), value)); diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilFuture.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilFuture.java index 2b25f9a5e..d7906385b 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilFuture.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilFuture.java @@ -86,7 +86,7 @@ public class UtilFuture CompletableFuture.allOf(values.toArray(new CompletableFuture[values.size()])); return futuresCompleted.thenApply(v -> - seqValues.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().join()))); + (Map>) seqValues.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> (Collection) entry.getValue().join()))); } /** diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilPlayer.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilPlayer.java index 773fcf442..5f7e00ddc 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilPlayer.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilPlayer.java @@ -1,16 +1,17 @@ package mineplex.core.common.util; -import mineplex.core.common.MinecraftVersion; -import mineplex.core.common.events.PlayerMessageEvent; -import net.md_5.bungee.api.chat.ClickEvent; -import net.md_5.bungee.api.chat.ClickEvent.Action; -import net.md_5.bungee.api.chat.HoverEvent; -import net.md_5.bungee.api.chat.TextComponent; -import net.minecraft.server.v1_8_R3.EntityPlayer; -import net.minecraft.server.v1_8_R3.Packet; -import net.minecraft.server.v1_8_R3.PacketPlayOutWorldBorder; -import net.minecraft.server.v1_8_R3.PlayerConnection; -import net.minecraft.server.v1_8_R3.WorldBorder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.UUID; + import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.Location; @@ -26,9 +27,23 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryView; import org.bukkit.potion.PotionEffect; +import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.BlockIterator; import org.bukkit.util.Vector; +import mineplex.core.common.MinecraftVersion; +import mineplex.core.common.events.PlayerMessageEvent; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ClickEvent.Action; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.EntityTracker; +import net.minecraft.server.v1_8_R3.EntityTrackerEntry; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayOutWorldBorder; +import net.minecraft.server.v1_8_R3.PlayerConnection; +import net.minecraft.server.v1_8_R3.WorldBorder; import java.util.*; public class UtilPlayer @@ -73,6 +88,49 @@ public class UtilPlayer return true; } + public static void setSpectating(Player player, Entity ent) + { + if(!ent.isValid()) return; + + player.setGameMode(GameMode.SPECTATOR); + + if(player.getSpectatorTarget() != null) + { + player.setSpectatorTarget(null); + } + + player.teleport(ent); + + if(isTracked(player, ent)) + { + player.setSpectatorTarget(ent); + } + else + { + new BukkitRunnable() + { + public void run() + { + setSpectating(player, ent); + } + }.runTaskLater(UtilServer.getPlugin(), 1); + } + } + + /** + * Returns true if the given player is tracking the given target, meaning that the player + * got the entity loaded and knows about the entity. + */ + public static boolean isTracked(Player player, Entity target) + { + EntityPlayer ep = ((CraftPlayer) player).getHandle(); + + EntityTracker tracker = ep.u().getTracker(); + EntityTrackerEntry entry = tracker.trackedEntities.get(target.getEntityId()); + + return entry.trackedPlayers.contains(ep); + } + public static void hideFrom(Player player, Collection players) { players.stream().forEach(p->p.hidePlayer(player)); } diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilReflection.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilReflection.java new file mode 100644 index 000000000..079182304 --- /dev/null +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilReflection.java @@ -0,0 +1,33 @@ +package mineplex.core.common.util; + +import java.lang.reflect.Field; + +public class UtilReflection +{ + /** + * Returns the value of the field from the given object instance + */ + public static Object getValueOfField(Object object, String fieldName) + { + return getValueOfField(object.getClass(), object, fieldName); + } + + /** + * Returns the value of the field from the given object instance + */ + public static Object getValueOfField(Class className, Object object, String fieldName) + { + try + { + Field f = className.getDeclaredField(fieldName); + f.setAccessible(true); + return f.get(object); + } + catch (Exception e) + { + e.printStackTrace(); + return null; + } + } + +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java b/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java index aef40f7c1..136d324ab 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java @@ -25,6 +25,7 @@ public enum GameDisplay Evolution("Evolution", Material.EMERALD, (byte)0, GameCategory.ARCADE, 16), Gravity("Gravity", Material.ENDER_PORTAL_FRAME, (byte)0, GameCategory.EXTRA, 18), Halloween("Halloween Horror", Material.PUMPKIN, (byte)0, GameCategory.CLASSICS, 19), + Halloween2016("Pumpkin's Revenge", Material.PUMPKIN, (byte)0, GameCategory.CLASSICS, 63), HideSeek("Block Hunt", Material.GRASS, (byte)0, GameCategory.CLASSICS, 20), HoleInTheWall("Hole in the Wall", Material.STAINED_GLASS, (byte) 2, GameCategory.ARCADE, 52), Horse("Horseback", Material.IRON_BARDING, (byte)0, GameCategory.ARCADE, 21), diff --git a/Plugins/Mineplex.MapParser/src/mineplex/mapparser/GameType.java b/Plugins/Mineplex.MapParser/src/mineplex/mapparser/GameType.java index 006d485b0..1f4262d28 100644 --- a/Plugins/Mineplex.MapParser/src/mineplex/mapparser/GameType.java +++ b/Plugins/Mineplex.MapParser/src/mineplex/mapparser/GameType.java @@ -31,6 +31,7 @@ public enum GameType Gladiators("Gladiators"), Gravity("Gravity"), Halloween("Halloween Horror"), + Halloween2016("Halloween Horror 2016"), HideSeek("Block Hunt"), Horse("Horseback"), Lobbers("Bomb Lobbers"), diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java index 517358bd0..41613e265 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java @@ -40,6 +40,7 @@ import nautilus.game.arcade.game.games.gladiators.modes.OverpoweredGladiators; import nautilus.game.arcade.game.games.gladiators.modes.SmashGladiators; import nautilus.game.arcade.game.games.gravity.Gravity; import nautilus.game.arcade.game.games.halloween.Halloween; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; import nautilus.game.arcade.game.games.hideseek.HideSeek; import nautilus.game.arcade.game.games.hideseek.modes.Countdown; import nautilus.game.arcade.game.games.holeinwall.HoleInTheWall; @@ -143,6 +144,7 @@ public enum GameType { Pair.create(MinecraftVersion.ALL, "http://file.mineplex.com/ResHalloween.zip") }, true), + Halloween2016(Halloween2016.class, GameDisplay.Halloween2016), HideSeek(HideSeek.class, GameDisplay.HideSeek), HoleInTheWall(HoleInTheWall.class, GameDisplay.HoleInTheWall), Horse(Horse.class, GameDisplay.Horse), diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/Halloween.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/Halloween.java index 3f4c10226..a2160dda5 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/Halloween.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/Halloween.java @@ -1,7 +1,37 @@ package nautilus.game.arcade.game.games.halloween; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; + +import org.bukkit.ChatColor; +import org.bukkit.Difficulty; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.entity.Fireball; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntityTargetEvent; +import org.bukkit.event.entity.ItemSpawnEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + import mineplex.core.common.currency.GlobalCurrency; -import mineplex.core.common.util.*; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilBlock; +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.common.util.UtilTime.TimeUnit; import mineplex.core.recharge.Recharge; import mineplex.core.updater.UpdateType; @@ -17,36 +47,38 @@ import nautilus.game.arcade.game.games.halloween.creatures.InterfaceMove; import nautilus.game.arcade.game.games.halloween.kits.KitFinn; import nautilus.game.arcade.game.games.halloween.kits.KitRobinHood; import nautilus.game.arcade.game.games.halloween.kits.KitThor; -import nautilus.game.arcade.game.games.halloween.waves.*; +import nautilus.game.arcade.game.games.halloween.waves.Wave1; +import nautilus.game.arcade.game.games.halloween.waves.Wave2; +import nautilus.game.arcade.game.games.halloween.waves.Wave3; +import nautilus.game.arcade.game.games.halloween.waves.Wave4; +import nautilus.game.arcade.game.games.halloween.waves.Wave5; +import nautilus.game.arcade.game.games.halloween.waves.WaveBase; +import nautilus.game.arcade.game.games.halloween.waves.WaveBoss; +import nautilus.game.arcade.game.games.halloween.waves.WaveVictory; import nautilus.game.arcade.kit.Kit; import nautilus.game.arcade.managers.chat.ChatStatData; import net.minecraft.server.v1_8_R3.PacketPlayOutNamedSoundEffect; -import org.bukkit.*; -import org.bukkit.block.Block; -import org.bukkit.entity.Fireball; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.*; -import org.bukkit.event.entity.EntityDamageEvent.DamageCause; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; - -import java.util.*; public class Halloween extends SoloGame { //Wave Data - private ArrayList> _spawns; + protected ArrayList> _spawns; - private ArrayList _waves; - private int _wave = 0; + protected ArrayList _waves; + protected int _wave = 0; - private int _maxMobs = 80; - private ArrayList _mobs = new ArrayList(); + protected int _maxMobs = 80; + protected ArrayList> _mobs = new ArrayList<>(); - private HashMap _damageTime = new HashMap(); + protected HashMap _damageTime = new HashMap(); - private HashSet _soundOff = new HashSet(); + protected HashSet _soundOff = new HashSet(); + + protected UpdateType _updateCreatureMoveRate = UpdateType.FASTEST; + + protected boolean doVoices = true; + + public String Objective = null; public long total = 0; public long move = 0; @@ -78,7 +110,7 @@ public class Halloween extends SoloGame public Halloween(ArcadeManager manager) { - super(manager, GameType.Halloween, + this(manager, GameType.Halloween, new Kit[] { @@ -94,6 +126,12 @@ public class Halloween extends SoloGame "Defeat the waves of monsters", "Kill the Pumpkin King" }); + } + + protected Halloween(ArcadeManager manager, GameType gameType, Kit[] kits, String[] gameDesc) + { + super(manager, gameType, kits, gameDesc); + this.DamagePvP = false; @@ -116,6 +154,19 @@ public class Halloween extends SoloGame BlankLine, new ChatStatData("kit", "Kit", true) ); + + _help = new String[] + { + C.cGreen + "Giants one hit kill you! Stay away!!!", + C.cAqua + "Work together with your team mates.", + C.cGreen + "Each kit gives a buff to nearby allies.", + C.cAqua + "Kill monsters to keep their numbers down.", + C.cGreen + "Kill giants quickly.", + C.cAqua + "Defend your team mates from monsters.", + C.cGreen + "Zombies, Giants and Spiders get faster over time.", + C.cAqua + "Stick together to survive.", + C.cGreen + "The Pumpkin King gets harder over time!", + }; } @Override @@ -134,7 +185,7 @@ public class Halloween extends SoloGame _waves.add(new Wave4(this)); _waves.add(new Wave5(this)); _waves.add(new WaveBoss(this)); - _waves.add(new WaveVictory(this)); + _waves.add(new WaveVictory(this, GetSpawnSet(3))); //Make zombies break doors WorldData.World.setDifficulty(Difficulty.HARD); @@ -146,13 +197,20 @@ public class Halloween extends SoloGame if (event.GetState() != GameState.End) return; - for (CreatureBase ent : _mobs) - ent.GetEntity().remove(); + for (CreatureBase ent : _mobs) + { + ent.remove(); + } _mobs.clear(); _spawns.clear(); } + public ArrayList> getMobs() + { + return _mobs; + } + @EventHandler(priority = EventPriority.MONITOR) public void TeamGen(GameStateChangeEvent event) { @@ -168,6 +226,8 @@ public class Halloween extends SoloGame if (event.GetState() != GameState.Live) return; + if(!doVoices) return; + Announce(C.Bold + "Type " + C.cGreen + C.Bold + "/voice" + C.cWhite + C.Bold + " to disable voice audio."); } @@ -253,8 +313,12 @@ public class Halloween extends SoloGame if (!IsLive()) return; + + if(_waves.get(_wave) instanceof WaveVictory || + _waves.get(_wave) instanceof nautilus.game.arcade.game.games.halloween2016.wave.WaveVictory) + return; - if (Math.random() > 0.6) + if (Math.random() > 0.2) return; for (Player player : UtilServer.getPlayers()) @@ -297,12 +361,12 @@ public class Halloween extends SoloGame return locSet.get(UtilMath.r(locSet.size())); } - public void AddCreature(CreatureBase mob) + public void AddCreature(CreatureBase mob) { _mobs.add(0, mob); } - public ArrayList GetCreatures() + public ArrayList> GetCreatures() { return _mobs; } @@ -310,7 +374,7 @@ public class Halloween extends SoloGame @EventHandler public void CreatureMoveUpdate(UpdateEvent event) { - if (event.getType() != UpdateType.FASTEST) + if (event.getType() != _updateCreatureMoveRate) return; if (_mobs.isEmpty()) @@ -318,7 +382,7 @@ public class Halloween extends SoloGame long start = System.currentTimeMillis(); - CreatureBase base = _mobs.remove(0); + CreatureBase base = _mobs.remove(0); if (base instanceof InterfaceMove) { @@ -342,25 +406,33 @@ public class Halloween extends SoloGame return; //Clean - Iterator mobIterator = _mobs.iterator(); + Iterator> mobIterator = _mobs.iterator(); while (mobIterator.hasNext()) { - CreatureBase base = mobIterator.next(); + CreatureBase base = mobIterator.next(); if (base.Updater(event)) + { + onRemove(base); + base.remove(); mobIterator.remove(); + } } total += System.currentTimeMillis() - start; update += System.currentTimeMillis() - start; } + + public void onRemove(CreatureBase mob) + { + } @EventHandler public void CreatureDamage(CustomDamageEvent event) { long start = System.currentTimeMillis(); - for (CreatureBase base : _mobs) + for (CreatureBase base : _mobs) base.Damage(event); total += System.currentTimeMillis() - start; @@ -372,7 +444,7 @@ public class Halloween extends SoloGame { long start = System.currentTimeMillis(); - for (CreatureBase base : _mobs) + for (CreatureBase base : _mobs) base.Target(event); total += System.currentTimeMillis() - start; @@ -451,7 +523,7 @@ public class Halloween extends SoloGame { Block block = blockIterator.next(); - if (block.getY() < 4) + if (block.getY() < 4 || block.getY() <= WorldData.MinY) blockIterator.remove(); } @@ -494,40 +566,6 @@ public class Halloween extends SoloGame { return _maxMobs; } - - private long _helpTimer = 0; - private int _helpIndex = 0; - private String[] _help = new String[] - { - C.cGreen + "Giants one hit kill you! Stay away!!!", - C.cAqua + "Work together with your team mates.", - C.cGreen + "Each kit gives a buff to nearby allies.", - C.cAqua + "Kill monsters to keep their numbers down.", - C.cGreen + "Kill giants quickly.", - C.cAqua + "Defend your team mates from monsters.", - C.cGreen + "Zombies, Giants and Spiders get faster over time.", - C.cAqua + "Stick together to survive.", - C.cGreen + "The Pumpkin King gets harder over time!", - }; - - @EventHandler - public void StateUpdate(UpdateEvent event) - { - if (event.getType() != UpdateType.SEC) - return; - - if (this.GetState() != GameState.Recruit) - return; - - if (!UtilTime.elapsed(_helpTimer, 8000)) - return; - - _helpTimer = System.currentTimeMillis(); - - Announce(C.cWhite + C.Bold + "TIP " + ChatColor.RESET + _help[_helpIndex]); - - _helpIndex = (_helpIndex + 1)%_help.length; - } @Override @EventHandler @@ -552,7 +590,7 @@ public class Halloween extends SoloGame Scoreboard.writeNewLine(); Scoreboard.write(C.cYellow + C.Bold + "Players"); - if (GetPlayers(true).size() < 8) + if (GetPlayers(true).size() < 5) { for (Player player : GetPlayers(true)) { @@ -564,12 +602,21 @@ public class Halloween extends SoloGame Scoreboard.write(GetPlayers(true).size() + " Alive"); } + if(Objective != null) + { + Scoreboard.writeNewLine(); + Scoreboard.write(C.cYellow + C.Bold + "Objective"); + Scoreboard.write(Objective); + } + Scoreboard.draw(); } @EventHandler public void soundOff(PlayerCommandPreprocessEvent event) { + if(!doVoices) return; + if (event.getMessage().equalsIgnoreCase("/voice")) { if (_soundOff.remove(event.getPlayer())) @@ -587,12 +634,12 @@ public class Halloween extends SoloGame } } - public void playSound(HalloweenAudio audio) + public void playSound(NamedAudio audio) { for (Player player : UtilServer.getPlayers()) if (!_soundOff.contains(player)) { - PacketPlayOutNamedSoundEffect packet = new PacketPlayOutNamedSoundEffect(audio.getName(), + PacketPlayOutNamedSoundEffect packet = new PacketPlayOutNamedSoundEffect(audio.getAudioPath(), player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ(), 20f, 1F); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/HalloweenAudio.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/HalloweenAudio.java index c737a3a68..0b51ac003 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/HalloweenAudio.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/HalloweenAudio.java @@ -1,6 +1,6 @@ package nautilus.game.arcade.game.games.halloween; -public enum HalloweenAudio +public enum HalloweenAudio implements NamedAudio { WAVE_1("halloween.wave1"), WAVE_2("halloween.wave2"), @@ -25,7 +25,7 @@ public enum HalloweenAudio _name = name; } - public String getName() + public String getAudioPath() { return _name; } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/NamedAudio.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/NamedAudio.java new file mode 100644 index 000000000..ab4b6f987 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/NamedAudio.java @@ -0,0 +1,8 @@ +package nautilus.game.arcade.game.games.halloween; + +public interface NamedAudio +{ + + public String getAudioPath(); + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/creatures/CreatureBase.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/creatures/CreatureBase.java index fb4b3232c..69dd85093 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/creatures/CreatureBase.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/creatures/CreatureBase.java @@ -1,18 +1,22 @@ package nautilus.game.arcade.game.games.halloween.creatures; +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.entity.Creature; +import org.bukkit.entity.Damageable; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityTargetEvent; + import mineplex.core.common.util.UtilEnt; import mineplex.core.common.util.UtilMath; import mineplex.core.updater.event.UpdateEvent; import mineplex.minecraft.game.core.damage.CustomDamageEvent; import nautilus.game.arcade.game.games.halloween.Halloween; -import org.bukkit.Location; -import org.bukkit.entity.Creature; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.entity.EntityTargetEvent; -import org.bukkit.util.Vector; - public abstract class CreatureBase { public Halloween Host; @@ -22,6 +26,8 @@ public abstract class CreatureBase private Location _target; private long _targetTime; + + private List _parts = new ArrayList<>(); public CreatureBase(Halloween game, String name, Class mobClass, Location loc) { @@ -37,11 +43,39 @@ public abstract class CreatureBase _ent.setCustomName(name); _ent.setCustomNameVisible(true); } + + addEntityPart(_ent); SpawnCustom(_ent); game.CreatureAllowOverride = false; } + + protected void addEntityPart(Entity ent) + { + if(_parts.contains(ent)) return; + _parts.add(ent); + } + + public List getEntityParts() + { + return new ArrayList<>(_parts); + } + + public List getInsideBoundingBox() + { + List players = Host.GetPlayers(true); + List list = UtilEnt.getPlayersInsideEntity(_ent, players); + for(Entity ent : _parts) + { + players.removeAll(list); + if(players.isEmpty()) break; + + list.addAll(UtilEnt.getPlayersInsideEntity(ent, players)); + } + + return list; + } public abstract void SpawnCustom(T ent); @@ -114,8 +148,13 @@ public abstract class CreatureBase public abstract void Damage(CustomDamageEvent event); public abstract void Target(EntityTargetEvent event); - + public void CreatureMove(Creature creature) + { + CreatureMove(creature, 1); + } + + public void CreatureMove(Creature creature, float speed) { //New Target SetTarget(GetRoamTarget()); @@ -131,8 +170,23 @@ public abstract class CreatureBase //Move else { - UtilEnt.CreatureMove(creature, GetTarget(), 1f); + UtilEnt.CreatureMove(creature, GetTarget(), speed); Host.moves++; } } + + public void remove() + { + for(Entity ent : _parts) + { + if(ent instanceof Damageable) + { + ((Damageable) ent).damage(((Damageable) ent).getHealth()); + } + else + { + ent.remove(); + } + } + } } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/kits/KitRobinHood.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/kits/KitRobinHood.java index cd31b70d3..c7dcb1f32 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/kits/KitRobinHood.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/kits/KitRobinHood.java @@ -31,8 +31,8 @@ public class KitRobinHood extends ProgressingKit }; private static final Perk[] PERKS = { - new PerkFletcher(1, 8, true), - new PerkBarrage(8, 125, true, true), + new PerkFletcher(3, 6, true), + new PerkBarrage(8, 125, true, false), new PerkQuickshotRobinHood() }; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/kits/KitThor.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/kits/KitThor.java index 58bba7619..84ffe7f24 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/kits/KitThor.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/kits/KitThor.java @@ -32,7 +32,7 @@ public class KitThor extends ProgressingKit private static final Perk[] PERKS = { new PerkKnockbackAttack(2), - new PerkFletcher(2, 2, true, 9), + new PerkFletcher(2, 2, true, 8), new PerkSeismicHammer(), new PerkHammerThrow(), }; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/waves/WaveBase.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/waves/WaveBase.java index 3a8a07c4a..9d5a06b62 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/waves/WaveBase.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/waves/WaveBase.java @@ -1,6 +1,6 @@ package nautilus.game.arcade.game.games.halloween.waves; -import java.util.ArrayList; +import java.util.List; import org.bukkit.Location; import org.bukkit.Material; @@ -9,29 +9,40 @@ import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import nautilus.game.arcade.game.games.halloween.Halloween; -import nautilus.game.arcade.game.games.halloween.HalloweenAudio; import mineplex.core.common.util.C; import mineplex.core.common.util.UtilMath; import mineplex.core.common.util.UtilServer; -import mineplex.core.common.util.UtilTime; import mineplex.core.common.util.UtilTextMiddle; +import mineplex.core.common.util.UtilTime; +import nautilus.game.arcade.game.games.halloween.Halloween; +import nautilus.game.arcade.game.games.halloween.NamedAudio; public abstract class WaveBase { protected Halloween Host; protected String _name; - protected HalloweenAudio _audio; + protected boolean _displayWaveNumber = true; + protected boolean _announceWaveChat = true; + protected boolean _announceWaveTitle = true; + protected NamedAudio _audio; protected long _start; protected long _duration; private int _tick = 0; - protected ArrayList _spawns; + protected List _spawns; - public WaveBase(Halloween host, String name, long duration, ArrayList spawns, HalloweenAudio audio) + private boolean _spawnBeacons = true; + private boolean _announceStart = true; + private boolean _displayProgress = true; + + protected String _titleColor = C.cYellow; + + protected String[] _desc = null; + + public WaveBase(Halloween host, String name, long duration, List spawns, NamedAudio audio) { Host = host; @@ -66,22 +77,57 @@ public abstract class WaveBase if (_tick == 0) { System.out.println("Wave " + wave + " has started."); - Host.Announce(C.cRed + C.Bold + "Wave " + wave + ": " + C.cYellow + _name); - - UtilTextMiddle.display(C.cYellow + "Wave " + wave, _name, 10, 100, 20); - - if (_audio != null) - { - Host.playSound(_audio); + if(_announceStart) + { + if(_announceWaveChat) + { + String number = C.cRed + C.Bold + "Wave " + wave; + String name = C.cYellow + _name; + if(name != null) + { + number += ": "; + } + if(_name == null) name = ""; + if(!_displayWaveNumber) number = ""; + + String waveName = number + name; + + Host.Announce(waveName); + } + if(_desc != null) + { + for(String l : _desc) + { + Host.Announce(C.cGray + " ● " + C.cYellow + l); + } + } + + if(_announceWaveTitle) + { + String waveTitle = _displayWaveNumber ? _titleColor + "Wave " + wave : _name; + String waveSub = _displayWaveNumber ? _name : ""; + UtilTextMiddle.display(waveTitle, waveSub, 10, 100, 20); + } + + + if (_audio != null) + { + Host.playSound(_audio); + } } } //Display - for (Player player : UtilServer.getPlayers()) - player.setExp(Math.min(0.999f, (float)(_duration - (System.currentTimeMillis() - _start)) / (float)_duration)); + if(_displayProgress) + { + for (Player player : UtilServer.getPlayers()) + { + player.setExp(Math.min(0.999f, (float)(_duration - (System.currentTimeMillis() - _start)) / (float)_duration)); + } + } //Spawn Beacons - if (_tick == 0) + if (_tick == 0 && _spawnBeacons) SpawnBeacons(_spawns); //Spawn @@ -92,7 +138,7 @@ public abstract class WaveBase return false; } - public void SpawnBeacons(ArrayList locs) + public void SpawnBeacons(List locs) { //Average Location Vector total = new Vector(0,0,0); @@ -121,6 +167,36 @@ public abstract class WaveBase { return true; } + + public void setAnnounceStart(boolean announceStart) + { + _announceStart = announceStart; + } + + public void setDisplayProgress(boolean displayProgress) + { + _displayProgress = displayProgress; + } + + public void setSpawnBeacons(boolean spawnBeacons) + { + _spawnBeacons = spawnBeacons; + } + + public boolean getAnnounceStart() + { + return _announceStart; + } + + public boolean getDisplayProgress() + { + return _displayProgress; + } + + public boolean getSpawnBeacons() + { + return _spawnBeacons; + } public abstract void Spawn(int tick); } diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/waves/WaveVictory.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/waves/WaveVictory.java index 618658947..dada174c5 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/waves/WaveVictory.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween/waves/WaveVictory.java @@ -1,6 +1,9 @@ package nautilus.game.arcade.game.games.halloween.waves; +import java.util.List; + import org.bukkit.Effect; +import org.bukkit.Location; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -11,9 +14,9 @@ import nautilus.game.arcade.game.games.halloween.creatures.CreatureBase; public class WaveVictory extends WaveBase { - public WaveVictory(Halloween host) + public WaveVictory(Halloween host, List beaconSpawn) { - super(host, "Celebration!", 15000, host.GetSpawnSet(3), null); + super(host, "Celebration!", 15000, beaconSpawn, null); } @Override @@ -28,7 +31,7 @@ public class WaveVictory extends WaveBase player.playEffect(Host.WorldData.GetDataLocs("BLACK").get(0), Effect.RECORD_PLAY, 2259); //Mobs - for (CreatureBase mob : Host.GetCreatures()) + for (CreatureBase mob : Host.GetCreatures()) mob.GetEntity().damage(5); //Time diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/Crypt.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/Crypt.java new file mode 100644 index 000000000..562bd08cc --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/Crypt.java @@ -0,0 +1,139 @@ +package nautilus.game.arcade.game.games.halloween2016; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.entity.Entity; + +import mineplex.core.common.block.schematic.Schematic; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTextTop; +import mineplex.core.common.util.UtilTime; + +public class Crypt +{ + + private int _maxHealth = 2000; + private int _health = _maxHealth; + + private List _states; + private int _stateIndex = 0; + private Location _schematicBase; + + private Map _damageCooldown = new HashMap<>(); + + private Halloween2016 _host; + + public Crypt(Halloween2016 host, Location base, List states) + { + _host = host; + _states = new ArrayList<>(); + _states.addAll(states); + _schematicBase = base.clone(); + } + + public boolean tryDamage(Entity mob, int damage, int cooldown) + { + if(isDestroyed()) return false; + Integer lastTime = _damageCooldown.get(mob); + if(lastTime != null && lastTime > UtilTime.getServerTick()) return false; + + _health -= damage; + _damageCooldown.put(mob, UtilTime.getServerTick() + cooldown); + + updateState(damage); + + return true; + } + + public void setHealth(int health) + { + int diff = _health-health; + _health = health; + updateState(diff); + } + + public void updateHealthDisplay() + { + UtilTextTop.displayProgress(C.cRed + C.Bold + "Crypt", getHealthProgress(), UtilServer.getPlayers()); + } + + public float getHealthProgress() + { + return Math.max(0, _health/ (float) _maxHealth); + } + + public int getMaxHealth() + { + return _maxHealth; + } + + public int getHealth() + { + return _health; + } + + public int getStateIndex() + { + return _stateIndex; + } + + public Location getSchematicBase() + { + return _schematicBase.clone(); + } + + public void updateState(int damage) + { + float prevProg = (damage + _health) / (float) _maxHealth; + float progress = getHealthProgress(); + + int state = (int) (_states.size() * (1-progress)); + if(state != _stateIndex && state < _states.size()) + { + _stateIndex = state; + _states.get(state).paste(_schematicBase, false, true); + } + + int iprog = (int) Math.ceil(progress*100); + int iprevProg = (int) Math.ceil(prevProg*100); + + if((iprog%10 == 0 || iprog <= 5) && iprevProg > iprog) + { + String color = C.cGreen; + if(iprog <= 60) color = C.cYellow; + if(iprog <= 30) color = C.cGold; + if(iprog <= 10) color = C.cRed; + + if(iprog == 0) + { + _host.Announce(F.main("Crypt", "The crypt has been destroyed!"), true); + } + else + { + _host.Announce(F.main("Crypt", "The crypt only has " + color + C.Bold + iprog + "%" + C.mBody + " left!"), true); + } + + if(iprog == 0) + { + for(Location loc : _host.getInfrontOfDoorTargets()) + { + loc.getWorld().playEffect(loc, Effect.EXPLOSION_HUGE, 0); + loc.getWorld().strikeLightningEffect(loc); + } + } + } + } + + public boolean isDestroyed() + { + return _health <= 0; + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/Halloween2016.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/Halloween2016.java new file mode 100644 index 000000000..4fef083cc --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/Halloween2016.java @@ -0,0 +1,715 @@ +package nautilus.game.arcade.game.games.halloween2016; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import mineplex.core.common.animation.AnimationPoint; +import mineplex.core.common.animation.Animator; +import mineplex.core.common.animation.AnimatorFactory; +import mineplex.core.common.block.schematic.Schematic; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +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.reward.RewardRarity; +import mineplex.core.reward.rewards.PetReward; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; + +import javafx.util.Pair; +import nautilus.game.arcade.ArcadeManager; +import nautilus.game.arcade.GameType; +import nautilus.game.arcade.events.GameStateChangeEvent; +import nautilus.game.arcade.game.GameTeam; +import nautilus.game.arcade.game.games.halloween.Halloween; +import nautilus.game.arcade.game.games.halloween.creatures.CreatureBase; +import nautilus.game.arcade.game.games.halloween.kits.KitFinn; +import nautilus.game.arcade.game.games.halloween.kits.KitRobinHood; +import nautilus.game.arcade.game.games.halloween.kits.KitThor; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobPumpling; +import nautilus.game.arcade.game.games.halloween2016.tutorial.TutorialHalloween2016; +import nautilus.game.arcade.game.games.halloween2016.wave.Wave1; +import nautilus.game.arcade.game.games.halloween2016.wave.Wave2; +import nautilus.game.arcade.game.games.halloween2016.wave.Wave3; +import nautilus.game.arcade.game.games.halloween2016.wave.Wave4; +import nautilus.game.arcade.game.games.halloween2016.wave.Wave5; +import nautilus.game.arcade.game.games.halloween2016.wave.WaveBoss; +import nautilus.game.arcade.game.games.halloween2016.wave.WaveVictory; +import nautilus.game.arcade.kit.Kit; + +public class Halloween2016 extends Halloween +{ + + private List _pumpkins = new ArrayList<>(); + private Crypt _crypt; + + private Animator _introAnimator; + + private int _maxPumplings = 30; + private int _maxNonPumplings = 65; + + private double _mobCapMultiplier = 1; + private int _defaultMaxPlayerCount = 16; + + private List _pumplings = new ArrayList<>(); + private List> _nonPumplings = new ArrayList<>(); + + private List> _lanes = new ArrayList<>(); + + private Location _cryptView; + + private Location _lockAllPlayers = null; + private Map> _playerPreLockData = new HashMap<>(); + + private static boolean DO_TUTORIALS = true; + + public Halloween2016(ArcadeManager manager) + { + super(manager, GameType.Halloween2016, + new Kit[] + { + new KitFinn(manager), + new KitRobinHood(manager), + new KitThor(manager) + }, + new String[] + { + "Do not die.", + "Work as a team!", + "Defeat the waves of monsters", + "Kill the Pumpkin Prince", + "Destroy pumpkins by hitting them 3 times", + "Protect the crypt!" + } + ); + + _help = new String[] + { + C.cGreen + "Giants one hit kill you! Stay away!!!", + C.cAqua + "Work together with your teammates.", + C.cGreen + "Each kit gives a buff to nearby allies.", + C.cAqua + "Kill monsters to keep their numbers down.", + C.cGreen + "Giants instantly destroy the crypt! Kill them quickly!", + C.cAqua + "Defend your teammates from monsters.", + C.cGreen + "Zombies, Giants and Spiders get faster over time.", + C.cAqua + "Stick together to survive.", + C.cGreen + "The Pumpkin Prince gets harder over time!", + C.cAqua + "Protect the crypt to not lose the game!", + C.cGreen + "Pumplings spawn from pumpkins. Hit the pumpkins 3 times to prevent it from spawning.", + }; + + _updateCreatureMoveRate = UpdateType.TICK; + EnableTutorials = DO_TUTORIALS; + + doVoices = false; + } + + public void setObjective(String objective) + { + Objective = objective; + Announce(F.main("Objective", C.cYellow + C.Bold + objective)); + } + + public void unlockAllPlayers() + { + if(_lockAllPlayers == null) return; + + _lockAllPlayers = null; + for(Entry> e : _playerPreLockData.entrySet()) + { + e.getKey().teleport(e.getValue().getKey()); + e.getKey().setGameMode(e.getValue().getValue()); + if(IsAlive(e.getKey())) + { + UtilPlayer.showForAll(e.getKey()); + } + } + _playerPreLockData.clear(); + + Manager.getCosmeticManager().setHideParticles(false); + } + + public void lockAllPlayers(Location loc) + { + unlockAllPlayers(); + + _lockAllPlayers = loc; + + Manager.getCosmeticManager().setHideParticles(true); + } + + @EventHandler + public void lockPlayerTask(UpdateEvent event) + { + if(event.getType() != UpdateType.TICK) return; + + if(_lockAllPlayers != null) + { + for(Player p : Bukkit.getOnlinePlayers()) + { + if(!_playerPreLockData.containsKey(p)) + { + _playerPreLockData.put(p, new Pair(p.getLocation(), p.getGameMode())); + p.setGameMode(GameMode.SPECTATOR); + } + p.teleport(_lockAllPlayers); + if(IsAlive(p)) + { + UtilPlayer.hideFromAll(p); + } + } + } + } + + @EventHandler + @Override + public void onGameStart(GameStateChangeEvent event) + { + super.onGameStart(event); + + if(event.GetState() != GameState.Live) return; + + _mobCapMultiplier = (double) GetPlayers(true).size() / (double) _defaultMaxPlayerCount; + if(_mobCapMultiplier < 0.5) + { + _mobCapMultiplier = 0.5; + } + + _maxNonPumplings *= _mobCapMultiplier; + _maxPumplings *= _mobCapMultiplier; + _maxMobs *= _mobCapMultiplier; + } + + public int getMaxPumplings() + { + return _maxPumplings; + } + + public void setMaxPumplings(int maxPumplings) + { + _maxPumplings = maxPumplings; + } + + @Override + public void ParseData() + { + List schematics = new ArrayList<>(); + Location doorSchematicLocation = getDoorSchematicLocation(); + _crypt = new Crypt(this, getDoorSchematicLocation(), schematics); + + for(Location loc : getPumkinSpawns()) + { + _pumpkins.add(new PumpkinPlant(this, loc)); + } + + _lanes.add(getBackLane()); + _lanes.add(getLeftLane()); + _lanes.add(getRightLane()); + _lanes.add(getMainLane()); + _lanes.add(getGraveLane()); + + _waves = new ArrayList<>(); + _waves.add(new Wave1(this)); + _waves.add(new Wave2(this)); + _waves.add(new Wave3(this)); + _waves.add(new Wave4(this)); + _waves.add(new Wave5(this)); + _waves.add(new WaveBoss(this)); + _waves.add(new WaveVictory(this, getMobSpawns())); + + _spawns = new ArrayList<>(); + + + CreatureAllowOverride = true; + ArmorStand bat = doorSchematicLocation.getWorld().spawn(doorSchematicLocation, ArmorStand.class); + CreatureAllowOverride = false; + UtilEnt.Vegetate(bat, true); + UtilEnt.setAI(bat, false); + UtilEnt.setTickWhenFarAway(bat, true); + bat.setRemoveWhenFarAway(false); + bat.setVisible(false); + + _introAnimator = new Animator(Manager.getPlugin()) + { + private int _tick = 0; + @Override + protected void tick(Location loc) + { + if(loc == null) return; + + for(Player p : Halloween2016.this.GetPlayers(false)) + { + if(p.getGameMode() != GameMode.SPECTATOR) p.setGameMode(GameMode.SPECTATOR); + if(!p.getAllowFlight()) p.setAllowFlight(true); + if(!p.isFlying()) p.setFlying(true); + + if(_tick%3 == 0) p.teleport(loc); + } + + _tick++; + } + + @Override + protected void finish(Location loc) + {} + }; + + _cryptView = WorldData.GetCustomLocs("CryptView").get(0); + _cryptView.setDirection(getClosest(_cryptView, "PINK").subtract(_cryptView).toVector()); + + AnimatorFactory factory = new AnimatorFactory(); + + double lastEntry = 0; + double firstEntry = Double.MAX_VALUE; + Location first = null; + + for(Entry> point : WorldData.GetAllCustomLocs().entrySet()) + { + String[] args = point.getKey().split(" "); + if(args.length < 2) continue; + if(args[0].equals("Intro")) + { + try + { + double sec = Double.parseDouble(args[1]); + double delay = 0; + try + { + delay = Double.parseDouble(args[2]); + } + catch(Exception e1) {} + int tick = (int) (sec*20); + int tickdelay = (int) (delay*20); + + Location loc = point.getValue().get(0); + Location lookingAt = getClosest(loc, "PINK"); + + loc.setDirection(lookingAt.subtract(loc).toVector()); + + factory.addLocation(loc, tick); + if(tickdelay > 0) factory.addLocation(loc, tickdelay); + + if(sec > lastEntry) lastEntry = sec; + if(delay > lastEntry) lastEntry = delay; + + if(sec < firstEntry) + { + firstEntry = sec; + first = loc.clone(); + } + } + catch(Exception e2) {} + } + } + + System.out.print("Scanned " + WorldData.GetAllCustomLocs().entrySet().size() + " data points"); + + List animation = factory.getBuildList(first); + _introAnimator.addPoints(animation); + + System.out.println("Loaded intro animation with " + _introAnimator.getSet().size() + " | " + animation.size() + " points and duration of " + lastEntry + "s"); + + GameTeam team = GetTeamList().get(0); + team.setTutorial(new TutorialHalloween2016(this, _introAnimator, team, first, (int) (lastEntry * 20))); + } + + public Location getInfrontOfCrypt() + { + return WorldData.GetCustomLocs("PumpkinKing Win").get(0).clone(); + } + + public Location getPrinceTargetInfrontOfCrypt() + { + return WorldData.GetCustomLocs("PrinceTarget").get(0).clone(); + } + + public Location getPrinceSpawn() + { + return WorldData.GetCustomLocs("PrinceSpawn").get(0).clone(); + } + + + public Location getClosest(Location loc, String dataSet) + { + Location c = null; + double dist = 0; + for(Location l : WorldData.GetDataLocs(dataSet)) + { + double ldist = loc.distanceSquared(l); + if(c == null || ldist <= dist) + { + c = l; + dist = ldist; + } + } + if(c == null) return null; + return c.clone(); + } + + public Crypt getCrypt() + { + return _crypt; + } + + public Location getGiantSpawn() + { + return getMainLane().get(UtilMath.r(getMainLane().size())); + } + + public List getMainLane() + { + return WorldData.GetDataLocs("RED"); + } + + public List getLeftLane() + { + return WorldData.GetDataLocs("MAGENTA"); + } + + public List getBackLane() + { + return WorldData.GetDataLocs("LIGHT_BLUE"); + } + + public List getRightLane() + { + return WorldData.GetDataLocs("YELLOW"); + } + + public List getGraveLane() + { + return WorldData.GetDataLocs("MAGENTA"); + } + + public List getRandomLane() + { + List lane = new ArrayList<>(); + lane.addAll(_lanes.get(UtilMath.r(_lanes.size()))); + return lane; + } + + public List getMobSpawns() + { + List list = new ArrayList<>(); + for(List lane : _lanes) + { + list.addAll(lane); + } + return list; + } + + public List getPumkinSpawns() + { + return new ArrayList<>(WorldData.GetDataLocs("ORANGE")); + } + + public List getInfrontOfDoorTargets() + { + return new ArrayList<>(WorldData.GetDataLocs("BLUE")); + } + + public Location getDoorSchematicLocation() + { + return WorldData.GetCustomLocs("Door Schematic Paste").get(0).clone(); + } + + @EventHandler + public void updatePumpkinPlants(UpdateEvent event) + { + if(!IsLive()) return; + + if(event.getType() != UpdateType.TICK) return; + + List notGrowing = new ArrayList<>(); + int growing = 0; + for(PumpkinPlant plant : _pumpkins) + { + if(plant.isGrowing()) + { + growing++; + } + else + { + notGrowing.add(plant); + } + plant.tick(); + } + + if(!notGrowing.isEmpty() && growing + getPumplings().size() < getMaxPumplings()) + { + notGrowing.get(UtilMath.r(notGrowing.size())).startGrow(); + } + } + + public Location getCryptView() + { + return _cryptView.clone(); + } + + + @Override + @EventHandler + public void WaveUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + return; + + if (!IsLive()) + return; + + if(_crypt.isDestroyed() && !(_waves.get(_wave) instanceof WaveBoss) && !(_waves.get(_wave) instanceof WaveVictory)) + { + for(CreatureBase c : _mobs) + { + c.remove(); + } + + Announce(F.main("Objective", C.cRed + C.Bold + "Objective failed!")); + endGame(GetTeam(ChatColor.RED)); + + return; + } + + super.WaveUpdate(event); + } + + + @EventHandler + public void onUpdateCrypt(UpdateEvent event) + { + if(event.getType() != UpdateType.TICK) return; + if(!IsLive()) return; + if(_crypt.isDestroyed()) return; + _crypt.updateHealthDisplay(); + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) + { + if(event.getAction() != Action.LEFT_CLICK_BLOCK) return; + if(event.getClickedBlock() == null) return; + + Block block = event.getClickedBlock(); + + for(PumpkinPlant plant : _pumpkins) + { + plant.hit(block); + } + } + + @Override + public void AddCreature(CreatureBase mob) + { + AddCreature(mob, true); + } + + public void AddCreature(CreatureBase mob, boolean cap) + { + super.AddCreature(mob); + if(!cap) return; + + if(mob instanceof MobPumpling) + { + _pumplings.add((MobPumpling) mob); + } + else + { + _nonPumplings.add(mob); + } + } + + public List getPumplings() + { + return _pumplings; + } + + public List> getNonPumplings() + { + return _nonPumplings; + } + + + public int getMaxNonPumplings() + { + return _maxNonPumplings; + } + + @Override + public void onRemove(CreatureBase mob) + { + _pumplings.remove(mob); + _nonPumplings.remove(mob); + } + + + @EventHandler + public void onCommand(PlayerCommandPreprocessEvent event) + { + if(!UtilServer.isTestServer()) return; + + + String[] args = event.getMessage().split(" "); + boolean orig = event.isCancelled(); + event.setCancelled(true); + if(args[0].equalsIgnoreCase("/setwave")) + { + if(event.getMessage().matches("/setwave [0-9]+")) + { + Announce(event.getPlayer().getName() + " set wave to " + args[1], true); + _wave = Integer.parseInt(args[1]); + } + else + { + event.getPlayer().sendMessage("Use /setwave #Wave"); + } + } + else if(args[0].equalsIgnoreCase("/god")) + { + Announce(event.getPlayer().getName() + " made everyone 'gods'", true); + for(Player p : GetPlayers(false)) + { + p.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 99999, 200, true, false), true); + p.addPotionEffect(new PotionEffect(PotionEffectType.SATURATION, 99999, 200, true, false), true); + p.addPotionEffect(new PotionEffect(PotionEffectType.NIGHT_VISION, 99999, 200, true, false), true); + } + } + else if(args[0].equalsIgnoreCase("/degod")) + { + Announce(event.getPlayer().getName() + " made everyone no longer 'gods'", true); + for(Player p : GetPlayers(false)) + { + p.removePotionEffect(PotionEffectType.REGENERATION); + p.removePotionEffect(PotionEffectType.SATURATION); + p.removePotionEffect(PotionEffectType.NIGHT_VISION); + } + } + else if(args[0].equals("/tutorial")) + { + if(args.length != 2) + { + event.getPlayer().sendMessage("Use /tutorial - true = tutorial enabled before game"); + return; + } + if(args[1].equalsIgnoreCase("true") || args[1].equalsIgnoreCase("on")) + { + DO_TUTORIALS = true; + Announce(event.getPlayer().getName() + " enabled tutorials before games starts"); + } + else if(args[1].equalsIgnoreCase("false") || args[1].equalsIgnoreCase("off")) + { + DO_TUTORIALS = false; + Announce(event.getPlayer().getName() + " disabled tutorials before games starts"); + } + else + { + event.getPlayer().sendMessage("Use /tutorial - true = tutorial enabled before game"); + } + + EnableTutorials = DO_TUTORIALS; + } + else + { + event.setCancelled(orig); + } + } + + @EventHandler + public void onDeath(EntityDeathEvent event) + { + if(event.getEntity().getKiller() != null) + { + AddGems(event.getEntity().getKiller(), 0.2, "Mobs Killed", true, true); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void Clean(GameStateChangeEvent event) + {} + + @Override + @EventHandler(priority = EventPriority.MONITOR) + public void TeamGen(GameStateChangeEvent event) + { + if (event.GetState() != GameState.Live) + return; + + GetTeamList().add(new GameTeam(this, "Pumpkin Prince", ChatColor.RED, WorldData.GetDataLocs("RED"))); + } + + @Override + public void EndCheck() + { + if (!IsLive()) + return; + + if (_wave >= _waves.size()) + { + for (Player player : GetPlayers(false)) + { + Manager.GetGame().AddGems(player, 30, "Killing the Pumpkin Prince", false, false); + Manager.GetGame().AddGems(player, 10, "Participation", false, false); + } + + if (Manager.IsRewardItems()) + { + SetCustomWinLine("You earned the Grim Reaper Pet!"); + + for (Player player : GetPlayers(false)) + { + //Prevent game hopping + if (!player.isOnline()) + continue; + + PetReward pr = new PetReward(Manager.getCosmeticManager().getPetManager(), Manager.getInventoryManager(), Manager.GetDonation(), "Grim Reaper", "Grim Reaper", EntityType.BLAZE, RewardRarity.OTHER, 0, 0); + + if (pr.canGiveReward(player)) + { + pr.giveReward(null, player, data -> {}); + } + } + } + + AnnounceEnd(this.GetTeamList().get(0)); + + SetState(GameState.End); + } + + else if (GetPlayers(true).size() == 0) + { + for (Player player : GetPlayers(false)) + { + Manager.GetGame().AddGems(player, 10, "Participation", false, false); + } + + AnnounceEnd(this.GetTeamList().get(1)); + + SetState(GameState.End); + } + } + + + + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/PumpkinPlant.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/PumpkinPlant.java new file mode 100644 index 000000000..0b2a18ad9 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/PumpkinPlant.java @@ -0,0 +1,107 @@ +package nautilus.game.arcade.game.games.halloween2016; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.material.MaterialData; + +import nautilus.game.arcade.game.games.halloween2016.creatures.MobPumpling; + +public class PumpkinPlant +{ + + /** + * Defines how fast the pumpkin is going to blink. the closer to 1, the faster the blinking. + */ + private static final double BLINK_SPEED = 0.95; + + private Halloween2016 _game; + + private int _growTicksTotal = 30 * 20; + private int _growTick; + private int _sleep; + private Block _growing = null; + private int _health; + + public PumpkinPlant(Halloween2016 game, Location loc) + { + _growing = loc.getBlock(); + _game = game; + } + + public void startGrow() + { + if(isGrowing()) return; + + _growing.setType(Material.PUMPKIN); + + _growTick = _growTicksTotal; + _sleep = _growTick; + _health = 3; + } + + public boolean isGrowing() + { + return _growing != null &&_growing.getType() != Material.AIR; + } + + public void tick() + { + if(!isGrowing()) return; + + if(_sleep > _growTick) + { + _sleep *= BLINK_SPEED; + Material old = _growing.getType(); + _growing.setType(old == Material.PUMPKIN ? Material.JACK_O_LANTERN : Material.PUMPKIN); + } + _growTick--; + + if(_growTick == 0) + { + spawn(); + } + } + + public void spawn() + { + _growing.setType(Material.AIR); + _growTick = 0; + _sleep = 0; + + Location loc = _growing.getLocation().add(0.5, 0, 0.5); + + _game.AddCreature(new MobPumpling(_game, loc)); + + loc.getWorld().playEffect(loc, Effect.LARGE_SMOKE, 4); + } + + public void hit(Block block) + { + if(block.equals(_growing)) + { + _health--; + + Location loc = _growing.getLocation().add(0.5, 0, 0.5); + + if(_health <= 0) + { + _growing.setType(Material.AIR); + _growTick = 0; + _sleep = 0; + + + loc.getWorld().playEffect(loc, Effect.TILE_BREAK, new MaterialData(Material.PUMPKIN)); + + _growing = null; + } + else + { + loc.getWorld().playSound(loc, Sound.DIG_WOOL, 1, 1); + } + } + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/CryptBreaker.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/CryptBreaker.java new file mode 100644 index 000000000..5dd31ea1c --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/CryptBreaker.java @@ -0,0 +1,256 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.Creature; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityTargetEvent; + +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import nautilus.game.arcade.game.games.halloween.creatures.CreatureBase; +import nautilus.game.arcade.game.games.halloween.creatures.InterfaceMove; +import nautilus.game.arcade.game.games.halloween2016.Crypt; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; +import net.minecraft.server.v1_8_R3.PacketPlayOutAnimation; + +public abstract class CryptBreaker extends CreatureBase implements InterfaceMove +{ + + protected final Crypt _crypt; + protected final List _doorLocations = new ArrayList<>(); + + protected final int _cryptDamage; + protected final int _cryptDamageRate; + + protected double _playerTargetForwardRange = 4; + protected double _playerTargetBackRange = 1; + protected double _playerFollowRange = 5; + + protected double _customCryptRange = -1; + + protected double _extraDamage; + + protected float _speed; + + protected boolean _targetPlayers = true; + + protected Halloween2016 Host16; + + public CryptBreaker(Halloween2016 game, String name, Class mobClass, Location loc, int cryptDamage, int cryptDamageRate, float speed) + { + super(game, name, mobClass, loc); + _crypt = game.getCrypt(); + _doorLocations.addAll(game.getInfrontOfDoorTargets()); + _cryptDamage = cryptDamage; + _cryptDamageRate = cryptDamageRate; + _speed = speed; + Host16 = game; + + Creature ent = GetEntity(); + UtilEnt.setTickWhenFarAway(ent, true); + ent.setRemoveWhenFarAway(false); + } + + @Override + public void SpawnCustom(T ent) + {} + + @Override + public void Update(UpdateEvent event) + { + if(event.getType() != UpdateType.TICK) return; + + if(inCryptRange()) + { + attackCrypt(); + } + } + + public boolean inCryptRange() + { + double width = UtilEnt.getWidth(GetEntity()); + if(_customCryptRange != -1) + { + width = _customCryptRange; + } + + if(getClosestDoor().distanceSquared(GetEntity().getLocation()) <= width*width) + { + return true; + } + return false; + } + + public void attackCrypt() + { + if(!_crypt.tryDamage(GetEntity(), _cryptDamage, _cryptDamageRate)) return; + + GetEntity().getWorld().playSound(GetEntity().getLocation(), Sound.ZOMBIE_WOODBREAK, 1, 0.7f + UtilMath.random.nextFloat() * 0.5f); + swingArms(); + } + + public void swingArms() + { + PacketPlayOutAnimation packet = new PacketPlayOutAnimation(); + packet.a = GetEntity().getEntityId(); + packet.b = 0; + + for(Player p : Host.GetPlayers(false)) + { + UtilPlayer.sendPacket(p, packet); + } + } + + @Override + public void Damage(CustomDamageEvent event) + { + if(_extraDamage > 0) + { + if(GetEntity().equals(event.GetDamagerEntity(true))) + { + event.AddMod("Mod", _extraDamage); + } + } + } + + @Override + public void Target(EntityTargetEvent event) + { + if(_crypt.isDestroyed()) return; + + if(!event.getEntity().equals(GetEntity())) return; + if(event.getTarget() == null) return; + + if(!_targetPlayers) + { + event.setCancelled(true); + return; + } + + if(!(event.getTarget() instanceof Player)) + { + event.setCancelled(true); + return; + } + + if(inCryptRange()) + { + event.setCancelled(true); + return; + } + + Location door = getClosestDoor(); + Location target = event.getTarget().getLocation(); + if(target.distanceSquared(door) - _playerTargetBackRange*_playerTargetBackRange > door.distanceSquared(GetEntity().getLocation())) + { + event.setCancelled(true); + return; + } + if(target.distanceSquared(GetEntity().getLocation()) <= _playerTargetForwardRange*_playerTargetForwardRange) + { + event.setCancelled(true); + return; + } + } + + @Override + public Location GetRoamTarget() + { + if(_crypt.isDestroyed()) return GetPlayerTarget(); + + Location door = getClosestDoor(); + double distDoor = door.distanceSquared(GetEntity().getLocation()); + + if(!_targetPlayers) return door; + + Player player = null; + double distance = -1; + + for(Player p : Host.GetPlayers(true)) + { + if(p.getLocation().distanceSquared(door) - _playerTargetBackRange*_playerTargetBackRange > distDoor) continue; + + double dist = GetEntity().getLocation().distanceSquared(p.getLocation()); + if(player == null || dist < distance) + { + player = p; + distance = dist; + } + } + + if(player != null && distance <= _playerTargetForwardRange*_playerTargetForwardRange) + { + GetEntity().setTarget(player); + return player.getLocation(); + } + + return door; + } + + @Override + public void Move() + { + if(_crypt.isDestroyed()) + { + CreatureMove(GetEntity()); + return; + } + + Location door = getClosestDoor(); + double distDoor = door.distanceSquared(GetEntity().getLocation()); + if(GetEntity().getTarget() != null) + { + Location target = GetEntity().getTarget().getLocation(); + if(target.distanceSquared(door) - _playerFollowRange*_playerFollowRange > distDoor) + { + GetEntity().setTarget(null); + SetTarget(GetRoamTarget()); + } + } + + if(GetEntity().getTarget() == null) + { + SetTarget(GetRoamTarget()); + } + + if(_customCryptRange > 0) + { + if(distDoor <= _customCryptRange*_customCryptRange) + { + SetTarget(GetEntity().getLocation()); + } + } + + if(GetTarget() != null) + { + UtilEnt.CreatureMove(GetEntity(), GetTarget(), _speed); + Host.moves++; + } + } + + public Location getClosestDoor() + { + Location loc = GetEntity().getLocation(); + Location door = null; + double dist = -1; + for(Location d : _doorLocations) + { + double testDist = d.distanceSquared(loc); + if(door == null || testDist < dist) + { + door = d; + dist = testDist; + } + } + return door.clone(); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobBlaze.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobBlaze.java new file mode 100644 index 000000000..af79dd420 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobBlaze.java @@ -0,0 +1,23 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import org.bukkit.Location; +import org.bukkit.entity.Blaze; + +import mineplex.core.common.util.C; + +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; + +public class MobBlaze extends CryptBreaker +{ + + private static int CRYPT_DAMAGE = 10; + private static int CRYPT_RATE = 30; + + private static float SPEED = 1; + + public MobBlaze(Halloween2016 game, Location loc) + { + super(game, C.cYellow + "Blaze", Blaze.class, loc, CRYPT_DAMAGE, CRYPT_RATE, SPEED); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobCreeper.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobCreeper.java new file mode 100644 index 000000000..01af9bb08 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobCreeper.java @@ -0,0 +1,83 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import java.lang.reflect.Method; + +import net.minecraft.server.v1_8_R3.EntityCreeper; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftCreeper; +import org.bukkit.entity.Creeper; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilReflection; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; + +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; + +public class MobCreeper extends CryptBreaker +{ + + public static final int CRYPT_DAMAGE = 200; + public static float SPEED = 0.8f; + + private boolean exploded = false; + + public MobCreeper(Halloween2016 game, Location loc) + { + super(game, C.cYellow + "Creeper", Creeper.class, loc, 0, 0, SPEED); + + _extraDamage = 5; + + _targetPlayers = false; + } + + + @Override + public void Update(UpdateEvent event) + { + if(event.getType() != UpdateType.TICK) return; + + if(_crypt.isDestroyed()) return; + + double width = UtilEnt.getWidth(GetEntity()); + + EntityCreeper c = ((CraftCreeper)GetEntity()).getHandle(); + if(getClosestDoor().distanceSquared(GetEntity().getLocation()) <= width*width) + { + c.co(); + } + + int fuse = (int) UtilReflection.getValueOfField(c, "fuseTicks"); + int max = (int) UtilReflection.getValueOfField(c, "maxFuseTicks"); + + if(fuse >= max-1) + { + _crypt.tryDamage(GetEntity(), CRYPT_DAMAGE, 0); + exploded = true; + } + } + + @Override + public void remove() + { + if(!exploded && GetEntity().isDead()) + { + //Make creeper explode, even if dead using NMS code + try + { + EntityCreeper nms = ((CraftCreeper)GetEntity()).getHandle(); + Method explodeMethod = nms.getClass().getDeclaredMethod("cr"); + explodeMethod.setAccessible(true); + explodeMethod.invoke(nms); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + super.remove(); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobGiant.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobGiant.java new file mode 100644 index 000000000..6f6a41af4 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobGiant.java @@ -0,0 +1,190 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.Giant; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilText; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; + +public class MobGiant extends CryptBreaker +{ + + //Instant destroy crypt + public static final int CRYPT_DAMAGE = 100000; + public static final int CRYPT_DAMAGE_COOLDOWN = 1; + public static final float SPEED = 0.5f; + + private static double DAMAGE = 9000; + private static double KNOCKBACK = 8; + private static double HEALTH = 200; + + private static float EXTRA_EXPLOSION_DAMAGE = 10; + + private boolean _cryptDestroyed = false; + + private Zombie _pathDummy; + + private Player _target; + + public MobGiant(Halloween2016 game, Location loc) + { + super(game, null, Giant.class, loc, CRYPT_DAMAGE, CRYPT_DAMAGE_COOLDOWN, SPEED); + + _customCryptRange = 3; + } + + @Override + public void SpawnCustom(Giant ent) + { + _pathDummy = ent.getWorld().spawn(ent.getLocation(), Zombie.class); + + super.Host.Manager.GetCondition().Factory().Invisible("Cloak", _pathDummy, _pathDummy, 999999, 0, false, false, false); + _pathDummy.setCustomNameVisible(true); + + ent.setMaxHealth(HEALTH); + ent.setHealth(ent.getMaxHealth()); + + UtilEnt.setBoundingBox(_pathDummy, 0, 0); + UtilEnt.Vegetate(_pathDummy, true); + UtilEnt.setStepHeight(_pathDummy, 1); + + //Prevent other mobs from pushing the giant + UtilEnt.ghost(_pathDummy, true, true); + + _pathDummy.setRemoveWhenFarAway(false); + UtilEnt.setTickWhenFarAway(_pathDummy, true); + + addEntityPart(_pathDummy); + } + + @Override + public void Update(UpdateEvent event) + { + if(event.getType() == UpdateType.TICK) + { + move(); + updateHealthBar(); + } + + if(!_cryptDestroyed && _crypt.isDestroyed()) + { + SetTarget(null); + _cryptDestroyed = true; + } + + } + + private Player getRandomPlayer() + { + List players = Host.GetPlayers(true); + return players.get(UtilMath.r(players.size())); + } + + private void move() + { + if(_target != null) + { + if(!_target.isOnline() || !_target.isValid() || !Host.GetPlayers(true).contains(_target)) + { + _target = null; + } + } + + Location target = GetTarget(); + if(target == null && _target == null) + { + if(_crypt.isDestroyed()) + { + _target = getRandomPlayer(); + } + else + { + target = getClosestDoor(); + + } + SetTarget(target); + } + if(_target != null) + { + target = _target.getLocation(); + } + UtilEnt.CreatureMove(_pathDummy, target, SPEED); + GetEntity().teleport(_pathDummy); + + if(!_crypt.isDestroyed()) + { + if(getClosestDoor().distanceSquared(GetEntity().getLocation()) <= _customCryptRange*_customCryptRange) + { + if(!_crypt.tryDamage(GetEntity(), _cryptDamage, _cryptDamageRate)) return; + + GetEntity().getWorld().playSound(GetEntity().getLocation(), Sound.ZOMBIE_WOODBREAK, 1, 0.7f + UtilMath.random.nextFloat() * 0.5f); + swingArms(); + } + } + + boolean hit = false; + + for(Player p : getInsideBoundingBox()) + { + Host.getArcadeManager().GetDamage().NewDamageEvent(p, GetEntity(), null, GetEntity().getLocation(), DamageCause.ENTITY_ATTACK, DAMAGE, true, false, false, "Giant", "Giant Damage", false); + hit = true; + } + if(hit) + { + swingArms(); + GetEntity().getWorld().playSound(GetEntity().getLocation(), Sound.ZOMBIE_IDLE, 2, 0.5f); + } + } + + @Override + public void Move() + {} + + @Override + public void Damage(CustomDamageEvent event) + { + if(_pathDummy.equals(event.GetDamageeEntity())) + { + event.SetCancelled("Invalid Entity"); + return; + } + if(event.GetDamageeEntity().equals(GetEntity())) + { + event.SetKnockback(false); + + if(event.GetCause() == DamageCause.SUFFOCATION) + { + event.SetCancelled("Invalid Giant Damage"); + return; + } + else if(event.GetCause() == DamageCause.ENTITY_EXPLOSION) + { + event.AddMod("Explosion", EXTRA_EXPLOSION_DAMAGE); + } + } + + if(!GetEntity().equals(event.GetDamagerEntity(false))) return; + + event.SetKnockback(true); + event.AddKnockback("Giant Knockback", KNOCKBACK); + } + + public void updateHealthBar() + { + _pathDummy.setCustomName(UtilText.getProgress(C.cGreen, GetEntity().getHealth()/GetEntity().getMaxHealth(), C.cGray, false)); + } + + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobMiniZombie.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobMiniZombie.java new file mode 100644 index 000000000..63a4bad70 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobMiniZombie.java @@ -0,0 +1,70 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.Zombie; +import org.bukkit.event.entity.EntityTargetEvent; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +import nautilus.game.arcade.game.games.halloween.Halloween; +import nautilus.game.arcade.game.games.halloween.creatures.CreatureBase; +import nautilus.game.arcade.game.games.halloween.creatures.InterfaceMove; + +public class MobMiniZombie extends CreatureBase implements InterfaceMove +{ + + private static final double HEALTH = 5; + + public MobMiniZombie(Halloween game, Location loc) + { + super(game, C.cYellow + "Baby Zombie", Zombie.class, loc); + } + + @Override + public void SpawnCustom(Zombie ent) + { + ent.setBaby(true); + + ent.setMaxHealth(HEALTH); + ent.setHealth(HEALTH); + } + + @Override + public void Update(UpdateEvent event) + { + + } + + @Override + public void Damage(CustomDamageEvent event) + { + + } + + @Override + public void Target(EntityTargetEvent event) + { + + } + + @Override + public void Move() + { + CreatureMove(GetEntity(), 1f); + } + + @Override + public void remove() + { + super.remove(); + UtilParticle.PlayParticleToAll(ParticleType.LARGE_SMOKE, GetEntity().getLocation(), null, 0.1f, 10, ViewDist.NORMAL); + GetEntity().getWorld().playSound(GetEntity().getLocation(), Sound.FIZZ, 0.8f, 0.3f); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPigZombie.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPigZombie.java new file mode 100644 index 000000000..369f7e102 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPigZombie.java @@ -0,0 +1,72 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.C; +import mineplex.core.disguise.disguises.DisguisePigZombie; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; + +public class MobPigZombie extends CryptBreaker +{ + + private static float SPEED = 1; + private static int CRYPT_DAMAGE = 3; + private static int CRYPT_RATE = 20; + + private static int FIRE_TICKS = 60; + + public MobPigZombie(Halloween2016 game, Location loc) + { + super(game, C.cYellow + "Pigman Warrior", Zombie.class, loc, CRYPT_DAMAGE, CRYPT_RATE, SPEED); + + _extraDamage = 5; + } + + @Override + public void SpawnCustom(Zombie ent) + { + ent.getEquipment().setItemInHand(new ItemStack(Material.GOLD_SWORD)); + + DisguisePigZombie disg = new DisguisePigZombie(ent); + Host.getArcadeManager().GetDisguise().disguise(disg); + } + + @Override + public void Update(UpdateEvent event) + { + super.Update(event); + if(event.getType() == UpdateType.TICK) + { + GetEntity().setFireTicks(5); + } + } + + @Override + public void Damage(CustomDamageEvent event) + { + if(event.GetDamageeEntity() instanceof Player) + { + if(GetEntity().equals(event.GetDamagerEntity(false))) + { + event.GetDamageeEntity().setFireTicks(FIRE_TICKS); + } + } + + else if(GetEntity().equals(event.GetDamageeEntity())) + { + if(event.GetCause() == DamageCause.FIRE || event.GetCause() == DamageCause.FIRE_TICK) + { + event.SetCancelled("Cancel Fire"); + } + } + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPrinceGuard.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPrinceGuard.java new file mode 100644 index 000000000..36c04abfa --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPrinceGuard.java @@ -0,0 +1,236 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import java.util.List; + +import net.minecraft.server.v1_8_R3.PacketPlayOutAnimation; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Horse.Variant; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.entity.Zombie; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityTargetEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; +import org.spigotmc.event.entity.EntityDismountEvent; + +import mineplex.core.common.util.C; +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.disguise.disguises.DisguiseHorse; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +import nautilus.game.arcade.game.games.halloween.Halloween; +import nautilus.game.arcade.game.games.halloween.creatures.CreatureBase; + +public class MobPrinceGuard extends CreatureBase +{ + + private Zombie _horse; + private DisguiseHorse _horseDisguise; + + private MobPumpkinPrince _prince; + private Entity _target; + + private Location _strikeTarget; + private long _strikeStamp; + + private boolean _AI = true; + + private final static float HORSE_SPEED = 1.8f; + private final static float HORSE_SPEED_CHARGE = 2.3f; + private final static double STRIKE_RANGE = 10; + private final static long MAX_STRIKE_TIME = 10_000; + private final static long STRIKE_COOLDOWN = 15_000; + private final static double DAMAGE = 5; + private final static double KNOCKBACK = 3; + private final static double HEALTH = 50; + + public MobPrinceGuard(Halloween game, Location loc, MobPumpkinPrince prince) + { + super(game, C.cYellow + C.Bold + "Prince Guard", Skeleton.class, loc); + _prince = prince; + } + + public Zombie getHorse() + { + return _horse; + } + + @Override + public void SpawnCustom(Skeleton ent) + { + ent.getEquipment().setItemInHand(new ItemStack(Material.IRON_SWORD)); + ent.getEquipment().setHelmet(new ItemStack(Material.PUMPKIN)); + + _horse = ent.getWorld().spawn(ent.getLocation(), Zombie.class); + + _horseDisguise = new DisguiseHorse(_horse); + _horseDisguise.setType(Variant.SKELETON_HORSE); + Host.getArcadeManager().GetDisguise().disguise(_horseDisguise); + + _horse.setRemoveWhenFarAway(false); + UtilEnt.setTickWhenFarAway(_horse, true); + + UtilEnt.setStepHeight(_horse, 1); + UtilEnt.setBoundingBox(_horse, 0, 0); + + UtilEnt.setTickWhenFarAway(ent, true); + ent.setRemoveWhenFarAway(true); + + ent.setMaxHealth(HEALTH); + ent.setHealth(ent.getMaxHealth()); + + _horse.setPassenger(ent); + + _horse.setVegetated(true); + //UtilEnt#silence doesn't seem to work. Using native silence instead + ((CraftEntity)_horse).getHandle().b(true); + + addEntityPart(_horse); + } + + public void setAI(boolean aI) + { + _AI = aI; + } + + public boolean getAI() + { + return _AI; + } + + @Override + public void Update(UpdateEvent event) + { + if(event.getType() != UpdateType.TICK) return; + + if(!_AI) return; + + if(_strikeTarget != null) + { + if(_strikeStamp < System.currentTimeMillis()) + { + _strikeTarget = null; + } + else if(UtilEnt.canEntityWalkCloserToNavigationTarget(_horse)) + { + _strikeTarget = null; + return; + } + else + { + _horse.getWorld().playSound(_horse.getLocation(), Sound.FIZZ, 0.2f, 1f); + _horse.getWorld().playSound(_horse.getLocation(), Sound.SKELETON_WALK, 0.2f, 0.5f); + + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, _horse.getLocation(), null, 0.1f, 5, ViewDist.NORMAL); + UtilParticle.PlayParticleToAll(ParticleType.FLAME, _horse.getLocation(), null, 0.1f, 5, ViewDist.NORMAL); + } + } + + List inGame = Host.GetPlayers(true); + if(_target == null || !inGame.contains(_target)) + { + double dist = 0; + for(Player p : inGame) + { + double d = p.getLocation().distanceSquared(_prince.getHorse().getLocation()); + if(_target == null || dist > d) + { + dist = d; + _target = p; + } + } + } + Location target = _target.getLocation(); + Vector diff = target.clone().subtract(_horse.getLocation()).toVector(); + if(_strikeStamp + STRIKE_COOLDOWN > System.currentTimeMillis() || diff.lengthSquared() >= STRIKE_RANGE*STRIKE_RANGE) + { + diff.normalize().multiply(STRIKE_RANGE*2); + target.add(diff); + SetTarget(target); + + UtilEnt.CreatureMove(_horse, GetTarget(), HORSE_SPEED); + } + else + { + _target = null; + + _strikeTarget = target; + _strikeStamp = System.currentTimeMillis() + MAX_STRIKE_TIME; + + UtilEnt.CreatureMove(_horse, GetTarget(), HORSE_SPEED_CHARGE); + } + + for(Player p : getInsideBoundingBox()) + { + Host.getArcadeManager().GetDamage().NewDamageEvent(p, _horse, null, _horse.getLocation(), DamageCause.ENTITY_ATTACK, DAMAGE, true, false, false, "Prince Guard", "Horse Kick", false); + } + } + + @Override + public void Damage(CustomDamageEvent event) + { + if(_horse.equals(event.GetDamageeEntity())) + { + event.setDamagee(GetEntity()); + } + + if(GetEntity().equals(event.GetDamageeEntity())) + { + if(_prince.equals(event.GetDamagerEntity(true))) + { + if(event.GetProjectile() != null) + { + event.GetProjectile().setFireTicks(0); + } + event.SetCancelled("Cancel"); + return; + } + + if(!_AI) + { + event.SetCancelled("No AI"); + return; + } + + if(!event.isCancelled() && _horse != null && _horse.isValid()) + { + PacketPlayOutAnimation hurt = new PacketPlayOutAnimation(); + hurt.a = _horseDisguise.getEntityId(); + hurt.b = 1; + _horseDisguise.sendPacket(hurt); + } + } + + else if(event.GetDamageeEntity() instanceof Player) + { + if(_horse.equals(event.GetDamagerEntity(false))) + { + event.AddKnockback("Horse Knockback", KNOCKBACK); + } + } + } + + @Override + public void Target(EntityTargetEvent event) + {} + + @EventHandler + public void onDismount(EntityDismountEvent event) + { + if(event.getDismounted().equals(GetEntity())) event.setCancelled(true); + } + + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPumpkinPrince.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPumpkinPrince.java new file mode 100644 index 000000000..a09970660 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPumpkinPrince.java @@ -0,0 +1,478 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import net.minecraft.server.v1_8_R3.PacketPlayOutAnimation; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.BlockFace; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftZombie; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Fireball; +import org.bukkit.entity.Horse.Variant; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.entity.Skeleton.SkeletonType; +import org.bukkit.entity.Snowball; +import org.bukkit.entity.Zombie; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.EntityTargetEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; +import org.spigotmc.event.entity.EntityDismountEvent; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilItem; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTextTop; +import mineplex.core.disguise.disguises.DisguiseHorse; +import mineplex.core.recharge.Recharge; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +import nautilus.game.arcade.game.games.halloween.creatures.CreatureBase; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; + +public class MobPumpkinPrince extends CreatureBase implements Listener +{ + + private Halloween2016 Host; + + private Zombie _horse; + private DisguiseHorse _horseDisguise; + + private boolean _AI = false; + private boolean _invulnerable = false; + + private long _horseKick = 0; + private static final long HORSE_KICK_DURATION = 1000; + + private static final double HORSE_KICK_DAMAGE = 5; + + private static final float HORSE_SPEED = 1.5f; + + private static final double STAGE_3_KNOCKBACK = 3; + private static final double HORSE_KNOCKBACK = 3; + + private static final double HEALTH = 1000; + + + public MobPumpkinPrince(Halloween2016 game, Location loc) + { + super(game, C.cRed + C.Bold + "Pumpkin Prince", Skeleton.class, loc); + Host = game; + } + + @Override + public void SpawnCustom(Skeleton ent) + { + ent.getEquipment().setHelmet(new ItemStack(Material.PUMPKIN)); + ent.getEquipment().setItemInHand(new ItemStack(Material.BOW)); + + ent.setMaxHealth(HEALTH); + ent.setHealth(ent.getMaxHealth()); + + ent.setSkeletonType(SkeletonType.WITHER); + + + super.Host.CreatureAllowOverride = true; + _horse = ent.getWorld().spawn(ent.getLocation(), Zombie.class); + super.Host.CreatureAllowOverride = false; + + _horseDisguise = new DisguiseHorse(_horse); + _horseDisguise.setType(Variant.SKELETON_HORSE); + + super.Host.getArcadeManager().GetDisguise().disguise(_horseDisguise); + + UtilEnt.setStepHeight(ent, 1); + UtilEnt.setStepHeight(_horse, 1); + + UtilEnt.setBoundingBox(_horse, 0, 0); + + //For some reason 'UtilEnt.silence' doesn't work, so using native silence instead + //UtilEnt.silence(_horse, true); + ((CraftZombie)_horse).getHandle().b(true); + + _horse.setPassenger(ent); + UtilEnt.Vegetate(_horse); + + UtilServer.RegisterEvents(this); + + UtilEnt.setTickWhenFarAway(ent, true); + ent.setRemoveWhenFarAway(false); + UtilEnt.setTickWhenFarAway(_horse, true); + _horse.setRemoveWhenFarAway(false); + + addEntityPart(_horse); + } + + public void setInvulnerable(boolean invulnerable) + { + _invulnerable = invulnerable; + } + + public boolean isInvulnerable() + { + return _invulnerable; + } + + public void setAI(boolean AI) + { + _AI = AI; + } + + public boolean getAI() + { + return _AI; + } + + @Override + public void Update(UpdateEvent event) + { + if(!_AI) return; + + if(event.getType() != UpdateType.TICK) return; + + UtilTextTop.displayProgress(C.cYellow + C.Bold + "Pumpkin Prince", getHealthProgress(), UtilServer.getPlayers()); + + int state = getState(); + + if(_horse.isValid() && state > 1) + { + _horse.getWorld().playSound(_horse.getLocation(), Sound.BLAZE_DEATH, 3, 1); + UtilParticle.PlayParticleToAll(ParticleType.LARGE_SMOKE, _horse.getLocation(), null, 0.5f, 20, ViewDist.NORMAL); + _horse.setHealth(0); + } + + if(state == 1) + { + Entity target = GetEntity().getTarget(); + if(target != null) + { + UtilEnt.CreatureMove(_horse, GetEntity().getTarget().getLocation(), HORSE_SPEED); + + boolean hit = false; + + for(Player p : getInsideBoundingBox()) + { + CustomDamageEvent dmgEvent = Host.getArcadeManager().GetDamage().NewDamageEvent(p, _horse, null, GetEntity().getLocation(), DamageCause.ENTITY_ATTACK, HORSE_KICK_DAMAGE, true, false, false, "Pumpkin Prince", "Horse Kick", false); + if(dmgEvent.isCancelled()) continue; + hit = true; + } + if(hit) + { + _horseKick = System.currentTimeMillis(); + + _horseDisguise.kick(); + Host.getArcadeManager().GetDisguise().updateDisguise(_horseDisguise); + + _horse.getWorld().playSound(_horse.getLocation(), Sound.SKELETON_HURT, 4f, 0.6f); + _horse.getWorld().playSound(_horse.getLocation(), Sound.SKELETON_HURT, 4f, 0.6f); + } + + if(_horseKick + HORSE_KICK_DURATION < System.currentTimeMillis()) + { + _horseDisguise.stopKick(); + Host.getArcadeManager().GetDisguise().updateDisguise(_horseDisguise); + } + + if(GetEntity().getTicksLived() % 15 == 0) + { + if(target.getLocation().distanceSquared(GetEntity().getLocation()) > 40*40) return; + + Arrow a = GetEntity().launchProjectile(Arrow.class); + + Vector force = UtilAlg.getTrajectory(GetEntity(), target).add(new Vector(0, 0.2, 0)); + a.setVelocity(force); + + a.setFireTicks(99999); + } + + } + else + { + GetEntity().setTarget(getRandomPlayer()); + } + } + else if(state == 2) + { + if(GetEntity().getTicksLived() % (20*5) == 0) + { + for(int i = 0; i < 64; i++) + { + if(tryRandomTeleport()) break; + } + } + if(GetEntity().getTicksLived() % 25 == 0) + { + Vector v = GetPlayerTarget().subtract(GetEntity().getLocation()).toVector().multiply(0.01); + + Location loc = GetEntity().getLocation(); + loc.setDirection(v); + GetEntity().teleport(loc); + GetEntity().launchProjectile(Fireball.class, v); + } + } + else if(state == 3) + { + if(GetEntity().getTicksLived() % 20*10 == 0) + { + GetEntity().setTarget(getRandomPlayer()); + } + } + } + + public Player getRandomPlayer() + { + return Host.GetPlayers(true).get(UtilMath.r(Host.GetPlayers(true).size())); + } + + private boolean tryRandomTeleport() + { + Location loc = GetPlayerTarget(); + loc.add((UtilMath.random.nextDouble() - 0.5) * 64, UtilMath.r(64)-32, (UtilMath.random.nextDouble() - 0.5) * 64); + + for(int y = loc.getBlockY(); y > 0; y--) + { + if(!loc.getBlock().getRelative(BlockFace.DOWN).getType().isSolid()) continue; + Material m1 = loc.getBlock().getType(); + Material m2 = loc.getBlock().getRelative(BlockFace.UP).getType(); + if(m1.isSolid()) continue; + if(m2.isSolid()) continue; + if(UtilItem.isLiquid(m1)) continue; + if(UtilItem.isLiquid(m2)) continue; + + loc.getWorld().playEffect(GetEntity().getLocation(), Effect.ENDER_SIGNAL, 0); + loc.getWorld().playSound(GetEntity().getLocation(), Sound.ENDERMAN_TELEPORT, 2, 0); + GetEntity().teleport(loc.getBlock().getLocation().add(0.5, 0, 0.5)); + loc.getWorld().playEffect(GetEntity().getLocation(), Effect.ENDER_SIGNAL, 0); + loc.getWorld().playSound(GetEntity().getLocation(), Sound.ENDERMAN_TELEPORT, 2, 0); + return true; + } + return false; + + } + + @EventHandler + public void onShoot(EntityShootBowEvent event) + { + if(!event.getEntity().equals(GetEntity())) return; + + event.setCancelled(true); + } + + @EventHandler + public void onDismount(EntityDismountEvent event) + { + if(event.getDismounted().equals(GetEntity())) event.setCancelled(true); + } + + public Zombie getHorse() + { + return _horse; + } + + @Override + public void Damage(CustomDamageEvent event) + { + if(event.GetDamageeEntity().equals(_horse)) + { + event.setDamagee(GetEntity()); + _horse.setFireTicks(0); + } + + if(event.GetDamageeEntity() instanceof Player) + { + if(GetEntity().equals(event.GetDamagerEntity(true))) + { + onPrinceDamagePlayer(event); + } + else + { + onOtherDamagePlayer(event); + } + } + + if(GetEntity().equals(event.GetDamageeEntity())) + { + onPrinceTakeDamage(event); + + if(!event.isCancelled() && _horse != null && _horse.isValid()) + { + PacketPlayOutAnimation hurt = new PacketPlayOutAnimation(); + hurt.a = _horseDisguise.getEntityId(); + hurt.b = 1; + _horseDisguise.sendPacket(hurt); + } + } + } + + public void onPrinceTakeDamage(CustomDamageEvent event) + { + if(event.GetCause() == DamageCause.SUFFOCATION || event.GetCause() == DamageCause.FALL) + { + event.SetCancelled("Boss Invalid Damage"); + return; + } + + if(GetEntity().equals(event.GetDamagerEntity(true))) + { + event.SetCancelled("Boss Invalid Damage"); + return; + } + + if(!_AI) + { + event.SetCancelled("AI Disabled"); + return; + } + + if(_invulnerable) + { + event.SetCancelled("Invulnerable"); + Player p = event.GetDamagerPlayer(true); + if(p != null) + { + if(Recharge.Instance.use(p, "Boss Inulnerable Info", 5000, false, false)) + { + p.sendMessage(F.main("Game", "Kill the " + F.item("Guards") + " before you can damage the " + F.color("Pumpkin Prince", C.cYellow + C.Bold))); + } + } + return; + } + + if(event.GetProjectile() instanceof Snowball) + { + event.SetKnockback(false); + } + + updateHealth(GetEntity().getHealth(), GetEntity().getHealth()-event.GetDamage()); + } + + public void onPrinceDamagePlayer(CustomDamageEvent event) + { + int state = getState(); + + if(state == 3) + { + event.AddKnockback("Boss Knockback", STAGE_3_KNOCKBACK); + } + } + + public void onOtherDamagePlayer(CustomDamageEvent event) + { + if(_horse.equals(event.GetDamagerEntity(false))) + { + event.AddKnockback("Horse Kick", HORSE_KNOCKBACK); + } + } + + public void updateHealth(double oldH, double newH) + { + int oldState = getState(getHealthProgress(oldH)); + int newState = getState(getHealthProgress(newH)); + if(oldState != newState) + { + updateState(newState); + } + } + + public void updateState(int state) + { + if(state == 1) + { + + } + if(state == 2) + { + GetEntity().getEquipment().setItemInHand(new ItemStack(Material.DIAMOND_SWORD)); + + GetEntity().addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 1)); + GetEntity().addPotionEffect(new PotionEffect(PotionEffectType.JUMP, Integer.MAX_VALUE, 1)); + } + if(state == 3) + { + Host.setMaxPumplings(0); + + GetEntity().addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 2), true); + GetEntity().addPotionEffect(new PotionEffect(PotionEffectType.JUMP, Integer.MAX_VALUE, 2), true); + } + } + + @Override + public void remove() + { + die(); + super.remove(); + } + + public void die() + { + UtilServer.Unregister(this); + } + + @Override + public void Target(EntityTargetEvent event) + { + if(!event.getEntity().equals(GetEntity())) return; + + if(!_AI) + { + event.setCancelled(true); + return; + } + + if(event.getTarget() == null) + { + event.setCancelled(true); + return; + } + + if(event.getTarget().getType() != EntityType.PLAYER) event.setCancelled(true); + } + + public int getState() + { + return getState(getHealthProgress()); + } + + public int getState(double healthProgress) + { + if(healthProgress > 0.6) return 1; + if(healthProgress > 0.4) return 2; + return 3; + } + + public double getHealthProgress(double health) + { + return health / GetEntity().getMaxHealth(); + } + + public double getHealthProgress() + { + return getHealthProgress(GetEntity().getHealth()); + } + + public boolean isDead() + { + return getHealthProgress() <= 0; + } + + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPumpling.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPumpling.java new file mode 100644 index 000000000..774cbbecd --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobPumpling.java @@ -0,0 +1,97 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.entity.EntityTargetEvent; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.C; +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.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import nautilus.game.arcade.game.games.halloween.creatures.CreatureBase; +import nautilus.game.arcade.game.games.halloween.creatures.InterfaceMove; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; + +public class MobPumpling extends CreatureBase implements InterfaceMove +{ + private static double EXTRA_DAMAGE = 5; + private static float SPEED = 1; + + public MobPumpling(Halloween2016 game, Location loc) + { + super(game, C.cYellow + "Pumpling", Skeleton.class, loc); + } + + @Override + public void SpawnCustom(Skeleton ent) + { + Host.Manager.GetCondition().Factory().Invisible("Cloak", ent, ent, 999999, 0, false, false, false); + + ent.getEquipment().setHelmet(new ItemStack(Material.PUMPKIN)); + + ent.setMaxHealth(15); + ent.setHealth(ent.getMaxHealth()); + + UtilEnt.setTickWhenFarAway(ent, true); + } + + @Override + public void Damage(CustomDamageEvent event) + { + if(GetEntity().equals(event.GetDamagerEntity(false))) + { + event.AddMod("Damage", EXTRA_DAMAGE); + } + } + + @Override + public void Target(EntityTargetEvent event) + { + + } + + @Override + public void Update(UpdateEvent event) + { + + } + + @Override + public void Move() + { + UtilEnt.CreatureMove(GetEntity(), getClosestPlayer(), SPEED); + } + + public Location getClosestPlayer() + { + Player p = null; + double d = 0; + for(Player pp : Host.GetPlayers(true)) + { + double dd = pp.getLocation().distanceSquared(GetEntity().getLocation()); + if(p == null || dd < d) + { + d = dd; + p = pp; + } + } + return p.getLocation(); + } + + @Override + public void remove() + { + UtilParticle.PlayParticleToAll(ParticleType.LARGE_SMOKE, GetEntity().getLocation(), null, 0.3f, 20, ViewDist.NORMAL); + GetEntity().getWorld().playSound(GetEntity().getLocation(), Sound.SKELETON_DEATH, 1, 1); + GetEntity().getWorld().playSound(GetEntity().getLocation(), Sound.FIZZ, 1, 1); + super.remove(); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobSkeletonArcher.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobSkeletonArcher.java new file mode 100644 index 000000000..fcc6f7235 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobSkeletonArcher.java @@ -0,0 +1,53 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftArrow; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Skeleton; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.C; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; + +public class MobSkeletonArcher extends CryptBreaker +{ + + private static final int CRYPT_DAMAGE = 3; + private static final int CRYPT_DAMAGE_RATE = 20; + private static final float SPEED = 1; + private static final double HEALTH = 15; + + public MobSkeletonArcher(Halloween2016 game, Location loc) + { + super(game, C.cYellow + "Skeleton Archer", Skeleton.class, loc, CRYPT_DAMAGE, CRYPT_DAMAGE_RATE, SPEED); + + _extraDamage = 1; + _customCryptRange = 3; + + _playerTargetBackRange = 2; + } + + @Override + public void SpawnCustom(Skeleton ent) + { + ent.getEquipment().setItemInHand(new ItemStack(Material.BOW)); + + ent.setMaxHealth(HEALTH); + ent.setHealth(HEALTH); + } + + @Override + public void attackCrypt() + { + if(!_crypt.tryDamage(GetEntity(), _cryptDamage, _cryptDamageRate)) return; + + Location door = getClosestDoor(); + Vector diff = door.toVector().subtract(GetEntity().getLocation().toVector()); + diff.setY(diff.getY() + 0.5); + Arrow a = GetEntity().launchProjectile(Arrow.class, diff); + ((CraftArrow)a).getHandle().noclip = true; + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobWitch.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobWitch.java new file mode 100644 index 000000000..3342f1f96 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobWitch.java @@ -0,0 +1,295 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftCreature; +import org.bukkit.entity.Bat; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityTargetEvent; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.C; +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.UtilServer; +import mineplex.core.disguise.disguises.DisguiseWitch; +import mineplex.core.recharge.Recharge; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import nautilus.game.arcade.game.games.halloween.creatures.CreatureBase; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; +import net.minecraft.server.v1_8_R3.RandomPositionGenerator; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class MobWitch extends CreatureBase +{ + private static int HEALTH = 20; + private static int PANIC_TIME = 100; + + private float SPEED_IDLE = 1f; + private float SPEED_PANIC = 2f; + + private static int BATS_BURST = 10; + private static int BATS_TICKS = 80; + private static double BAT_KNOCKBACK = 1.75; + private static int BAT_FIRE_TICKS = 10; + private static double BAT_DAMAGE = 3; + + private static double HEAL_DISTANCE = 7; + private static double HEAL_AMOUNT = 10; + private static double HEAL_RAY_SPEED = 0.2; + + + + private CreatureBase _healTarget = null; + public Location _healRay = null; + + private int _panicTicks = 0; + private List _bats = new ArrayList<>(); + + private Location _panicTarget = null; + + private Halloween2016 _host; + + public MobWitch(Halloween2016 game, Location loc) + { + super(game, C.cYellow + "Witch", Zombie.class, loc); + _host = game; + } + + @Override + public void SpawnCustom(Zombie ent) + { + ent.setMaxHealth(HEALTH); + ent.setHealth(ent.getMaxHealth()); + + UtilEnt.setTickWhenFarAway(ent, true); + ent.setRemoveWhenFarAway(false); + + DisguiseWitch disg = new DisguiseWitch(ent); + Host.getArcadeManager().GetDisguise().disguise(disg); + } + + @Override + public void Update(UpdateEvent event) + { + if(event.getType() == UpdateType.TICK) + { + updateBats(); + move(); + } + } + + @Override + public void Damage(CustomDamageEvent event) + { + if(event.isCancelled()) return; + + if(_bats.contains(event.GetDamageeEntity())) + { + if(event.GetCause() == DamageCause.FIRE_TICK) + { + event.SetCancelled("Fire Imunity"); + return; + } + } + if(event.GetDamageeEntity() instanceof Player) + { + if (event.GetReason() != null && event.GetReason().contains(GetName())) + { + event.AddKnockback(GetName(), BAT_KNOCKBACK); + return; + } + } + if(!GetEntity().equals(event.GetDamageeEntity())) return; + + LivingEntity damager = event.GetDamagerEntity(false); + + if(damager != null && _panicTicks <= 0) + { + shootBats(damager.getEyeLocation().subtract(GetEntity().getEyeLocation()).toVector()); + } + + _panicTicks = PANIC_TIME; + } + + public void shootBats(Vector direction) + { + Location loc = GetEntity().getLocation(); + loc.setDirection(direction); + GetEntity().teleport(loc); + Host.CreatureAllowOverride = true; + for(int i = 0; i < BATS_BURST; i++) + { + Bat bat = GetEntity().getWorld().spawn(GetEntity().getEyeLocation(), Bat.class); + UtilEnt.Vegetate(bat); + _bats.add(bat); + addEntityPart(bat); + } + Host.CreatureAllowOverride = false; + } + + @Override + public void Target(EntityTargetEvent event) + {} + + public void move() + { + if(_panicTicks > 0) + { + movePanic(); + _panicTicks--; + } + else + { + _panicTarget = null; + moveIdle(); + } + } + + public void updateBats() + { + for (Iterator it = _bats.iterator(); it.hasNext();) + { + Bat bat = it.next(); + if (!bat.isValid()) + { + it.remove(); + continue; + } + + if(bat.getTicksLived() > BATS_TICKS) + { + bat.remove(); + it.remove(); + UtilParticle.PlayParticle(ParticleType.LARGE_SMOKE, bat.getLocation(), 0, 0, 0, 0, 3, + ViewDist.LONG, UtilServer.getPlayers()); + continue; + } + + bat.setFireTicks(10); + + Vector rand = new Vector((Math.random() - 0.5)/2, (Math.random() - 0.5)/2, (Math.random() - 0.5)/2); + bat.setVelocity(bat.getLocation().getDirection().multiply(0.5).add(rand)); + + for(Player p : UtilEnt.getPlayersInsideEntity(bat, Host.GetPlayers(true))) + { + if (!Recharge.Instance.usable(p, "Hit by Bat")) + continue; + + //Damage Event + Host.getArcadeManager().GetDamage().NewDamageEvent(p, GetEntity(), null, + DamageCause.CUSTOM, BAT_DAMAGE, true, true, false, + GetEntity().getName(), GetName()); + p.setFireTicks(p.getFireTicks() + BAT_FIRE_TICKS); + + //Effect + bat.getWorld().playSound(bat.getLocation(), Sound.BAT_HURT, 1f, 1f); + UtilParticle.PlayParticle(ParticleType.LARGE_SMOKE, bat.getLocation(), 0, 0, 0, 0, 3, + ViewDist.LONG, UtilServer.getPlayers()); + + bat.remove(); + it.remove(); + + //Recharge on hit + Recharge.Instance.useForce(p, "Hit by Bat", 200); + } + } + } + + public void getNewHealTarget() + { + CreatureBase close = null; + double dist = -1; + for(CreatureBase c : _host.getNonPumplings()) + { + if(c.equals(this)) continue; + if(!c.GetEntity().isValid()) continue; + + if(c.GetEntity().getHealth() < c.GetEntity().getMaxHealth()) + { + double d = GetEntity().getLocation().distanceSquared(c.GetEntity().getLocation()); + if(close == null || d < dist) + { + close = c; + dist = d; + } + } + } + _healTarget = close; + } + + public void moveIdle() + { + if(_healTarget != null && !_healTarget.GetEntity().isValid()) + { + _healTarget = null; + } + if(_healTarget == null) + { + getNewHealTarget(); + } + + if(_healTarget == null) + { + UtilEnt.CreatureMove(GetEntity(), _host.getInfrontOfDoorTargets().get(0), SPEED_IDLE); + + return; + } + + if(_healRay != null) + { + Vector diff = _healTarget.GetEntity().getEyeLocation().subtract(_healRay).toVector(); + double length = diff.lengthSquared(); + if(length <= HEAL_RAY_SPEED * HEAL_RAY_SPEED) + { + LivingEntity ent = _healTarget.GetEntity(); + ent.setHealth(Math.min(ent.getMaxHealth(), ent.getHealth()+HEAL_AMOUNT)); + + UtilParticle.PlayParticleToAll(ParticleType.HEART, ent.getEyeLocation(), 1, 1, 1, 0, 20, ViewDist.NORMAL); + + _healTarget = null; + _healRay = null; + + return; + } + diff.normalize().multiply(HEAL_RAY_SPEED); + + _healRay.add(diff); + UtilParticle.PlayParticleToAll(ParticleType.HEART, _healRay, 0, 0, 0, 0, 1, ViewDist.NORMAL); + + return; + } + + double dist = _healTarget.GetEntity().getLocation().distanceSquared(GetEntity().getLocation()); + if(dist < HEAL_DISTANCE * HEAL_DISTANCE) + { + _healRay = GetEntity().getEyeLocation(); + return; + } + + UtilEnt.CreatureMove(GetEntity(), _healTarget.GetEntity().getLocation(), SPEED_IDLE); + } + + public void movePanic() + { + if(_panicTarget == null || UtilEnt.canEntityWalkCloserToNavigationTarget(GetEntity())) + { + Vec3D v = RandomPositionGenerator.a(((CraftCreature)GetEntity()).getHandle(), 5, 4); + _panicTarget = new Location(GetEntity().getWorld(), v.a, v.b, v.c); + } + + UtilEnt.CreatureMove(GetEntity(), _panicTarget, SPEED_PANIC); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobZombie.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobZombie.java new file mode 100644 index 000000000..5de0819e6 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobZombie.java @@ -0,0 +1,32 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import org.bukkit.Location; +import org.bukkit.entity.Zombie; + +import mineplex.core.common.util.C; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; + +public class MobZombie extends CryptBreaker +{ + + private static float SPEED = 1; + private static int CRYPT_DAMAGE = 3; + private static int CRYPT_DAMAGE_COOLDOWN = 20; + + private static double HEALTH = 15; + + public MobZombie(Halloween2016 game, Location loc) + { + super(game, C.cYellow + "Zombie", Zombie.class, loc, CRYPT_DAMAGE, CRYPT_DAMAGE_COOLDOWN, SPEED); + + _extraDamage = 5; + } + + @Override + public void SpawnCustom(Zombie ent) + { + ent.setMaxHealth(HEALTH); + ent.setHealth(HEALTH); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobZombieSpawner.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobZombieSpawner.java new file mode 100644 index 000000000..6b5ae9fef --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/creatures/MobZombieSpawner.java @@ -0,0 +1,75 @@ +package nautilus.game.arcade.game.games.halloween2016.creatures; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Zombie; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; + +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; + +public class MobZombieSpawner extends CryptBreaker +{ + + private static final int CRYPT_DAMAGE = 20; + private static final int CRYPT_RATE = 20; + private static final float SPEED = 0.5f; + private static final int MAX_MINI_ZOMBIES = 4; + + private List _miniZombies = new ArrayList<>(); + + public MobZombieSpawner(Halloween2016 game, Location loc) + { + super(game, C.cYellow + "Zombie Spawner", Zombie.class, loc, CRYPT_DAMAGE, CRYPT_RATE, SPEED); + } + + @Override + public void SpawnCustom(Zombie ent) + { + ent.setVillager(true); + + ent.getEquipment().setHelmet(new ItemStack(Material.MOB_SPAWNER)); + } + + @Override + public void Update(UpdateEvent event) + { + super.Update(event); + + if(event.getType() == UpdateType.SEC_05) + { + for(Iterator it = _miniZombies.iterator(); it.hasNext();) + { + if(!it.next().GetEntity().isValid()) it.remove(); + } + + if(_miniZombies.size() >= MAX_MINI_ZOMBIES) return; + + //Combat concurrency issues (can't add mobs while in the "tick" loop of mobs) + Host.Manager.runSync(() -> + { + if(GetEntity().isValid()) + { + Location loc = GetEntity().getLocation().add(GetEntity().getLocation().getDirection().normalize()); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, loc, null, 0.1f, 20, ViewDist.NORMAL); + loc.getWorld().playSound(loc, Sound.ZOMBIE_INFECT, 1, 0.6f); + MobMiniZombie mini = new MobMiniZombie(Host, loc); + _miniZombies.add(mini); + Host16.AddCreature(mini, false); + } + }); + } + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/tutorial/TutorialHalloween2016.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/tutorial/TutorialHalloween2016.java new file mode 100644 index 000000000..c38389e25 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/tutorial/TutorialHalloween2016.java @@ -0,0 +1,44 @@ +package nautilus.game.arcade.game.games.halloween2016.tutorial; + +import org.bukkit.Location; + +import mineplex.core.common.animation.Animator; + +import nautilus.game.arcade.game.GameTeam; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; +import nautilus.game.arcade.gametutorial.GameTutorial; +import nautilus.game.arcade.gametutorial.TutorialPhase; + +public class TutorialHalloween2016 extends GameTutorial +{ + + private Halloween2016 _host; + + public TutorialHalloween2016(Halloween2016 host, Animator animator, GameTeam team, Location start, int duration) + { + super(host.Manager, new TutorialPhase[]{ + new TutorialPhaseHalloween(duration, animator, team, start) + }); + _host = host; + + SetTutorialPositions = false; + } + + @Override + public void onStart() + { + super.onStart(); + + _host.Manager.getCosmeticManager().setHideParticles(true); + } + + @Override + public void onEnd() + { + super.onEnd(); + _host.AllowParticles = true; + + _host.Manager.getCosmeticManager().setHideParticles(false); + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/tutorial/TutorialPhaseHalloween.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/tutorial/TutorialPhaseHalloween.java new file mode 100644 index 000000000..5ad45f140 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/tutorial/TutorialPhaseHalloween.java @@ -0,0 +1,67 @@ +package nautilus.game.arcade.game.games.halloween2016.tutorial; + +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import mineplex.core.common.animation.Animator; +import mineplex.core.common.util.C; + +import nautilus.game.arcade.game.GameTeam; +import nautilus.game.arcade.gametutorial.TutorialPhase; +import nautilus.game.arcade.gametutorial.TutorialText; + +public class TutorialPhaseHalloween extends TutorialPhase +{ + + private Animator _animator; + private GameTeam _team; + private Location _start; + + public TutorialPhaseHalloween(int duration, Animator animator, GameTeam team, Location start) + { + super(new TutorialText[] + { + new TutorialText(C.cGold + "Legend says that many years ago", 5 * 20, 1), + new TutorialText(C.cGold + "A group of heroes defeated the Pumpkin King", 4 * 20, 2), + new TutorialText(C.cGold + "Since then the world has known peace.", 3 * 20, 3), + new TutorialText("", 2 * 20, 4), + new TutorialText(C.cGold + "My family has guarded this tomb for generations.", 4 * 20, 5), + new TutorialText(C.cGold + "All I know is we must not let it fall.", 4 * 20, 6), + new TutorialText("", 2 * 20, 7), + new TutorialText("", Math.max((duration-(24*20)), 8)) + }); + + _animator = animator; + _team = team; + _start = start; + } + + + @Override + public void onStart() + { + _animator.start(_start); + } + + + + @Override + public void onEnd() + { + for(Player p : _team.GetPlayers(false)) + { + p.setGameMode(GameMode.SURVIVAL); + } + _animator.stop(); + } + + @Override + public int ID() + { + return 1; + } + + + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave1.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave1.java new file mode 100644 index 000000000..b2ed6fd86 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave1.java @@ -0,0 +1,46 @@ +package nautilus.game.arcade.game.games.halloween2016.wave; + +import mineplex.core.common.util.UtilTime; + +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobSkeletonArcher; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobZombie; + +public class Wave1 extends WaveBase +{ + + public Wave1(Halloween2016 host) + { + super(host, null, 80000, host.getMobSpawns(), null); + _desc = new String[] + { + "Zombies", + "Skeletons" + }; + } + + @Override + public void Spawn(int tick) + { + if(tick == 0) + { + Host.setObjective("Protect the Crypt"); + } + + if (UtilTime.elapsed(_start, 50000)) + return; + + if (Host.getNonPumplings().size() > Host.getMaxNonPumplings()) return; + + if(tick%10 == 0) + { + Host.AddCreature(new MobZombie(Host, GetSpawn())); + } + + if(tick%15 == 0) + { + Host.AddCreature(new MobSkeletonArcher(Host, GetSpawn())); + } + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave2.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave2.java new file mode 100644 index 000000000..b716a7095 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave2.java @@ -0,0 +1,56 @@ +package nautilus.game.arcade.game.games.halloween2016.wave; + +import mineplex.core.common.util.UtilTime; + +import nautilus.game.arcade.game.games.halloween.creatures.MobSpiderLeaper; +import nautilus.game.arcade.game.games.halloween.creatures.MobSpiderSmasher; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobGiant; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobZombie; + +public class Wave2 extends WaveBase +{ + + public Wave2(Halloween2016 host) + { + super(host, null, 90000, host.getMobSpawns(), null); + _desc = new String[] + { + "Giants", + "Creepers", + "Zombies", + "Spiders" + }; + } + + @Override + public void Spawn(int tick) + { + if(tick == 0) + { + Host.AddCreature(new MobGiant(Host, getSpawn(Host.getMainLane()))); + } + + if (UtilTime.elapsed(_start, 60000)) + return; + + if(tick%200 == 0) + { + spawnCreepers(); + } + + if (Host.getNonPumplings().size() > Host.getMaxNonPumplings()) return; + + if(tick%7 == 0) + { + Host.AddCreature(new MobZombie(Host, GetSpawn())); + } + + if(tick%20 == 0) + { + Host.AddCreature(new MobSpiderLeaper(Host, GetSpawn())); + Host.AddCreature(new MobSpiderSmasher(Host, GetSpawn())); + } + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave3.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave3.java new file mode 100644 index 000000000..fef51ae1a --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave3.java @@ -0,0 +1,68 @@ +package nautilus.game.arcade.game.games.halloween2016.wave; + +import mineplex.core.common.util.UtilTime; + +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobBlaze; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobGiant; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobWitch; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobZombie; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobZombieSpawner; + +public class Wave3 extends WaveBase +{ + + public Wave3(Halloween2016 host) + { + super(host, null, 90000, host.getMobSpawns(), null); + _desc = new String[] + { + "Giants", + "Creepers", + "Zombies", + "Zombie Spawners", + "Blazes" + }; + } + + @Override + public void Spawn(int tick) + { + if (UtilTime.elapsed(_start, 60000)) + return; + + if(tick%200 == 0) + { + spawnCreepers(); + } + + if(tick%(20*7) == 0) + { + Host.AddCreature(new MobWitch(Host, GetSpawn())); + } + + if(tick%(20 * 10) == 0) + { + Host.AddCreature(new MobGiant(Host, getSpawn(Host.getMainLane()))); + } + + if (Host.getNonPumplings().size() > Host.getMaxNonPumplings()) return; + + if(tick%15 == 0) + { + Host.AddCreature(new MobZombie(Host, GetSpawn())); + } + + if(tick%60 == 0) + { + Host.AddCreature(new MobZombieSpawner(Host, GetSpawn())); + } + + if(tick%30 == 0) + { + Host.AddCreature(new MobBlaze(Host, GetSpawn())); + } + + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave4.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave4.java new file mode 100644 index 000000000..7083c3e87 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave4.java @@ -0,0 +1,56 @@ +package nautilus.game.arcade.game.games.halloween2016.wave; + +import mineplex.core.common.util.UtilTime; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobBlaze; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobGiant; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobPigZombie; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobWitch; + +public class Wave4 extends WaveBase +{ + + public Wave4(Halloween2016 host) + { + super(host, null, 100000, host.getMobSpawns(), null); + _desc = new String[] + { + "Giants", + "Creepers", + "Zombie Pigmen", + "Blazes", + "Witches", + }; + } + + @Override + public void Spawn(int tick) + { + if(tick%(20 * 30) == 0) + { + Host.AddCreature(new MobGiant(Host, getSpawn(Host.getMainLane()))); + } + + if (Host.getNonPumplings().size() > Host.getMaxNonPumplings()) return; + + if (UtilTime.elapsed(_start, 70000)) + return; + + if(tick%15 == 0) + { + Host.AddCreature(new MobPigZombie(Host, GetSpawn())); + } + + if(tick%60 == 0) + { + Host.AddCreature(new MobBlaze(Host, GetSpawn())); + } + + if(tick%100 == 0) + { + Host.AddCreature(new MobWitch(Host, GetSpawn())); + } + + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave5.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave5.java new file mode 100644 index 000000000..176d375b7 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/Wave5.java @@ -0,0 +1,84 @@ +package nautilus.game.arcade.game.games.halloween2016.wave; + +import mineplex.core.common.util.UtilTime; + +import nautilus.game.arcade.game.games.halloween.creatures.MobSpiderLeaper; +import nautilus.game.arcade.game.games.halloween.creatures.MobSpiderSmasher; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobBlaze; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobGiant; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobSkeletonArcher; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobWitch; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobZombie; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobZombieSpawner; + +public class Wave5 extends WaveBase +{ + + public Wave5(Halloween2016 host) + { + super(host, null, 120000, host.getMobSpawns(), null); + _desc = new String[] + { + "Giants", + "Creepers", + "Zombies", + "Zombie Spawners", + "Skeletons", + "Witches", + "Blazes", + "Spiders" + }; + } + + @Override + public void Spawn(int tick) + { + if(tick%(20*30) == 0) + { + Host.AddCreature(new MobGiant(Host, getSpawn(Host.getMainLane()))); + } + + if (UtilTime.elapsed(_start, 100000)) + return; + + if(tick%300 == 0) + { + spawnCreepers(); + } + + if (Host.getNonPumplings().size() > Host.getMaxNonPumplings()) return; + + if(tick%40 == 0) + { + Host.AddCreature(new MobZombie(Host, GetSpawn())); + } + + if(tick%40 == 0) + { + Host.AddCreature(new MobSkeletonArcher(Host, GetSpawn())); + } + + if(tick%50 == 0) + { + Host.AddCreature(new MobZombieSpawner(Host, GetSpawn())); + } + + if(tick%50 == 0) + { + Host.AddCreature(new MobWitch(Host, GetSpawn())); + } + + if(tick%50 == 0) + { + Host.AddCreature(new MobBlaze(Host, GetSpawn())); + } + + if(tick%40 == 0) + { + Host.AddCreature(new MobSpiderLeaper(Host, GetSpawn())); + Host.AddCreature(new MobSpiderSmasher(Host, GetSpawn())); + } + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveBase.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveBase.java new file mode 100644 index 000000000..95a211c18 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveBase.java @@ -0,0 +1,46 @@ +package nautilus.game.arcade.game.games.halloween2016.wave; + +import java.util.List; + +import org.bukkit.Location; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilMath; + +import nautilus.game.arcade.game.games.halloween.NamedAudio; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobCreeper; + +public abstract class WaveBase extends nautilus.game.arcade.game.games.halloween.waves.WaveBase +{ + + protected Halloween2016 Host; + + protected static final int CREEPER_SPAWN_PACK_SIZE = 5; + + public WaveBase(Halloween2016 host, String name, long duration, List spawns, NamedAudio audio) + { + super(host, name, duration, spawns, audio); + Host = host; + + _titleColor = C.cRed; + } + + public Location getSpawn(List lane) + { + return lane.get(UtilMath.r(lane.size())); + } + + public void spawnCreepers() + { + Location loc = GetSpawn(); + for(int i = 0; i < CREEPER_SPAWN_PACK_SIZE; i++) + { + double x = UtilMath.random(-3, 3); + double z = UtilMath.random(-3, 3); + + Host.AddCreature(new MobCreeper(Host, loc.clone().add(x, 0, z)), false); + } + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveBoss.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveBoss.java new file mode 100644 index 000000000..c390473bc --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveBoss.java @@ -0,0 +1,253 @@ +package nautilus.game.arcade.game.games.halloween2016.wave; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Fireball; +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.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTextMiddle; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +import nautilus.game.arcade.game.games.halloween.creatures.CreatureBase; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobPrinceGuard; +import nautilus.game.arcade.game.games.halloween2016.creatures.MobPumpkinPrince; + +public class WaveBoss extends WaveBase implements Listener +{ + private MobPumpkinPrince _prince; + private Halloween2016 Host; + + private Skeleton _pumpkinKing; + + private List _guards = new ArrayList<>(); + private int _guardsCount = 4; + private int _guardsCountQueue = _guardsCount; + private double _nextPrinceHealthStageForNewGuards; + + private int _tick = 0; + + private Fireball _fireball; + + private final static float KING_SPEED = 1.7f; + private final static float PRINCE_SPEED = 1.3f; + + private Location _princeTarget; + + public WaveBoss(Halloween2016 host) + { + super(host, "Boss Fight", 0, host.getMobSpawns(), null); + Host = host; + } + + @Override + public void Spawn(int tick) + { + tick = _tick; + _tick++; + if(tick == 0) + { + UtilServer.RegisterEvents(this); + + for(Player p : Host.GetPlayers(true)) + { + p.teleport(Host.getCryptView()); + } + Host.lockAllPlayers(Host.getCryptView()); + + for(CreatureBase c : Host.getMobs()) + { + c.remove(); + } + } + else if(tick == 4) + { + for(CreatureBase c : Host.getMobs()) + { + c.remove(); + } + for(Entity e : Host.WorldData.World.getEntities()) + { + if((e instanceof LivingEntity) && !(e instanceof Player)) + { + e.remove(); + } + } + } + else if(tick == 5) + { + + _princeTarget = Host.getPrinceTargetInfrontOfCrypt(); + + _prince = new MobPumpkinPrince(Host, Host.getPrinceSpawn()); + _prince.setAI(false); + Host.AddCreature(_prince); + + _nextPrinceHealthStageForNewGuards = _prince.GetEntity().getHealth()-200; + } + else if(tick < 20 * 5) + { + UtilEnt.CreatureMove(_prince.getHorse(), _princeTarget, PRINCE_SPEED); + } + else if(tick == 20 * 6) + { + Vector diff = Host.getInfrontOfDoorTargets().get(1).clone().add(0, 1, 0).subtract(_prince.GetEntity().getEyeLocation()).toVector(); + UtilEnt.CreatureLook(_prince.GetEntity(), UtilAlg.GetPitch(diff), UtilAlg.GetYaw(diff)); + _fireball = _prince.GetEntity().launchProjectile(Fireball.class); + } + else if(tick == 20 * 11) + { + Host.Announce("", false); + Host.Announce("", false); + say("Pumpkin King", "I am free! Free at last!"); + } + if(tick == 20 * 12) + { + say("Pumpkin King", "Protect me my son!"); + } + if(tick > 20 * 13 && tick < 20 * 18) + { + UtilEnt.CreatureMove(_pumpkinKing, Host.getGiantSpawn(), KING_SPEED); + + } + else if(tick == 20 * 18) + { + _pumpkinKing.remove(); + + Host.unlockAllPlayers(); + _prince.setAI(true); + for(MobPrinceGuard guard : _guards) + { + guard.setAI(true); + } + + Host.Objective = "Eliminate the Guards"; + Host.Announce(C.cGreen + C.Bold + "Kill the Prince's Guards first!", false); + } + + + + + + + + + if(tick > 20 * 18){ + boolean empt = _guards.isEmpty(); + for(Iterator it = _guards.iterator(); it.hasNext();) + { + MobPrinceGuard g = it.next(); + if(!g.GetEntity().isValid()) it.remove(); + } + if(empt != _guards.isEmpty() && !empt) + { + Host.Objective = "Defeat the Pumpkin Prince"; + Host.Announce(C.cGreen + C.Bold + "All the Pumpking Prince's guards are dead!", false); + Host.Announce(C.cGreen + C.Bold + "Kill him while he is unprotected!", true); + } + + _prince.setInvulnerable(!_guards.isEmpty()); + + if(_prince.GetEntity().getHealth() < _nextPrinceHealthStageForNewGuards) + { + Host.Objective = "Eliminate the Guards"; + Host.Announce(C.cGreen + C.Bold + "The Pumpkin Prince's guards are back to protect him", false); + Host.Announce(C.cGreen + C.Bold + "Kill them first before attacking the Prince!", true); + + + _prince.setInvulnerable(true); + _nextPrinceHealthStageForNewGuards -= 200; + _guardsCountQueue = _guardsCount; + } + + if(tick % 20 * 20 == 0) + { + if(_guardsCountQueue > 0) + { + MobPrinceGuard guard = new MobPrinceGuard(Host, Host.getGiantSpawn(), _prince); + _guards.add(guard); + Host.AddCreature(guard); + _guardsCountQueue--; + } + } + } + } + + public void say(String role, String msg) + { + Host.Announce("\n" + C.cGold + C.Bold + role + ": " + C.cGray + msg + "\n"); + UtilTextMiddle.display(C.cGold + msg, null, 0, 40, 0); + } + + @Override + public boolean CanEnd() + { + boolean r = _prince != null && _prince.isDead(); + if(r) + { + end(); + } + return r; + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onExplode(EntityExplodeEvent event) + { + if(event.getEntity().equals(_fireball)) + { + event.setCancelled(true); + event.blockList().clear(); + Host.getCrypt().setHealth(0); + + + Host.CreatureAllowOverride = true; + _pumpkinKing = GetSpawn().getWorld().spawn(Host.getInfrontOfCrypt(), Skeleton.class); + Host.CreatureAllowOverride = false; + + _pumpkinKing.setSkeletonType(SkeletonType.WITHER); + _pumpkinKing.getEquipment().setHelmet(new ItemStack(Material.PUMPKIN)); + + _pumpkinKing.setCustomName(C.cYellow + C.Bold + "Pumpking King"); + _pumpkinKing.setCustomNameVisible(true); + + UtilEnt.Vegetate(_pumpkinKing); + + _pumpkinKing.getWorld().strikeLightningEffect(_pumpkinKing.getLocation()); + } + } + + public void end() + { + UtilServer.Unregister(this); + + Host.Announce("\n" + C.cYellow + C.Bold + "The Pumpkin Prince has been defeated!\nThe World is safe... for tonight.\n"); + } + + @EventHandler + public void onDamage(CustomDamageEvent event) + { + if(event.GetDamageeEntity().equals(_pumpkinKing)) + { + event.SetCancelled("Invincible Statue"); + } + } + +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveVictory.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveVictory.java new file mode 100644 index 000000000..fc775aae3 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/halloween2016/wave/WaveVictory.java @@ -0,0 +1,52 @@ +package nautilus.game.arcade.game.games.halloween2016.wave; + +import java.util.List; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; + +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import nautilus.game.arcade.game.games.halloween.creatures.CreatureBase; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; + +public class WaveVictory extends WaveBase +{ + public WaveVictory(Halloween2016 host, List beaconSpawn) + { + super(host, "Celebration!", 15000, beaconSpawn, null); + + _displayWaveNumber = false; + _announceWaveChat = false; + } + + @Override + public void Spawn(int tick) + { + if (UtilTime.elapsed(_start, 20000)) return; + + // Play + if (tick == 0) + { + for (Player player : UtilServer.getPlayers()) + { + player.playEffect(Host.getDoorSchematicLocation(), Effect.RECORD_PLAY, 2259); + } + } + + // Mobs + for (CreatureBase mob : Host.GetCreatures()) + { + mob.GetEntity().damage(5); + } + + // Time + if (Host.WorldTimeSet != 6000) + { + Host.WorldTimeSet = (Host.WorldTimeSet + 50) % 24000; + Host.WorldData.World.setTime(Host.WorldTimeSet); + } + } +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkFletcher.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkFletcher.java index e0bd889de..3867996c0 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkFletcher.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkFletcher.java @@ -57,7 +57,7 @@ public class PerkFletcher extends Perk public PerkFletcher(int time, int max, boolean remove, int slot, boolean instant) { - this(time, max, remove, slot, instant, "Fletcted Arrow"); + this(time, max, remove, slot, instant, "Fletched Arrow"); } public PerkFletcher(int time, int max, boolean remove, int slot, boolean instant, String name) @@ -162,7 +162,13 @@ public class PerkFletcher extends Perk } else { - cur.getInventory().setItem(_slot, ItemStackFactory.Instance.CreateStack(262, (byte)0, 1, F.item(_name))); + int amount = 1; + ItemStack old = cur.getInventory().getItem(_slot); + if(old != null && old.getType() == Material.ARROW) + { + amount += old.getAmount(); + } + cur.getInventory().setItem(_slot, ItemStackFactory.Instance.CreateStack(262, (byte)0, amount, F.item(_name))); } cur.playSound(cur.getLocation(), Sound.ITEM_PICKUP, 2f, 1f); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkHammerThrow.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkHammerThrow.java index 10c87bc33..f8ebc7caa 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkHammerThrow.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkHammerThrow.java @@ -87,7 +87,7 @@ public class PerkHammerThrow extends Perk implements IThrown @EventHandler public void Pickup(PlayerPickupItemEvent event) { - if (!_thrown.containsKey(event.getItem())) + if (!event.getPlayer().equals(_thrown.get(event.getItem()))) return; event.setCancelled(true); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/NextBestGameManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/NextBestGameManager.java index 75a511baa..bc24be374 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/NextBestGameManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/NextBestGameManager.java @@ -20,6 +20,7 @@ import nautilus.game.arcade.events.PlayerStateChangeEvent; import nautilus.game.arcade.game.Game; import nautilus.game.arcade.game.Game.GameState; import nautilus.game.arcade.game.GameTeam.PlayerState; +import nautilus.game.arcade.game.games.halloween2016.Halloween2016; import nautilus.game.arcade.game.games.minestrike.Minestrike; import nautilus.game.arcade.game.games.paintball.Paintball; import nautilus.game.arcade.game.games.wither.WitherGame; @@ -245,6 +246,7 @@ public class NextBestGameManager implements Listener if(event.GetGame() instanceof Minestrike || event.GetGame() instanceof WitherGame || event.GetGame() instanceof Paintball + || event.GetGame() instanceof Halloween2016 || event.GetGame().Manager.GetHost() != null) { return; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/lobby/current/NewGameLobbyManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/lobby/current/NewGameLobbyManager.java index 1711097d6..ca5f05faf 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/lobby/current/NewGameLobbyManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/lobby/current/NewGameLobbyManager.java @@ -528,6 +528,12 @@ public class NewGameLobbyManager extends LobbyManager { _multipleLocs.put(lastName, locations); } + } else if(name.equalsIgnoreCase("MAP_NAME")) + { + if(tokens[1].toLowerCase().contains("halloween")) + { + WORLD.setTime(13850); + } } else { lastName = tokens[1];