diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/TriConsumer.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/TriConsumer.java new file mode 100644 index 000000000..eca685883 --- /dev/null +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/TriConsumer.java @@ -0,0 +1,54 @@ +package mineplex.core.common; + +import java.util.Objects; + +/** + * Represents an operation that accepts two input arguments and returns no + * result. This is the three-arity specialization of {@link Consumer}. + * Unlike most other functional interfaces, {@code TriConsumer} is expected + * to operate via side-effects. + * + *

This is a functional interface + * whose functional method is {@link #accept(Object, Object, Object)}. + * + * @param the type of the first argument to the operation + * @param the type of the second argument to the operation + * @param the type of the third argument to the operation + * + * @see Consumer + */ +@FunctionalInterface +public interface TriConsumer +{ + + /** + * Performs this operation on the given arguments. + * + * @param t the first input argument + * @param u the second input argument + * @param v the third input argument + */ + void accept(T t, U u, V v); + + /** + * Returns a composed {@code TriConsumer} that performs, in sequence, this + * operation followed by the {@code after} operation. If performing either + * operation throws an exception, it is relayed to the caller of the + * composed operation. If performing this operation throws an exception, + * the {@code after} operation will not be performed. + * + * @param after the operation to perform after this operation + * @return a composed {@code TriConsumer} that performs in sequence this + * operation followed by the {@code after} operation + * @throws NullPointerException if {@code after} is null + */ + default TriConsumer andThen(TriConsumer after) + { + Objects.requireNonNull(after); + + return (f, s, t) -> { + accept(f, s, t); + after.accept(f, s, t); + }; + } +} \ No newline at end of file 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 580b337f5..7af6ab2dd 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 @@ -1032,7 +1032,12 @@ public class UtilEnt return null; } - return entity.getMetadata(key).get(0); + return entity.getMetadata(key).get(0).value(); + } + + public static void removeMetadata(Entity entity, String key) + { + entity.removeMetadata(key, UtilServer.getPlugin()); } public static void SetItemInHand(LivingEntity entity, ItemStack item) diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilItem.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilItem.java index 3f933517b..47fd7594c 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilItem.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilItem.java @@ -1158,6 +1158,16 @@ public class UtilItem return i; } + public static boolean isUnbreakable(ItemStack i) + { + if (i == null) + { + return false; + } + + return i.getItemMeta().spigot().isUnbreakable(); + } + /** * diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilMath.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilMath.java index bd9e1600c..5e37e0ac5 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilMath.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilMath.java @@ -54,6 +54,23 @@ public class UtilMath return a.subtract(b).length(); } + public static double offset2dSquared(Entity a, Entity b) + { + return offset2dSquared(a.getLocation().toVector(), b.getLocation().toVector()); + } + + public static double offset2dSquared(Location a, Location b) + { + return offset2dSquared(a.toVector(), b.toVector()); + } + + public static double offset2dSquared(Vector a, Vector b) + { + a.setY(0); + b.setY(0); + return a.subtract(b).lengthSquared(); + } + public static double offset(Entity a, Entity b) { return offset(a.getLocation().toVector(), b.getLocation().toVector()); @@ -283,4 +300,36 @@ public class UtilMath { return n - ((int) ((int) n)); } + + public static int getMax(int... ints) + { + if (ints.length < 1) + { + return -1; + } + int max = ints[0]; + + for (int i = 1; i < ints.length; i++) + { + max = Math.max(max, ints[i]); + } + + return max; + } + + public static int getMin(int... ints) + { + if (ints.length < 1) + { + return -1; + } + int min = ints[0]; + + for (int i = 1; i < ints.length; i++) + { + min = Math.min(min, ints[i]); + } + + return min; + } } 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 6294181ab..0bb9502f6 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 @@ -595,8 +595,13 @@ public class UtilPlayer return nearbyMap; } - + public static Player getClosest(Location loc, Collection ignore) + { + return getClosest(loc, -1, ignore); + } + + public static Player getClosest(Location loc, double maxDist, Collection ignore) { Player best = null; double bestDist = 0; @@ -613,6 +618,11 @@ public class UtilPlayer continue; double dist = UtilMath.offset(cur.getLocation(), loc); + + if (maxDist > 0 && dist > maxDist) + { + continue; + } if (best == null || dist < bestDist) { @@ -623,8 +633,13 @@ public class UtilPlayer return best; } - + public static Player getClosest(Location loc, Entity... ignore) + { + return getClosest(loc, -1, ignore); + } + + public static Player getClosest(Location loc, double maxDist, Entity... ignore) { Player best = null; double bestDist = 0; @@ -654,7 +669,12 @@ public class UtilPlayer continue; } - double dist = UtilMath.offsetSquared(cur.getLocation(), loc); + double dist = UtilMath.offset(cur.getLocation(), loc); + + if (maxDist > 0 && dist > maxDist) + { + continue; + } if (best == null || dist < bestDist) { diff --git a/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java b/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java index 0c096b119..30d4ae905 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/account/CoreClientManager.java @@ -176,7 +176,7 @@ public class CoreClientManager extends MiniPlugin } /** - * Get the databse account id for a player. Requires the player is online + * Get the database account id for a player. Requires the player is online * * @param player * @return diff --git a/Plugins/Mineplex.Core/src/mineplex/core/account/command/TestRank.java b/Plugins/Mineplex.Core/src/mineplex/core/account/command/TestRank.java index e4ab7147e..e4ed2e7b8 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/account/command/TestRank.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/account/command/TestRank.java @@ -64,7 +64,7 @@ public class TestRank extends CommandBase UtilPlayer.message(caller, F.main(Plugin.getName(), ChatColor.RED + "" + ChatColor.BOLD + "Invalid rank!")); return; } - if (Plugin.Get(caller).GetRank(true) == Rank.SNR_MODERATOR) + if (!Plugin.Get(caller).GetRank(true).has(Rank.JNR_DEV)) { if (tempRank.has(Rank.TWITCH)) { diff --git a/Plugins/Mineplex.Core/src/mineplex/core/itemstack/ItemStackFactory.java b/Plugins/Mineplex.Core/src/mineplex/core/itemstack/ItemStackFactory.java index 8ca03762a..6cff9e3ba 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/itemstack/ItemStackFactory.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/itemstack/ItemStackFactory.java @@ -1000,10 +1000,10 @@ public class ItemStackFactory extends MiniPlugin ItemMeta meta = stack.getItemMeta(); if (meta == null) - return 0; + return empty; if (meta.getLore() == null) - return 0; + return empty; for (String cur : meta.getLore()) if (cur.contains(var)) @@ -1021,7 +1021,7 @@ public class ItemStackFactory extends MiniPlugin } - return 0; + return empty; } public void SetLoreVar(ItemStack stack, String var, String value) diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java index 8bddf656b..784e5c230 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java @@ -1,7 +1,9 @@ package mineplex.game.clans; -import mineplex.core.aprilfools.AprilFoolsManager; -import net.minecraft.server.v1_8_R3.MinecraftServer; +import static mineplex.core.Managers.require; + +import java.io.File; +import java.io.IOException; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -11,7 +13,6 @@ import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; import org.bukkit.plugin.java.JavaPlugin; import org.spigotmc.SpigotConfig; -import mineplex.core.common.Constants; import mineplex.core.CustomTagFix; import mineplex.core.FoodDupeFix; import mineplex.core.TimingsFix; @@ -20,12 +21,14 @@ import mineplex.core.achievement.AchievementManager; import mineplex.core.antihack.AntiHack; import mineplex.core.antihack.guardians.AntiHackGuardian; import mineplex.core.antihack.guardians.GuardianManager; +import mineplex.core.aprilfools.AprilFoolsManager; import mineplex.core.blockrestore.BlockRestore; import mineplex.core.chat.Chat; import mineplex.core.chatsnap.SnapshotManager; import mineplex.core.chatsnap.SnapshotPlugin; import mineplex.core.chatsnap.SnapshotRepository; import mineplex.core.command.CommandCenter; +import mineplex.core.common.Constants; import mineplex.core.common.MinecraftVersion; import mineplex.core.common.Pair; import mineplex.core.common.events.ServerShutdownEvent; @@ -74,12 +77,13 @@ import mineplex.game.clans.shop.mining.MiningShop; import mineplex.game.clans.shop.pvp.PvpShop; import mineplex.game.clans.spawn.travel.TravelShop; import mineplex.game.clans.world.WorldManager; - -import static mineplex.core.Managers.require; +import net.minecraft.server.v1_8_R3.MinecraftServer; public class Clans extends JavaPlugin { - public static final String MAP = "Season 2"; + public static final String MAP = "Season 3"; + + public static boolean HARDCORE = false; // Modules private CoreClientManager _clientManager; @@ -89,6 +93,14 @@ public class Clans extends JavaPlugin @Override public void onEnable() { + try + { + HARDCORE = new File(new File(".").getCanonicalPath() + File.separator + "Hardcore.dat").exists(); + } + catch (IOException e) + { + e.printStackTrace(); + } Bukkit.setSpawnRadius(0); // Configs diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Farming.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Farming.java index 1027a2253..78a0fd82c 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Farming.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Farming.java @@ -1,33 +1,17 @@ package mineplex.game.clans; -import com.google.common.collect.Sets; -import mineplex.core.MiniPlugin; -import mineplex.core.common.util.UtilItem; -import mineplex.core.itemstack.ItemStackFactory; -import mineplex.core.common.util.F; -import mineplex.core.common.util.UtilPlayer; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.event.EventHandler; import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.plugin.java.JavaPlugin; -import java.util.Set; +import mineplex.core.MiniPlugin; +import mineplex.core.common.util.UtilItem; +import mineplex.core.itemstack.ItemStackFactory; public class Farming extends MiniPlugin { - private static final Set PLANTABLE = Sets.newHashSet( - Material.WHEAT, - Material.SUGAR_CANE_BLOCK, - Material.PUMPKIN_STEM, - Material.MELON_STEM, - Material.COCOA, - Material.CARROT, - Material.POTATO - ); - public Farming(JavaPlugin plugin) { super("Farming", plugin); @@ -50,27 +34,4 @@ public class Farming extends MiniPlugin if (Math.random() > 0.999) event.getBlock().getWorld().dropItemNaturally(dropLocation, ItemStackFactory.Instance.CreateStack(Material.GOLDEN_APPLE)); } - - @EventHandler (ignoreCancelled = true) - public void BlockPlace(BlockPlaceEvent event) - { - if (!PLANTABLE.contains(event.getBlock().getType())) - return; - - double blockY = event.getBlock().getLocation().getY(); - double seaLevel = event.getBlock().getWorld().getSeaLevel(); - - if (blockY < seaLevel - 12) - { - UtilPlayer.message(event.getPlayer(), F.main(getName(), "You cannot plant " + - F.item(ItemStackFactory.Instance.GetName(event.getPlayer().getItemInHand(), true)) + " this deep underground.")); - event.setCancelled(true); - } - else if (blockY > seaLevel + 24) - { - UtilPlayer.message(event.getPlayer(), F.main(getName(), "You cannot plant " + - F.item(ItemStackFactory.Instance.GetName(event.getPlayer().getItemInHand(), true)) + " at this altitude.")); - event.setCancelled(true); - } - } -} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClanInfo.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClanInfo.java index a07074f98..2d4d42389 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClanInfo.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClanInfo.java @@ -11,7 +11,6 @@ import java.util.UUID; import org.bukkit.Location; import org.bukkit.Sound; -import org.bukkit.block.Block; import org.bukkit.entity.Player; import mineplex.core.common.util.C; @@ -208,11 +207,18 @@ public class ClanInfo } public int getAlliesMax() + { + return getAlliesMaxWithMemberCountOf(_memberMap.size()); + } + + public int getAlliesMaxWithMemberCountOf(int memberCount) { if (ssAdmin()) + { return 1000; - - return Math.max(2, 9 - _memberMap.size()); + } + + return Math.max(2, 6 - memberCount); } public BedStatus getBedStatus() diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansAdmin.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansAdmin.java index 3b8c45896..fcc116670 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansAdmin.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansAdmin.java @@ -372,15 +372,11 @@ public class ClansAdmin } else { - Clans.getClanDataAccess().war(clan, clanAgainst, value, new Callback() + Clans.getClanDataAccess().war(clan, clanAgainst, value, data -> { - @Override - public void run(ClanWarData data) - { - UtilPlayer.message(caller, F.main("Clans Admin", "Updated war points against " + F.elem(data.getClanB()))); - Clans.messageClan(clan, F.main("Clans", "Your war points with " + F.elem(clanAgainst.getName()) + " have been edited by " + F.elem(caller.getName()) + "!")); - Clans.messageClan(clanAgainst, F.main("Clans", "Your war points with " + F.elem(clan.getName()) + " have been edited by " + F.elem(caller.getName()) + "!")); - } + UtilPlayer.message(caller, F.main("Clans Admin", "Updated war points against " + F.elem(data.getClanB()))); + Clans.messageClan(clan, F.main("Clans", "Your war points with " + F.elem(clanAgainst.getName()) + " have been edited by " + F.elem(caller.getName()) + "!")); + Clans.messageClan(clanAgainst, F.main("Clans", "Your war points with " + F.elem(clan.getName()) + " have been edited by " + F.elem(caller.getName()) + "!")); }); } } @@ -401,15 +397,11 @@ public class ClansAdmin } else { - Clans.getClanDataAccess().war(clan, clanAgainst, value, new Callback() + Clans.getClanDataAccess().war(clan, clanAgainst, value, data -> { - @Override - public void run(ClanWarData data) - { - UtilPlayer.message(caller, F.main("Clans Admin", "Updated war points against " + F.elem(data.getClanB()))); - Clans.messageClan(clan, F.main("Clans", "Your war points with " + F.elem(clanAgainst.getName()) + " have been edited by " + F.elem(caller.getName()) + "!")); - Clans.messageClan(clanAgainst, F.main("Clans", "Your war points with " + F.elem(clan.getName()) + " have been edited by " + F.elem(caller.getName()) + "!")); - } + UtilPlayer.message(caller, F.main("Clans Admin", "Updated war points against " + F.elem(data.getClanB()))); + Clans.messageClan(clan, F.main("Clans", "Your war points with " + F.elem(clanAgainst.getName()) + " have been edited by " + F.elem(caller.getName()) + "!")); + Clans.messageClan(clanAgainst, F.main("Clans", "Your war points with " + F.elem(clan.getName()) + " have been edited by " + F.elem(caller.getName()) + "!")); }); } } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansBlocks.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansBlocks.java index 6a38d402c..fe4755ca0 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansBlocks.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansBlocks.java @@ -78,6 +78,8 @@ public class ClansBlocks denyUsePlace.add(390); //Pot denyUsePlace.add(404); //Comparator denyUsePlace.add(407); //TNT Cart + denyUsePlace.add(287); //String + denyUsePlace.add(397); //Skulls } if (id == 65) diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansDisplay.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansDisplay.java index 804690b92..0c5629d2d 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansDisplay.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansDisplay.java @@ -9,6 +9,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.plugin.java.JavaPlugin; +import mineplex.core.Managers; import mineplex.core.MiniPlugin; import mineplex.core.common.util.C; import mineplex.core.common.util.F; @@ -20,6 +21,8 @@ import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; import mineplex.game.clans.clans.ClansUtility.ClanRelation; import mineplex.game.clans.clans.event.PlayerEnterTerritoryEvent; +import mineplex.game.clans.clans.nether.NetherManager; +import mineplex.game.clans.clans.worldevent.WorldEventManager; import mineplex.game.clans.core.repository.ClanTerritory; public class ClansDisplay extends MiniPlugin @@ -56,7 +59,7 @@ public class ClansDisplay extends MiniPlugin client.setTerritory(UtilWorld.chunkToStr(player.getLocation().getChunk())); // AutoClaim - if (client.isAutoClaim()) _clansManager.getClanAdmin().claim(player); + if (client.isAutoClaim() && !(Managers.get(NetherManager.class).isInNether(player) || Managers.get(WorldEventManager.class).getRaidManager().isInRaid(player.getLocation()))) _clansManager.getClanAdmin().claim(player); // Map String owner = "Wilderness"; @@ -65,7 +68,7 @@ public class ClansDisplay extends MiniPlugin boolean safe = _clansManager.getClanUtility().isSafe(player); - PlayerEnterTerritoryEvent event = new PlayerEnterTerritoryEvent(player, client.getOwner(), owner, (owner.equals("Wilderness") && !_clansManager.getNetherManager().isInNether(player)) ? false : _clansManager.getClanUtility().getClaim(player.getLocation()).isSafe(player.getLocation()), true); + PlayerEnterTerritoryEvent event = new PlayerEnterTerritoryEvent(player, client.getOwner(), owner, safe, true); UtilServer.getServer().getPluginManager().callEvent(event); @@ -127,6 +130,11 @@ public class ClansDisplay extends MiniPlugin } } + if (_clansManager.getWorldEvent().getRaidManager().isInRaid(player.getLocation())) + { + ownerString = C.cDRed + "Raid World"; + } + // if (_clansManager.getNetherManager().isInNether(player)) // { // _clansManager.message(player, "You are not allowed to claim territory in " + F.clansNether("The Nether") + "."); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java index 989eb95b7..b5c293a04 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansManager.java @@ -31,6 +31,7 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.server.ServerListPingEvent; import org.bukkit.event.vehicle.VehicleEnterEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.java.JavaPlugin; @@ -85,11 +86,13 @@ import mineplex.core.task.TaskManager; import mineplex.core.teleport.Teleport; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.Clans; import mineplex.game.clans.clans.ClanTips.TipType; import mineplex.game.clans.clans.ClansUtility.ClanRelation; import mineplex.game.clans.clans.amplifiers.AmplifierManager; import mineplex.game.clans.clans.ban.ClansBanManager; import mineplex.game.clans.clans.banners.BannerManager; +import mineplex.game.clans.clans.boxes.BoxManager; import mineplex.game.clans.clans.commands.ClanManagementCommand; import mineplex.game.clans.clans.commands.ClansAllyChatCommand; import mineplex.game.clans.clans.commands.ClansChatCommand; @@ -104,6 +107,7 @@ import mineplex.game.clans.clans.gui.ClanShop; import mineplex.game.clans.clans.invsee.InvseeManager; import mineplex.game.clans.clans.loot.LootManager; import mineplex.game.clans.clans.map.ItemMapManager; +import mineplex.game.clans.clans.mounts.MountManager; import mineplex.game.clans.clans.nameblacklist.ClansBlacklist; import mineplex.game.clans.clans.nether.NetherManager; import mineplex.game.clans.clans.observer.ObserverManager; @@ -433,10 +437,10 @@ public class ClansManager extends MiniClientPluginimplements IRelati new Location(Spawn.getSpawnWorld(), -25, 200, 390), // East Spawn - new Location(Spawn.getSpawnWorld(), 34, 200, -393), - new Location(Spawn.getSpawnWorld(), 8, 200, -365), - new Location(Spawn.getSpawnWorld(), -25, 200, -393), - new Location(Spawn.getSpawnWorld(), 8, 200, -424) + new Location(Spawn.getSpawnWorld(), 34, 206, -393), + new Location(Spawn.getSpawnWorld(), 8, 206, -365), + new Location(Spawn.getSpawnWorld(), -25, 206, -393), + new Location(Spawn.getSpawnWorld(), 8, 206, -424) ); List welcomeHolograms = Arrays.asList( @@ -444,10 +448,10 @@ public class ClansManager extends MiniClientPluginimplements IRelati new Location(Spawn.getSpawnWorld(), 8, 200, 399), new Location(Spawn.getSpawnWorld(), 0, 200, 390), new Location(Spawn.getSpawnWorld(), 8, 200, 381), - new Location(Spawn.getSpawnWorld(), 8, 200, -384), - new Location(Spawn.getSpawnWorld(), 0, 200, -393), - new Location(Spawn.getSpawnWorld(), 8, 200, -402), - new Location(Spawn.getSpawnWorld(), 17, 200, -393) + new Location(Spawn.getSpawnWorld(), 8, 206, -384), + new Location(Spawn.getSpawnWorld(), 0, 206, -393), + new Location(Spawn.getSpawnWorld(), 8, 206, -402), + new Location(Spawn.getSpawnWorld(), 17, 206, -393) ); for (Location location : jumpOffHolograms) @@ -472,6 +476,10 @@ public class ClansManager extends MiniClientPluginimplements IRelati _netherManager = new NetherManager(this); _amplifierManager = new AmplifierManager(plugin); + new MountManager(plugin, clientManager, donationManager); + + new BoxManager(plugin); + _restartManager = new RestartManager(plugin); } @@ -650,6 +658,19 @@ public class ClansManager extends MiniClientPluginimplements IRelati public long lastPower = System.currentTimeMillis(); + @EventHandler + public void displayHardcoreMode(ServerListPingEvent event) + { + if (Clans.HARDCORE) + { + event.setMotd("Hardcore"); + } + else + { + event.setMotd("Casual"); + } + } + @EventHandler public void savePlayerActiveBuild(PlayerQuitEvent event) { @@ -912,7 +933,7 @@ public class ClansManager extends MiniClientPluginimplements IRelati recipients.clear(); } - @EventHandler + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void disableObsidian(BlockBreakEvent event) { if(event.getBlock().getType().equals(Material.OBSIDIAN)) @@ -1220,6 +1241,7 @@ public class ClansManager extends MiniClientPluginimplements IRelati _safeLog.onDisable(); _restartManager.onDisable(); _observerManager.onDisable(); + Managers.get(MountManager.class).onDisable(); } @EventHandler(priority = EventPriority.HIGHEST) @@ -1387,29 +1409,6 @@ public class ClansManager extends MiniClientPluginimplements IRelati } } - @EventHandler - public void damageHorse(EntityDamageEvent event) - { - if (event.getEntity() instanceof Horse) - { - if (event.getEntity().getPassenger() != null && event.getEntity().getPassenger() instanceof Player) - { - event.getEntity().getPassenger().eject(); - Recharge.Instance.use((Player) event.getEntity().getPassenger(), "Ride Horse", 2 * 20L, false, false); - } - event.getEntity().eject(); - - } - else if(event.getEntity() instanceof Player) - { - if(event.getEntity().getVehicle() != null && event.getEntity().getVehicle() instanceof Horse) - { - Recharge.Instance.use((Player) event.getEntity(), "Ride Horse", 2 * 20L, false, false); - event.getEntity().getVehicle().eject(); - } - } - } - public Pair leftRecently(UUID uniqueId, long time) { if (_clanMemberLeftMap.containsKey(uniqueId) && (System.currentTimeMillis() - _clanMemberLeftMap.get(uniqueId).getRight()) <= time) @@ -1465,4 +1464,4 @@ public class ClansManager extends MiniClientPluginimplements IRelati { return _incognitoManager; } -} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansUtility.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansUtility.java index b1c63970f..a2ecef65e 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansUtility.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ClansUtility.java @@ -1221,6 +1221,12 @@ public class ClansUtility UtilPlayer.message(caller, F.main("Clans", "You cannot invite yourself.")); return; } + + if (clan.getAllies() > clan.getAlliesMaxWithMemberCountOf(clan.getSize() + 1)) + { + UtilPlayer.message(caller, F.main("Clans", "You cannot invite more members until you remove some allies.")); + return; + } // Inform clan.inform(F.name(caller.getName()) + " invited " + F.name(target.getName()) + " to join your Clan.", caller.getName()); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ban/ClansBanManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ban/ClansBanManager.java index 8b3d18877..ab8e38228 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ban/ClansBanManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/ban/ClansBanManager.java @@ -266,7 +266,7 @@ public class ClansBanManager extends MiniPlugin player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, 999999, -10)); for (Player alert : UtilServer.GetPlayers()) { - if (_clientManager.Get(staff).GetRank().has(null, Rank.ADMIN, new Rank[] {Rank.CMOD, Rank.CMA}, false)) + if (_clientManager.Get(alert).GetRank().has(null, Rank.ADMIN, new Rank[] {Rank.CMOD, Rank.CMA}, false)) { UtilPlayer.message(alert, F.main(getName(), F.elem(player.getName()) + " has been frozen by " + F.elem(staff.getName()) + "!")); } @@ -287,7 +287,7 @@ public class ClansBanManager extends MiniPlugin player.removePotionEffect(PotionEffectType.JUMP); for (Player alert : UtilServer.GetPlayers()) { - if (_clientManager.Get(staff).GetRank().has(null, Rank.ADMIN, new Rank[] {Rank.CMOD, Rank.CMA}, false)) + if (_clientManager.Get(alert).GetRank().has(null, Rank.ADMIN, new Rank[] {Rank.CMOD, Rank.CMA}, false)) { UtilPlayer.message(alert, F.main(getName(), F.elem(player.getName()) + " has been unfrozen by " + F.elem(staff.getName()) + "!")); continue; diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/banners/BannerManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/banners/BannerManager.java index 307e1590d..6b5503b3c 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/banners/BannerManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/banners/BannerManager.java @@ -10,6 +10,7 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.event.block.BlockPlaceEvent; @@ -170,7 +171,7 @@ public class BannerManager extends MiniPlugin } } - @EventHandler + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onBreak(BlockBreakEvent event) { if (event.getBlock().getType() == Material.STANDING_BANNER || event.getBlock().getType() == Material.WALL_BANNER) diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/BoxManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/BoxManager.java new file mode 100644 index 000000000..c0019ad74 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/BoxManager.java @@ -0,0 +1,222 @@ +package mineplex.game.clans.clans.boxes; + +import java.util.function.Consumer; + +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.inventory.CraftItemEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.event.inventory.PrepareItemCraftEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; + +import mineplex.core.Managers; +import mineplex.core.MiniPlugin; +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.C; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.game.clans.clans.boxes.extra.BuilderBoxInventory; +import mineplex.game.clans.clans.boxes.extra.DyeBoxSpinner; + +public class BoxManager extends MiniPlugin +{ + private BuilderBoxInventory _builderBox; + + public BoxManager(JavaPlugin plugin) + { + super("Box Manager", plugin); + + final BoxShop shop = new BoxShop(this); + + _builderBox = new BuilderBoxInventory(); + + addCommand(new CommandBase(this, Rank.ALL, "boxes", "box") + { + @Override + public void Execute(Player caller, String[] args) + { + shop.attemptShopOpen(caller); + } + }); + } + + @EventHandler(priority=EventPriority.HIGHEST) + public void onCraftWithDye(PrepareItemCraftEvent event) + { + if (event.getInventory().getResult() == null) + { + return; + } + if (event.getInventory().getResult().getType() == Material.LAPIS_BLOCK) + { + for (ItemStack item : event.getInventory().getMatrix()) + { + if (item == null) + { + continue; + } + if (item.hasItemMeta() && item.getItemMeta().hasDisplayName() && item.getItemMeta().getDisplayName().equals(C.cGold + "Dye")) + { + event.getInventory().setResult(null); + return; + } + } + return; + } + if (event.getInventory().getResult().getType() == Material.INK_SACK) + { + event.getInventory().setResult(null); + return; + } + for (ItemStack item : event.getInventory().getMatrix()) + { + if (item == null) + { + continue; + } + if (item.getType() != Material.INK_SACK) + { + continue; + } + if (!item.hasItemMeta() || !item.getItemMeta().hasDisplayName() || !item.getItemMeta().getDisplayName().equals(C.cGold + "Dye")) + { + event.getInventory().setResult(null); + } + } + } + + @EventHandler(priority=EventPriority.HIGHEST) + public void onCraftWithDye(CraftItemEvent event) + { + if (event.getInventory().getResult() == null) + { + return; + } + if (event.getInventory().getResult().getType() == Material.LAPIS_BLOCK) + { + for (ItemStack item : event.getInventory().getMatrix()) + { + if (item == null) + { + continue; + } + if (item.hasItemMeta() && item.getItemMeta().hasDisplayName() && item.getItemMeta().getDisplayName().equals(C.cGold + "Dye")) + { + event.setCancelled(true); + return; + } + } + return; + } + if (event.getInventory().getResult().getType() == Material.INK_SACK) + { + event.setCancelled(true); + return; + } + for (ItemStack item : event.getInventory().getMatrix()) + { + if (item == null) + { + continue; + } + if (item.getType() != Material.INK_SACK) + { + continue; + } + if (!item.hasItemMeta() || !item.getItemMeta().hasDisplayName() || !item.getItemMeta().getDisplayName().equals(C.cGold + "Dye")) + { + event.setCancelled(true); + } + } + } + + @EventHandler(priority=EventPriority.HIGHEST) + public void onPlaceDyeInAnvil(InventoryClickEvent event) + { + if (!(event.getWhoClicked() instanceof Player)) + { + return; + } + if (!event.getInventory().getType().equals(InventoryType.ANVIL)) + { + return; + } + if (!(event.getCursor() != null && event.getCursor().hasItemMeta() && event.getCursor().getItemMeta().hasDisplayName() && event.getCursor().getItemMeta().getDisplayName().equals(C.cGold + "Dye")) && !(event.getCurrentItem() != null && event.getCurrentItem().hasItemMeta() && event.getCurrentItem().getItemMeta().hasDisplayName() && event.getCurrentItem().getItemMeta().getDisplayName().equals(C.cGold + "Dye"))) + { + return; + } + event.setCancelled(true); + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) + { + if (event.getItem() == null || !event.getItem().hasItemMeta() || !event.getItem().getItemMeta().hasDisplayName()) + { + return; + } + if (event.getItem().getItemMeta().getDisplayName().equals(C.cGold + "Dye")) + { + event.setCancelled(true); + } + } + + public static enum BoxType + { + BUILDER_BOX("Clans Builder Box", C.cGold + "Builder's Box", Material.GLOWSTONE, Managers.get(BoxManager.class)._builderBox::open), + @SuppressWarnings("deprecation") + DYE_BOX("Clans Dye Box", C.cGreen + "Dye Box", Material.INK_SACK, DyeColor.RED.getDyeData(), DyeBoxSpinner::createSpinner), + ; + + private String _itemName, _displayName; + private ItemBuilder _displayBuilder; + private Consumer _itemGenerator; + + private BoxType(String itemName, String displayName, Material displayMaterial, Consumer itemGenerator) + { + _itemName = itemName; + _displayName = displayName; + _displayBuilder = new ItemBuilder(displayMaterial).setTitle(displayName).addLore(C.cRed); + _itemGenerator = itemGenerator; + } + + private BoxType(String itemName, String displayName, Material displayMaterial, short data, Consumer itemGenerator) + { + _itemName = itemName; + _displayName = displayName; + _displayBuilder = new ItemBuilder(displayMaterial).setData(data).setTitle(displayName).addLore(C.cRed); + _itemGenerator = itemGenerator; + } + + public String getItemName() + { + return _itemName; + } + + public String getDisplayName() + { + return _displayName; + } + + public ItemStack getDisplayItem(int owned) + { + ItemBuilder newBuilder = new ItemBuilder(_displayBuilder.build()); + if (owned > 0) + { + newBuilder.setGlow(true); + } + return newBuilder.addLore(C.cGreenB + "Owned: " + C.cWhite + owned).build(); + } + + public void onUse(Player player) + { + _itemGenerator.accept(player); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/BoxOverviewPage.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/BoxOverviewPage.java new file mode 100644 index 000000000..bd17da0de --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/BoxOverviewPage.java @@ -0,0 +1,49 @@ +package mineplex.game.clans.clans.boxes; + +import org.bukkit.Sound; +import org.bukkit.entity.Player; + +import mineplex.core.recharge.Recharge; +import mineplex.core.shop.item.IButton; +import mineplex.core.shop.page.ShopPageBase; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.boxes.BoxManager.BoxType; + +public class BoxOverviewPage extends ShopPageBase +{ + public BoxOverviewPage(BoxManager plugin, BoxShop shop, String name, Player player) + { + super(plugin, shop, ClansManager.getInstance().getClientManager(), ClansManager.getInstance().getDonationManager(), name, player, 9); + + buildPage(); + } + + @Override + protected void buildPage() + { + int[] slots = {3, 5}; + for (int i = 0; i < BoxType.values().length && i < slots.length; i++) + { + BoxType type = BoxType.values()[i]; + int slot = slots[i]; + final int owns = ClansManager.getInstance().getInventoryManager().Get(getPlayer()).getItemCount(type.getItemName()); + IButton button = (player, clickType) -> + { + if (owns < 1) + { + playDenySound(player); + } + else + { + player.closeInventory(); + player.playSound(player.getLocation(), Sound.CHEST_OPEN, 1f, 1f); + if (Recharge.Instance.use(player, "Clans Box Click", 1000, false, false)) + { + type.onUse(player); + } + } + }; + addButton(slot, type.getDisplayItem(owns), button); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/BoxShop.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/BoxShop.java new file mode 100644 index 000000000..bc7e8a852 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/BoxShop.java @@ -0,0 +1,21 @@ +package mineplex.game.clans.clans.boxes; + +import org.bukkit.entity.Player; + +import mineplex.core.shop.ShopBase; +import mineplex.core.shop.page.ShopPageBase; +import mineplex.game.clans.clans.ClansManager; + +public class BoxShop extends ShopBase +{ + public BoxShop(BoxManager plugin) + { + super(plugin, ClansManager.getInstance().getClientManager(), ClansManager.getInstance().getDonationManager(), "Your Boxes"); + } + + @Override + protected ShopPageBase> buildPagesFor(Player player) + { + return new BoxOverviewPage(getPlugin(), this, "Your Boxes", player); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/extra/BuilderBoxInventory.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/extra/BuilderBoxInventory.java new file mode 100644 index 000000000..e45db862a --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/extra/BuilderBoxInventory.java @@ -0,0 +1,171 @@ +package mineplex.game.clans.clans.boxes.extra; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryView; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.Pair; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.boxes.BoxManager.BoxType; + +public class BuilderBoxInventory implements Listener +{ + private Map, ItemStack> _replace = new HashMap<>(); + + public BuilderBoxInventory() + { + _replace.put(Pair.create(Material.STONE, (byte)0), new ItemStack(Material.STAINED_CLAY)); + _replace.put(Pair.create(Material.GLASS, (byte)0), new ItemStack(Material.STAINED_GLASS)); + _replace.put(Pair.create(Material.THIN_GLASS, (byte)0), new ItemStack(Material.STAINED_GLASS_PANE)); + _replace.put(Pair.create(Material.WOOL, (byte)0), new ItemStack(Material.WOOL)); + _replace.put(Pair.create(Material.CARPET, (byte)0), new ItemStack(Material.CARPET)); + _replace.put(Pair.create(Material.RED_ROSE, (byte)0), new ItemStack(Material.RED_ROSE)); + _replace.put(Pair.create(Material.RED_ROSE, (byte)1), new ItemStack(Material.RED_ROSE)); + _replace.put(Pair.create(Material.RED_ROSE, (byte)2), new ItemStack(Material.RED_ROSE)); + _replace.put(Pair.create(Material.RED_ROSE, (byte)3), new ItemStack(Material.RED_ROSE)); + _replace.put(Pair.create(Material.RED_ROSE, (byte)4), new ItemStack(Material.RED_ROSE)); + _replace.put(Pair.create(Material.RED_ROSE, (byte)5), new ItemStack(Material.RED_ROSE)); + _replace.put(Pair.create(Material.RED_ROSE, (byte)6), new ItemStack(Material.RED_ROSE)); + _replace.put(Pair.create(Material.RED_ROSE, (byte)7), new ItemStack(Material.RED_ROSE)); + _replace.put(Pair.create(Material.RED_ROSE, (byte)8), new ItemStack(Material.RED_ROSE)); + _replace.put(Pair.create(Material.COBBLE_WALL, (byte)0), new ItemStack(Material.COBBLE_WALL)); + _replace.put(Pair.create(Material.JACK_O_LANTERN, (byte)0), new ItemStack(Material.GLOWSTONE)); + _replace.put(Pair.create(Material.SMOOTH_BRICK, (byte)0), new ItemStack(Material.SMOOTH_BRICK)); + + UtilServer.RegisterEvents(this); + } + + @SuppressWarnings("deprecation") + private Pair convert(ItemStack old) + { + if (old == null) + { + return Pair.create(old, false); + } + Pair pair = Pair.create(old.getType(), old.getData().getData()); + if (!_replace.containsKey(pair)) + { + return Pair.create(old, false); + } + ItemBuilder after = new ItemBuilder(_replace.get(pair)); + if (after.getType() == Material.RED_ROSE) + { + after.setData((short)UtilMath.r(9)); + } + else if (after.getType() == Material.COBBLE_WALL) + { + after.setData((short)1); + } + else if (after.getType() == Material.GLOWSTONE) + { + after.setData((short)0); + } + else if (after.getType() == Material.SMOOTH_BRICK) + { + after.setData(UtilMath.randomElement(new Short[] {1, 3}).shortValue()); + } + else + { + after.setData(UtilMath.randomElement(DyeColor.values()).getWoolData()); + } + after.setAmount(old.getAmount()); + + return Pair.create(after.build(), true); + } + + @SuppressWarnings("deprecation") + public void open(Player player) + { + Inventory newInv = Bukkit.createInventory(player, 27, "Builder's Box"); + ItemStack border = new ItemBuilder(Material.STAINED_GLASS_PANE).setData((short)DyeColor.GRAY.getWoolData()).setTitle(C.cRed + " ").build(); + ItemStack button = new ItemBuilder(Material.STAINED_GLASS_PANE).setData((short)DyeColor.LIME.getWoolData()).setTitle(C.cGreenB + "Convert").build(); + for (int i = 0; i < 27; i++) + { + if (i == 22) + { + newInv.setItem(i, button); + continue; + } + if (i < 9 || i > 17) + { + newInv.setItem(i, border); + } + } + player.openInventory(newInv); + } + + @EventHandler + public void onClose(InventoryCloseEvent event) + { + InventoryView view = event.getView(); + if (view.getTopInventory() != null) + { + Inventory top = view.getTopInventory(); + if (top.getTitle().equals("Builder's Box")) + { + List items = new ArrayList<>(); + for (int i = 9; i < 18; i++) + { + items.add(top.getItem(i)); + } + if (items != null && !items.isEmpty()); + { + int totalChanged = 0; + for (Pair pair : items.stream().map(this::convert).collect(Collectors.toList())) + { + if (pair.getLeft() == null) + { + continue; + } + if (pair.getRight()) + { + totalChanged++; + } + event.getPlayer().getInventory().addItem(pair.getLeft()); + } + if (totalChanged > 0) + { + ClansManager.getInstance().getInventoryManager().addItemToInventory((Player)event.getPlayer(), BoxType.BUILDER_BOX.getItemName(), -1); + UtilPlayer.message(event.getPlayer(), F.main("Builder's Box", "You have redeemed your box contents!")); + } + } + } + } + } + + @EventHandler + public void onClick(InventoryClickEvent event) + { + if (event.getClickedInventory() != null && event.getClickedInventory().getTitle().equals("Builder's Box")) + { + if (event.getSlot() < 9 || event.getSlot() > 17) + { + event.setCancelled(true); + } + if (event.getSlot() == 22) + { + event.getWhoClicked().closeInventory(); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/extra/DyeBoxSpinner.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/extra/DyeBoxSpinner.java new file mode 100644 index 000000000..0186f6b56 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/boxes/extra/DyeBoxSpinner.java @@ -0,0 +1,172 @@ +package mineplex.game.clans.clans.boxes.extra; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.boxes.BoxManager.BoxType; + +public class DyeBoxSpinner implements Listener +{ + private Player _player; + private Inventory _inv; + private int _step; + private List _items; + + private boolean _givenRewards = false; + + private DyeBoxSpinner(Player player) + { + _player = player; + _inv = Bukkit.createInventory(player, 27, "Dye Box"); + _step = 0; + _items = new ArrayList<>(); + buildGUI(); + generateRewards(); + player.openInventory(_inv); + Bukkit.getPluginManager().registerEvents(this, UtilServer.getPlugin()); + } + + /** + * Upper and lower bounds are inclusive + */ + private int getRandom(int max, int min) + { + return UtilMath.r(max - min + 1) + min; + } + + @SuppressWarnings("deprecation") + private void buildGUI() + { + ItemStack border = new ItemBuilder(Material.STAINED_GLASS_PANE).setData((short)DyeColor.GRAY.getWoolData()).setTitle(C.cRed + " ").build(); + ItemStack fill = new ItemBuilder(Material.STAINED_GLASS_PANE).setData((short)DyeColor.BLACK.getWoolData()).setTitle(C.cRed + " ").build(); + for (int i = 0; i < 27; i++) + { + if (i < 9 || i > 17) + { + _inv.setItem(i, border); + } + else + { + _inv.setItem(i, fill); + } + } + } + + @SuppressWarnings("deprecation") + private void generateRewards() + { + List commonColors = Arrays.asList(DyeColor.values()).stream().filter(c -> c != DyeColor.BLACK && c != DyeColor.WHITE).collect(Collectors.toList()); + List rareColors = Arrays.asList(DyeColor.WHITE, DyeColor.BLACK); + for (int i = 1; i <= getRandom(9, 5); i++) + { + DyeColor color = null; + if (Math.random() <= 0.05) + { + color = UtilMath.randomElement(rareColors); + } + else + { + color = UtilMath.randomElement(commonColors); + } + + _items.add(new ItemBuilder(Material.INK_SACK).setData(color.getDyeData()).setTitle(C.cGold + "Dye").build()); + } + } + + private void giveRewards() + { + if (_givenRewards) + { + return; + } + _givenRewards = true; + _player.closeInventory(); + _items.forEach(_player.getInventory()::addItem); + UtilPlayer.message(_player, F.main("Dye Box", "You have redeemed your box contents!")); + } + + @SuppressWarnings("deprecation") + private void progress() + { + if (_step == 0) + { + _step++; + return; + } + if (_step < 10) + { + int slot = 18 - _step; + if (Math.max(18, slot) - Math.min(18, slot) <= _items.size()) + { + _inv.setItem(slot, new ItemBuilder(Material.STAINED_GLASS_PANE).setData((short)DyeColor.LIME.getWoolData()).setTitle(C.cRed + " ").build()); + } + _step++; + return; + } + if (_step == 10) + { + int slot = 17; + for (int i = 0; i < _items.size(); i++) + { + _inv.setItem(slot, _items.get(i)); + slot--; + } + _step++; + return; + } + } + + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() == UpdateType.FASTEST) + { + if (_player.getOpenInventory() == null || _player.getOpenInventory().getTopInventory() == null || !_player.getOpenInventory().getTopInventory().getName().equals("Dye Box")) + { + HandlerList.unregisterAll(this); + giveRewards(); + } + } + if (event.getType() == UpdateType.SEC) + { + progress(); + } + } + + @EventHandler + public void onClick(InventoryClickEvent event) + { + if (event.getWhoClicked().getEntityId() == _player.getEntityId()) + { + event.setCancelled(true); + } + } + + public static void createSpinner(Player player) + { + ClansManager.getInstance().getInventoryManager().addItemToInventory(player, BoxType.DYE_BOX.getItemName(), -1); + new DyeBoxSpinner(player); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansAllyChatCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansAllyChatCommand.java index b1723b719..fdbd287a4 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansAllyChatCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansAllyChatCommand.java @@ -2,10 +2,13 @@ package mineplex.game.clans.clans.commands; import org.bukkit.entity.Player; +import mineplex.core.Managers; import mineplex.core.command.CommandBase; import mineplex.core.common.Rank; import mineplex.core.common.util.F; import mineplex.core.common.util.UtilPlayer; +import mineplex.core.punish.Punish; +import mineplex.core.punish.PunishClient; import mineplex.game.clans.clans.ClanInfo; import mineplex.game.clans.clans.ClansManager; @@ -39,7 +42,16 @@ public class ClansAllyChatCommand extends CommandBase { ClanInfo clan = Plugin.getClanUtility().getClanByPlayer(caller); if (clan == null) UtilPlayer.message(caller, F.main("Clans", "You are not in a Clan.")); - else Plugin.chatAlly(clan, caller, F.combine(args, 0, null, false)); + else + { + PunishClient punishClient = Managers.get(Punish.class).GetClient(caller.getName()); + if (punishClient != null && punishClient.IsMuted()) + { + UtilPlayer.message(caller, F.main("Clans", "You cannot do this while muted!")); + return; + } + Plugin.chatAlly(clan, caller, F.combine(args, 0, null, false)); + } } } } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansChatCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansChatCommand.java index 36619c1ef..3ce97064c 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansChatCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansChatCommand.java @@ -2,10 +2,13 @@ package mineplex.game.clans.clans.commands; import org.bukkit.entity.Player; +import mineplex.core.Managers; import mineplex.core.command.CommandBase; import mineplex.core.common.Rank; import mineplex.core.common.util.F; import mineplex.core.common.util.UtilPlayer; +import mineplex.core.punish.Punish; +import mineplex.core.punish.PunishClient; import mineplex.game.clans.clans.ClanInfo; import mineplex.game.clans.clans.ClansManager; @@ -41,7 +44,15 @@ public class ClansChatCommand extends CommandBase if (clan == null) UtilPlayer.message(caller, F.main("Clans", "You are not in a Clan.")); else + { + PunishClient punishClient = Managers.get(Punish.class).GetClient(caller.getName()); + if (punishClient != null && punishClient.IsMuted()) + { + UtilPlayer.message(caller, F.main("Clans", "You cannot do this while muted!")); + return; + } Plugin.chatClan(clan, caller, F.combine(args, 0, null, false)); + } } } } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansCommand.java index 39511c874..adef219f9 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/commands/ClansCommand.java @@ -549,6 +549,12 @@ public class ClansCommand extends CommandBase UtilPlayer.message(caller, F.main("Clans", "The clan " + F.elem("Clan " + clan.getName()) + " is full and cannot be joined!")); return; } + + if (clan.getAllies() > clan.getAlliesMaxWithMemberCountOf(clan.getSize() + 1)) + { + UtilPlayer.message(caller, F.main("Clans", "You cannot join " + F.elem("Clan " + clan.getName()) + " until they remove some allies!")); + return; + } ClanJoinEvent event = new ClanJoinEvent(clan, caller); Bukkit.getPluginManager().callEvent(event); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/ClanIcon.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/ClanIcon.java index 078b469f7..118549e90 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/ClanIcon.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/ClanIcon.java @@ -7,8 +7,8 @@ public enum ClanIcon JOIN(Material.PRISMARINE, (byte) 1), LEAVE(Material.PRISMARINE, (byte) 2), TERRITORY(Material.PRISMARINE, (byte) 0), - MEMBER(Material.SAND, (byte) 1), - COMMANDS(Material.RED_SANDSTONE, (byte) 0), + MEMBER(Material.WATER_BUCKET, (byte) 0), + COMMANDS(Material.LAVA_BUCKET, (byte) 0), ENERGY(Material.SEA_LANTERN, (byte) 0), CASTLE(Material.RECORD_9, (byte) 0), WAR(Material.RECORD_11, (byte) 0), diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/button/ClanTerritoryButton.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/button/ClanTerritoryButton.java index 363c78f01..ebcff0611 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/button/ClanTerritoryButton.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/button/ClanTerritoryButton.java @@ -9,6 +9,7 @@ import org.bukkit.event.inventory.ClickType; import mineplex.core.common.util.C; import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; import mineplex.core.common.util.UtilWorld; import mineplex.game.clans.clans.ClanInfo; import mineplex.game.clans.clans.ClanRole; @@ -27,12 +28,18 @@ public class ClanTerritoryButton extends ClanButton { if (UtilServer.CallEvent(new ClansButtonClickEvent(player, ClansButtonClickEvent.ButtonType.Territory)).isCancelled()) return; -// if (_clansManager.getNetherManager().isInNether(player)) -// { -// _clansManager.message(player, "You are not allowed to do anything with Territory while in " + F.clansNether("The Nether") + "."); -// player.closeInventory(); -// return; -// } + if (_clansManager.getNetherManager().isInNether(player)) + { + UtilPlayer.message(player, F.main(_clansManager.getNetherManager().getName(), "You cannot manage your clan's territory while in " + F.clansNether("The Nether") + "!")); + player.closeInventory(); + return; + } + if (_clansManager.getWorldEvent().getRaidManager().isInRaid(player.getLocation())) + { + UtilPlayer.message(player, F.main(_clansManager.getWorldEvent().getRaidManager().getName(), "You cannot manage your clan's territory while in a raid!")); + player.closeInventory(); + return; + } if (clickType == ClickType.LEFT) { diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/page/ClanMainPage.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/page/ClanMainPage.java index 7db99c36b..ee6361d72 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/page/ClanMainPage.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/gui/page/ClanMainPage.java @@ -361,4 +361,4 @@ public class ClanMainPage extends ClanPageBase addButton(slot, item, new ClanMemeberButton(getShop(), getPlugin(), getPlayer(), guiInfo, guiRole, this, clansPlayer.getPlayerName())); } -} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/loot/LootManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/loot/LootManager.java index a322d8041..949723a3a 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/loot/LootManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/loot/LootManager.java @@ -4,6 +4,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; +import mineplex.game.clans.clans.mounts.Mount.MountType; import mineplex.game.clans.economy.GoldManager; import mineplex.game.clans.items.GearManager; import mineplex.core.common.weight.WeightSet; @@ -87,8 +88,9 @@ public class LootManager private void populateRare() { // Gear - _rareSet.add(90, new GearLoot(_gearManager)); + _rareSet.add(70, new GearLoot(_gearManager)); _rareSet.add(10, new GoldTokenLoot(50000, 100000)); + _rareSet.add(20, new MountLoot(1, 3, MountType.values())); } public void dropCommon(Location location) diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/loot/MountLoot.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/loot/MountLoot.java new file mode 100644 index 000000000..65fe0c074 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/loot/MountLoot.java @@ -0,0 +1,45 @@ +package mineplex.game.clans.clans.loot; + +import org.bukkit.Color; +import org.bukkit.FireworkEffect.Type; +import org.bukkit.Location; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.UtilFirework; +import mineplex.core.common.util.UtilMath; +import mineplex.game.clans.clans.mounts.Mount.MountType; +import mineplex.game.clans.clans.mounts.MountClaimToken; + +public class MountLoot implements ILoot +{ + private int _minStars, _maxStars; + private MountType[] _types; + + public MountLoot(int minStars, int maxStars, MountType... types) + { + _minStars = Math.max(minStars, 1); + _maxStars = Math.min(maxStars, 3); + if (types.length == 0) + { + _types = MountType.values(); + } + else + { + _types = types; + } + } + + @Override + public void dropLoot(Location location) + { + MountClaimToken token = new MountClaimToken(UtilMath.rRange(_minStars, _maxStars), UtilMath.rRange(_minStars, _maxStars), UtilMath.rRange(_minStars, _maxStars), UtilMath.randomElement(_types)); + UtilFirework.playFirework(location.clone().add(0, 3, 0), Type.BALL, Color.SILVER, true, false); + location.getWorld().dropItemNaturally(location.clone().add(0, 3, 0), token.toItem()); + } + + @Override + public ItemStack getItemStack() + { + return new MountClaimToken(UtilMath.rRange(_minStars, _maxStars), UtilMath.rRange(_minStars, _maxStars), UtilMath.rRange(_minStars, _maxStars), UtilMath.randomElement(_types)).toItem(); + } +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/map/ItemMapRenderer.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/map/ItemMapRenderer.java index 69835e4ae..07ac8f1cf 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/map/ItemMapRenderer.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/map/ItemMapRenderer.java @@ -1,20 +1,6 @@ package mineplex.game.clans.clans.map; import java.awt.Color; -import java.util.List; - -import mineplex.core.common.util.UtilTime; -import mineplex.core.recharge.Recharge; -import mineplex.game.clans.clans.ClanInfo; -import mineplex.game.clans.clans.ClansUtility; -import mineplex.game.clans.clans.worldevent.WorldEventManager; -import mineplex.game.clans.tutorial.TutorialManager; -import mineplex.game.clans.tutorial.TutorialRegion; -import mineplex.game.clans.tutorial.TutorialType; -import mineplex.game.clans.tutorial.map.TutorialMapManager; -import mineplex.game.clans.tutorial.tutorials.clans.ClansMainTutorial; -import mineplex.minecraft.game.core.boss.EventState; -import mineplex.minecraft.game.core.boss.WorldEvent; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -26,6 +12,14 @@ import org.bukkit.map.MapPalette; import org.bukkit.map.MapRenderer; import org.bukkit.map.MapView; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.ClanInfo; +import mineplex.game.clans.clans.ClansUtility; +import mineplex.game.clans.clans.worldevent.WorldEventManager; +import mineplex.game.clans.clans.worldevent.api.EventState; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.game.clans.tutorial.TutorialManager; + public class ItemMapRenderer extends MapRenderer { private ItemMapManager _manager; diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/Mount.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/Mount.java new file mode 100644 index 000000000..093631e9b --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/Mount.java @@ -0,0 +1,370 @@ +package mineplex.game.clans.clans.mounts; + +import java.util.function.Consumer; + +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftHorse; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Horse.Color; +import org.bukkit.entity.Horse.Style; +import org.bukkit.entity.Horse.Variant; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.TriConsumer; +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.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.disguise.disguises.DisguiseBase; +import mineplex.core.disguise.disguises.DisguiseCow; +import mineplex.core.disguise.disguises.DisguiseSheep; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.game.clans.clans.ClansManager; +import net.minecraft.server.v1_8_R3.GenericAttributes; + +public class Mount +{ + private static final long HIT_REGEN_COOLDOWN = 30000; + + private Player _owner; + private CraftHorse _entity; + private SkinType _skin; + private final int _strength; + private long _lastHit; + private int _hits; + + public Mount(Player owner, CraftHorse entity, SkinType skin, int strength) + { + _owner = owner; + _entity = entity; + _skin = skin; + _strength = strength; + _lastHit = System.currentTimeMillis(); + _hits = 0; + } + + public Player getOwner() + { + return _owner; + } + + public CraftHorse getEntity() + { + return _entity; + } + + public void update() + { + if (_skin != null) + { + _skin.onUpdate(_entity); + } + if (UtilTime.elapsed(_lastHit, HIT_REGEN_COOLDOWN) && _hits > 0) + { + _hits--; + _lastHit = System.currentTimeMillis(); + } + } + + public void despawn(boolean forced) + { + UtilServer.CallEvent(new MountDespawnEvent(this, forced)); + _entity.getInventory().setSaddle(null); + _entity.getInventory().setArmor(null); + for (ItemStack item : _entity.getInventory().getContents()) + { + if (item == null || item.getType() == Material.AIR) + { + continue; + } + _entity.getWorld().dropItem(_entity.getLocation(), item); + } + _entity.remove(); + } + + public void handleHit() + { + _hits++; + if (_hits == _strength) + { + despawn(true); + } + } + + public static enum SkinType + { + INFERNAL_HORROR(1, "Clans Infernal Horror Mount Skin", C.cRed + "Infernal Horror", Material.BONE, Color.BLACK, Variant.SKELETON_HORSE, Style.BLACK_DOTS, horse -> {}, horse -> + { + UtilParticle.PlayParticleToAll(ParticleType.FLAME, horse.getLocation().add(0, 1, 0), + 0.25f, 0.25f, 0.25f, 0, 2,ViewDist.NORMAL); + }, MountType.HORSE), + GLACIAL_STEED(2, "Clans Glacial Steed Mount Skin", C.cGray + "Glacial Steed", Material.SNOW_BALL, Color.WHITE, Variant.HORSE, Style.WHITE, horse -> {}, horse -> + { + UtilParticle.PlayParticleToAll(ParticleType.SNOW_SHOVEL, horse.getLocation().add(0, 1, 0), + 0.25f, 0.25f, 0.25f, 0.1f, 4, ViewDist.NORMAL); + }, MountType.HORSE), + ZOMBIE_HORSE(3, "Clans Zombie Horse Mount Skin", C.cDGray + "Zombie Horse", Material.ROTTEN_FLESH, Color.BLACK, Variant.UNDEAD_HORSE, Style.BLACK_DOTS, horse -> {}, horse -> + { + UtilParticle.PlayParticleToAll(ParticleType.FOOTSTEP, horse.getLocation(), + null, 0, 1, ViewDist.NORMAL); + }, MountType.HORSE), + @SuppressWarnings("deprecation") + RAINBOW_SHEEP(4, "Clans Rainbow Sheep Mount Skin", C.cGreen + "Rainbow " + C.cAqua + "Sheep", new ItemBuilder(Material.WOOL).setData(DyeColor.RED.getWoolData()).build(),Color.WHITE, Variant.HORSE, Style.NONE, horse -> + { + DisguiseSheep disguise = new DisguiseSheep(horse); + disguise.setName(horse.getCustomName()); + ClansManager.getInstance().getDisguiseManager().disguise(disguise); + }, horse -> + { + DisguiseBase base = ClansManager.getInstance().getDisguiseManager().getActiveDisguise(horse); + if (base == null || !(base instanceof DisguiseSheep)) + { + return; + } + + DisguiseSheep sheep = (DisguiseSheep)base; + + if (horse.getTicksLived() % 4 == 0) sheep.setColor(DyeColor.RED); + else if (horse.getTicksLived() % 4 == 1) sheep.setColor(DyeColor.YELLOW); + else if (horse.getTicksLived() % 4 == 2) sheep.setColor(DyeColor.GREEN); + else if (horse.getTicksLived() % 4 == 3) sheep.setColor(DyeColor.BLUE); + }, MountType.HORSE), + ROYAL_STEED(5, "Clans Royal Steed Mount Skin", C.cGold + "Royal Steed", Material.DIAMOND_BARDING, Color.WHITE, Variant.HORSE, Style.WHITE, horse -> + { + horse.getInventory().setArmor(new ItemBuilder(Material.DIAMOND_BARDING).setTitle(C.cGoldB + "Royal Armor").build()); + }, horse -> + { + UtilParticle.PlayParticleToAll(ParticleType.BLOCK_DUST.getParticle(Material.GOLD_BLOCK, 0), horse.getLocation().add(0, 1, 0), + 0.25f, 0.25f, 0.25f, 0, 3, ViewDist.NORMAL); + }, MountType.HORSE), + ROYAL_GUARD_STEED(6, "Clans Royal Guard Steed Mount Skin", C.cGray + "Royal Guard's Steed", Material.GOLD_BARDING, Color.BLACK, Variant.HORSE, Style.NONE, horse -> + { + horse.getInventory().setArmor(new ItemBuilder(Material.GOLD_BARDING).setTitle(C.cGoldB + "Guardian Armor").build()); + }, horse -> + { + UtilParticle.PlayParticleToAll(ParticleType.BLOCK_DUST.getParticle(Material.IRON_BLOCK, 0), horse.getLocation().add(0, 1, 0), + 0.25f, 0.25f, 0.25f, 0, 3, ViewDist.NORMAL); + }, MountType.HORSE), + KNIGHT_STEED(7, "Clans Knight Steed Mount Skin", C.cDRed + "Knight's Steed", Material.IRON_BARDING, Color.GRAY, Variant.HORSE, Style.NONE, horse -> + { + horse.getInventory().setArmor(new ItemBuilder(Material.IRON_BARDING).setTitle(C.cGoldB + "Knightly Armor").build()); + }, horse -> + { + UtilParticle.PlayParticleToAll(ParticleType.ICON_CRACK.getParticle(Material.APPLE, 0), horse.getLocation().add(0, 1, 0), + 0.25f, 0.25f, 0.25f, 0, 3, ViewDist.NORMAL); + }, MountType.HORSE), + COW(8, "Clans Cow Mount Skin", C.cWhite + "Cow", Material.MILK_BUCKET, Color.WHITE, Variant.HORSE, Style.NONE, horse -> + { + DisguiseCow disguise = new DisguiseCow(horse); + disguise.setName(horse.getCustomName()); + ClansManager.getInstance().getDisguiseManager().disguise(disguise); + }, horse -> {}, MountType.HORSE), + SHEEP(9, "Clans Sheep Mount Skin", C.cWhite + "Sheep", Material.WOOL, Color.WHITE, Variant.HORSE, Style.NONE, horse -> + { + DisguiseSheep disguise = new DisguiseSheep(horse); + disguise.setName(horse.getCustomName()); + ClansManager.getInstance().getDisguiseManager().disguise(disguise); + }, horse -> {}, MountType.HORSE), + TRUSTY_MULE(10, "Clans Trusty Mule Mount Skin", C.cBlue + "Trusty Mule", Material.APPLE, Color.BROWN, Variant.MULE, Style.NONE, horse -> {}, horse -> {}, MountType.DONKEY) + ; + + private final int _id; + private final String _packageName; + private final String _displayName; + private final ItemStack _baseDisplayItem; + private final Color _color; + private final Variant _variant; + private final Style _style; + private final Consumer _onSpawn, _onUpdate; + private final MountType[] _possibleTypes; + + private SkinType(int id, String packageName, String displayName, Material displayType, Color color, Variant variant, Style style, Consumer onSpawn, Consumer onUpdate, MountType... possibleTypes) + { + this(id, packageName, displayName, new ItemStack(displayType), color, variant, style, onSpawn, onUpdate, possibleTypes); + } + + private SkinType(int id, String packageName, String displayName, ItemStack baseDisplayItem, Color color, Variant variant, Style style, Consumer onSpawn, Consumer onUpdate, MountType... possibleTypes) + { + _id = id; + _packageName = packageName; + _displayName = displayName; + _baseDisplayItem = baseDisplayItem; + _color = color; + _variant = variant; + _style = style; + _onSpawn = onSpawn; + _onUpdate = onUpdate; + _possibleTypes = possibleTypes; + } + + public int getId() + { + return _id; + } + + public String getPackageName() + { + return _packageName; + } + + public String getDisplayName() + { + return _displayName; + } + + public ItemStack getBaseDisplay() + { + return _baseDisplayItem; + } + + public Color getColor() + { + return _color; + } + + public Variant getVariant() + { + return _variant; + } + + public Style getStyle() + { + return _style; + } + + public void onSpawn(CraftHorse horse) + { + _onSpawn.accept(horse); + } + + public void onUpdate(CraftHorse horse) + { + _onUpdate.accept(horse); + } + + public MountType[] getPossibleTypes() + { + return _possibleTypes; + } + + public static SkinType getFromId(int id) + { + for (SkinType type : SkinType.values()) + { + if (type.getId() == id) + { + return type; + } + } + + return null; + } + } + + public static enum MountType + { + HORSE(1, C.cWhite + "Horse", Material.IRON_BARDING, (owner, skin, stats) -> + { + CraftHorse horse = (CraftHorse) owner.getWorld().spawnEntity(owner.getLocation(), EntityType.HORSE); + horse.setAdult(); + horse.setAgeLock(true); + horse.setBreed(false); + horse.setCustomNameVisible(true); + horse.setCustomName(owner.getName() + "'s " + (skin == null ? "Horse" : ChatColor.stripColor(skin.getDisplayName()))); + if (skin != null) + { + horse.setVariant(skin.getVariant()); + horse.setColor(skin.getColor()); + horse.setStyle(skin.getStyle()); + skin.onSpawn(horse); + } + horse.setTamed(true); + horse.getInventory().setSaddle(new ItemStack(Material.SADDLE)); + horse.setOwner(owner); + horse.setJumpStrength(MountManager.getJump(stats.JumpStars)); + horse.getHandle().getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(MountManager.getSpeed(stats.SpeedStars)); + //horse.setPassenger(owner); + Mount mount = new Mount(owner, horse, skin, MountManager.getStrength(stats.StrengthStars)); + UtilServer.CallEvent(new MountSpawnEvent(mount)); + }), + DONKEY(2, C.cWhite + "Donkey", Material.GOLD_BARDING, (owner, skin, stats) -> + { + CraftHorse horse = (CraftHorse) owner.getWorld().spawnEntity(owner.getLocation(), EntityType.HORSE); + horse.setAdult(); + horse.setAgeLock(true); + horse.setBreed(false); + horse.setCustomNameVisible(true); + horse.setCustomName(owner.getName() + "'s " + (skin == null ? "Donkey" : ChatColor.stripColor(skin.getDisplayName()))); + if (skin != null) + { + horse.setVariant(skin.getVariant()); + skin.onSpawn(horse); + } + else + { + horse.setVariant(Variant.DONKEY); + } + horse.setTamed(true); + horse.getInventory().setSaddle(new ItemStack(Material.SADDLE)); + horse.setOwner(owner); + horse.setJumpStrength(MountManager.getJump(stats.JumpStars)); + horse.getHandle().getAttributeInstance(GenericAttributes.MOVEMENT_SPEED).setValue(MountManager.getSpeed(stats.SpeedStars)); + horse.setCarryingChest(true); + //horse.setPassenger(owner); + Mount mount = new Mount(owner, horse, skin, MountManager.getStrength(stats.StrengthStars)); + UtilServer.CallEvent(new MountSpawnEvent(mount)); + }) + ; + + private final int _id; + private final String _displayName; + private final Material _displayType; + private final TriConsumer _spawnHandler; + + private MountType(int id, String displayName, Material displayType, TriConsumer spawnHandler) + { + _id = id; + _displayName = displayName; + _displayType = displayType; + _spawnHandler = spawnHandler; + } + + public int getId() + { + return _id; + } + + public String getDisplayName() + { + return _displayName; + } + + public Material getDisplayType() + { + return _displayType; + } + + public void spawn(Player owner, SkinType skinType, MountStatToken statToken) + { + _spawnHandler.accept(owner, skinType, statToken); + } + + public static MountType getFromId(int id) + { + for (MountType type : MountType.values()) + { + if (type.getId() == id) + { + return type; + } + } + + return null; + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountClaimToken.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountClaimToken.java new file mode 100644 index 000000000..63c0b11d6 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountClaimToken.java @@ -0,0 +1,103 @@ +package mineplex.game.clans.clans.mounts; + +import org.bukkit.ChatColor; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.C; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.game.clans.clans.mounts.Mount.MountType; + +public class MountClaimToken +{ + private final String STAR = "✩"; + + public final int JumpStars; + public final int SpeedStars; + public final int StrengthStars; + public final MountType Type; + + public MountClaimToken(int jumpStars, int speedStars, int strengthStars, MountType type) + { + JumpStars = jumpStars; + SpeedStars = speedStars; + StrengthStars = strengthStars; + Type = type; + } + + public ItemStack toItem() + { + ItemBuilder builder = new ItemBuilder(Type.getDisplayType()); + builder.setTitle(Type.getDisplayName() + " Mount Token"); + String strength = C.cYellow; + for (int i = 0; i < StrengthStars; i++) + { + strength += STAR; + } + builder.addLore(C.cPurple + "Strength: " + strength); + String speed = C.cYellow; + for (int i = 0; i < SpeedStars; i++) + { + speed += STAR; + } + builder.addLore(C.cPurple + "Speed: " + speed); + String jump = C.cYellow; + for (int i = 0; i < JumpStars; i++) + { + jump += STAR; + } + builder.addLore(C.cPurple + "Jump: " + jump); + builder.addLore(C.cRed); + builder.addLore(C.cDGreen + "Right-Click While Holding to Consume"); + + return builder.build(); + } + + public static MountClaimToken fromItem(ItemStack item) + { + if (!item.hasItemMeta() || !item.getItemMeta().hasLore()) + { + return null; + } + + MountType type = null; + for (MountType check : MountType.values()) + { + if (check.getDisplayType() == item.getType()) + { + type = check; + break; + } + } + if (type == null) + { + return null; + } + + int strength = -1; + int speed = -1; + int jump = -1; + + for (String lore : item.getItemMeta().getLore()) + { + if (ChatColor.stripColor(lore).startsWith("Strength: ")) + { + strength = ChatColor.stripColor(lore).replace("Strength: ", "").length(); + } + if (ChatColor.stripColor(lore).startsWith("Speed: ")) + { + speed = ChatColor.stripColor(lore).replace("Speed: ", "").length(); + } + if (ChatColor.stripColor(lore).startsWith("Jump: ")) + { + jump = ChatColor.stripColor(lore).replace("Jump: ", "").length(); + } + } + + if (strength <= 0 || speed <= 0 || jump <= 0) + { + return null; + } + + return new MountClaimToken(strength, speed, jump, type); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountDespawnEvent.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountDespawnEvent.java new file mode 100644 index 000000000..9d4745116 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountDespawnEvent.java @@ -0,0 +1,41 @@ +package mineplex.game.clans.clans.mounts; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Event called before a mount despawns + */ +public class MountDespawnEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + + private final Mount _mount; + private final boolean _forced; + + public MountDespawnEvent(Mount mount, boolean forced) + { + _mount = mount; + _forced = forced; + } + + public Mount getMount() + { + return _mount; + } + + public boolean isForced() + { + return _forced; + } + + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountManager.java new file mode 100644 index 000000000..2460ffea9 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountManager.java @@ -0,0 +1,528 @@ +package mineplex.game.clans.clans.mounts; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.WeakHashMap; + +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftHorse; +import org.bukkit.entity.Horse; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.inventory.HorseInventory; +import org.bukkit.plugin.java.JavaPlugin; + +import mineplex.core.MiniDbClientPlugin; +import mineplex.core.account.CoreClientManager; +import mineplex.core.command.CommandBase; +import mineplex.core.common.Pair; +import mineplex.core.common.Rank; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilEvent; +import mineplex.core.common.util.UtilEvent.ActionType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.donation.DonationManager; +import mineplex.core.recharge.Recharge; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.mounts.Mount.MountType; +import mineplex.game.clans.clans.mounts.Mount.SkinType; +import mineplex.game.clans.clans.mounts.gui.MountShop; +import mineplex.game.clans.spawn.Spawn; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import mineplex.serverdata.Utility; + +public class MountManager extends MiniDbClientPlugin +{ + private static final double[] JUMP_STARS = {0.8, 1, 1.2}; + private static final double[] SPEED_STARS = {0.2, 0.27, 0.33}; + private static final int[] STRENGTH_STARS = {1, 2, 3}; + + private static final long SUMMON_WARMUP = 5000; + private static final long FORCED_COOLDOWN = 120 * 1000; + private static final long MAX_TIME_DISMOUNTED = 30000; + + private static final int MAX_PER_TYPE = 3; + + private final MountRepository _repository; + private final DonationManager _donationManager; + + private final Map _spawnedMounts = new HashMap<>(); + private final Map> _summoning = new WeakHashMap<>(); + + public MountManager(JavaPlugin plugin, CoreClientManager clientManager, DonationManager donationManager) + { + super("Clans Mount Manager", plugin, clientManager); + + _repository = new MountRepository(plugin, this); + _donationManager = donationManager; + + final MountShop shop = new MountShop(this); + + addCommand(new CommandBase(this, Rank.ALL, "mounts", "mount") + { + @Override + public void Execute(Player caller, String[] args) + { + shop.attemptShopOpen(caller); + } + }); + + addCommand(new CommandBase(this, Rank.ADMIN, "givemount") + { + @Override + public void Execute(Player caller, String[] args) + { + if (args.length < 4) + { + UtilPlayer.message(caller, F.main(getName(), "Usage: /" + _aliasUsed + " ")); + return; + } + + Integer speed = 0; + Integer jump = 0; + Integer strength = 0; + MountType type = null; + + try + { + speed = Integer.parseInt(args[0]); + } + catch (Exception e) + { + UtilPlayer.message(caller, F.main(getName(), "Invalid speed!")); + return; + } + + try + { + jump = Integer.parseInt(args[1]); + } + catch (Exception e) + { + UtilPlayer.message(caller, F.main(getName(), "Invalid jump!")); + return; + } + + try + { + strength = Integer.parseInt(args[2]); + } + catch (Exception e) + { + UtilPlayer.message(caller, F.main(getName(), "Invalid strength!")); + return; + } + + try + { + type = MountType.valueOf(args[3]); + } + catch (Exception e) + { + UtilPlayer.message(caller, F.main(getName(), "Invalid type!")); + return; + } + + caller.getInventory().addItem(new MountClaimToken(jump, speed, strength, type).toItem()); + } + }); + } + + public DonationManager getDonationManager() + { + return _donationManager; + } + + public MountRepository getRepository() + { + return _repository; + } + + @Override + public void disable() + { + _summoning.clear(); + _spawnedMounts.keySet().forEach(CraftHorse::remove); + _spawnedMounts.clear(); + } + + public boolean summonMount(Player player, MountToken token) + { + if (_summoning.containsKey(player)) + { + UtilPlayer.message(player, F.main(getName(), "You are already summoning a mount!")); + return false; + } + if (Spawn.getInstance().isSafe(player.getLocation())) + { + UtilPlayer.message(player, F.main(getName(), "You cannot summon a mount in safezones!")); + return false; + } + if (ClansManager.getInstance().getNetherManager().isInNether(player)) + { + UtilPlayer.message(player, F.main(getName(), "You cannot summon a mount in the Nether!")); + return false; + } + if (ClansManager.getInstance().getWorldEvent().getRaidManager().isInRaid(player.getLocation())) + { + UtilPlayer.message(player, F.main(getName(), "You cannot summon a mount inside a raid!")); + return false; + } + if (!Recharge.Instance.usable(player, "Mount Spawn Delay")) + { + UtilPlayer.message(player, F.main(getName(), "You cannot summon a mount so soon after your last one was forcibly despawned!")); + return false; + } + _spawnedMounts.values().stream().filter(mount -> mount.getOwner().getEntityId() == player.getEntityId()).findFirst().ifPresent(mount -> mount.despawn(false)); + _summoning.put(player, Pair.create(System.currentTimeMillis(), token)); + UtilPlayer.message(player, F.main(getName(), "You are now summoning your mount! Please remain still for 5 seconds!")); + return true; + } + + public void giveMount(Player player, MountType type) + { + Pair tokens = Get(player).grantMount(type); + _repository.saveMount(ClientManager.getAccountId(player), tokens.getLeft(), tokens.getRight()); + } + + public void giveMount(Player player, MountClaimToken token) + { + Pair tokens = Get(player).grantMount(token.Type, token.SpeedStars, token.JumpStars, token.StrengthStars); + _repository.saveMount(ClientManager.getAccountId(player), tokens.getLeft(), tokens.getRight()); + } + + public void removeMountToken(Player player, MountToken token, Runnable after) + { + getRepository().deleteMount(token, id -> + { + Get(player).removeMount(id.intValue()); + Pair summonPair = _summoning.get(player); + if (summonPair != null) + { + if (summonPair.getRight().Id == id) + { + UtilEnt.addFlag(player, "REMOVED_MOUNT_TOKEN"); + } + } + after.run(); + }); + } + + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() == UpdateType.TICK) + { + Iterator> mountIterator = _spawnedMounts.entrySet().iterator(); + while (mountIterator.hasNext()) + { + Entry entry = mountIterator.next(); + if (entry.getKey().isDead() || !entry.getKey().isValid()) + { + mountIterator.remove(); + entry.getValue().despawn(false); + continue; + } + if (entry.getValue().getOwner().isDead() || !entry.getValue().getOwner().isValid() || !entry.getValue().getOwner().isOnline()) + { + mountIterator.remove(); + entry.getValue().despawn(false); + continue; + } + if (Spawn.getInstance().isSafe(entry.getKey().getLocation())) + { + mountIterator.remove(); + entry.getValue().despawn(false); + continue; + } + if (ClansManager.getInstance().getNetherManager().isInNether(entry.getKey().getLocation())) + { + mountIterator.remove(); + entry.getValue().despawn(false); + continue; + } + if (ClansManager.getInstance().getWorldEvent().getRaidManager().isInRaid(entry.getKey().getLocation())) + { + mountIterator.remove(); + entry.getValue().despawn(false); + continue; + } + if (entry.getKey().getPassenger() == null) + { + if (UtilEnt.GetMetadata(entry.getKey(), "DISMOUNT_TIME") != null) + { + Long dismount = (Long) UtilEnt.GetMetadata(entry.getKey(), "DISMOUNT_TIME"); + if (UtilTime.elapsed(dismount.longValue(), MAX_TIME_DISMOUNTED)) + { + mountIterator.remove(); + entry.getValue().despawn(false); + continue; + } + } + else + { + UtilEnt.SetMetadata(entry.getKey(), "DISMOUNT_TIME", System.currentTimeMillis()); + } + } + else + { + UtilEnt.removeMetadata(entry.getKey(), "DISMOUNT_TIME"); + } + entry.getValue().update(); + } + + Iterator>> summoningIterator = _summoning.entrySet().iterator(); + while (summoningIterator.hasNext()) + { + Entry> entry = summoningIterator.next(); + if (UtilEnt.hasFlag(entry.getKey(), "REMOVED_MOUNT_TOKEN")) + { + summoningIterator.remove(); + UtilEnt.removeFlag(entry.getKey(), "REMOVED_MOUNT_TOKEN"); + continue; + } + if (UtilTime.elapsed(entry.getValue().getLeft(), SUMMON_WARMUP)) + { + summoningIterator.remove(); + if (entry.getKey().isDead() || !entry.getKey().isValid() || !entry.getKey().isOnline()) + { + continue; + } + if (Spawn.getInstance().isSafe(entry.getKey().getLocation())) + { + continue; + } + if (ClansManager.getInstance().getNetherManager().isInNether(entry.getKey().getLocation())) + { + continue; + } + if (ClansManager.getInstance().getWorldEvent().getRaidManager().isInRaid(entry.getKey().getLocation())) + { + continue; + } + entry.getValue().getRight().Type.spawn(entry.getKey(), entry.getValue().getRight().Skin, Get(entry.getKey()).getStatToken(entry.getValue().getRight())); + continue; + } + if (UtilEnt.hasFlag(entry.getKey(), "MOVED_WHILE_SUMMONING_MOUNT")) + { + summoningIterator.remove(); + UtilEnt.removeFlag(entry.getKey(), "MOVED_WHILE_SUMMONING_MOUNT"); + UtilPlayer.message(entry.getKey(), F.main(getName(), "You have stopped summoning your mount as you have moved!")); + continue; + } + } + } + } + + @EventHandler + public void onMove(PlayerMoveEvent event) + { + if (_summoning.containsKey(event.getPlayer()) && !UtilEnt.hasFlag(event.getPlayer(), "MOVED_WHILE_SUMMONING_MOUNT")) + { + Block from = event.getFrom().getBlock(); + Block to = event.getTo().getBlock(); + + if (from.getX() == to.getX() && from.getY() == to.getY() && from.getZ() == to.getZ()) + { + return; + } + UtilEnt.addFlag(event.getPlayer(), "MOVED_WHILE_SUMMONING_MOUNT"); + } + } + + @EventHandler + public void onSummon(MountSpawnEvent event) + { + _spawnedMounts.put(event.getMount().getEntity(), event.getMount()); + UtilPlayer.message(event.getMount().getOwner(), F.main(getName(), "Your mount has spawned!")); + } + + @EventHandler + public void onDespawn(MountDespawnEvent event) + { + _spawnedMounts.remove(event.getMount().getEntity()); + event.getMount().getEntity().eject(); + event.getMount().getEntity().remove(); + UtilPlayer.message(event.getMount().getOwner(), F.main(getName(), "Your mount has despawned!")); + if (event.isForced()) + { + Recharge.Instance.use(event.getMount().getOwner(), "Mount Spawn Delay", FORCED_COOLDOWN, false, false); + } + } + + @EventHandler + public void onUseToken(PlayerInteractEvent event) + { + if (!UtilEvent.isAction(event, ActionType.R)) + { + return; + } + if (event.getItem() == null) + { + return; + } + MountClaimToken token = MountClaimToken.fromItem(event.getItem()); + if (token == null) + { + return; + } + + event.setCancelled(true); + + if (Get(event.getPlayer()).getAmountOwned(token.Type) >= MAX_PER_TYPE) + { + UtilPlayer.message(event.getPlayer(), F.main(getName(), "You have reached the maximum amount of that type of mount!")); + return; + } + + giveMount(event.getPlayer(), token); + UtilPlayer.message(event.getPlayer(), F.main(getName(), "You have redeemed your mount!")); + event.getPlayer().getInventory().setItemInHand(null); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void handleHorseHits(CustomDamageEvent event) + { + if (event.GetDamageeEntity() == null || !(event.GetDamageeEntity() instanceof Horse)) + { + return; + } + Mount mount = _spawnedMounts.get(event.GetDamageeEntity()); + if (mount == null) + { + return; + } + if (event.GetDamagerPlayer(true) != null && event.GetDamagerPlayer(true).getEntityId() == mount.getOwner().getEntityId()) + { + event.SetCancelled("Damaging own mount"); + mount.despawn(false); + return; + } + event.setDamagee(mount.getOwner()); + if (event.GetCause() != DamageCause.FALL) + { + mount.handleHit(); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void handleRiderHits(CustomDamageEvent event) + { + if (event.GetDamageePlayer() == null || event.GetDamageePlayer().getVehicle() == null || !(event.GetDamageePlayer().getVehicle() instanceof Horse)) + { + return; + } + if (event.GetDamagerPlayer(true) != null && event.GetDamagerPlayer(true).getEntityId() == event.GetDamageePlayer().getEntityId()) + { + return; + } + Mount mount = _spawnedMounts.get(event.GetDamageePlayer().getVehicle()); + if (mount == null) + { + return; + } + if (event.GetCause() != DamageCause.FALL) + { + mount.handleHit(); + } + } + + @EventHandler + public void onEditHorseInventory(InventoryClickEvent event) + { + if (!(event.getClickedInventory() instanceof HorseInventory)) + { + return; + } + if (!_spawnedMounts.containsKey(event.getClickedInventory().getHolder())) + { + return; + } + if (event.getSlot() == 0 || event.getSlot() == 1) + { + event.setCancelled(true); + } + } + + @EventHandler + public void mountInteract(PlayerInteractEntityEvent event) + { + if (!(event.getRightClicked() instanceof Horse)) + { + return; + } + Mount mount = _spawnedMounts.get(event.getRightClicked()); + if (mount == null) + { + return; + } + if (mount.getOwner().getEntityId() == event.getPlayer().getEntityId()) + { + return; + } + + UtilPlayer.message(event.getPlayer(), F.main(getName(), "This is not your Mount!")); + event.setCancelled(true); + } + + @Override + public String getQuery(int accountId, String uuid, String name) + { + return "SELECT am.id, am.mountTypeId, am.mountSkinId, ms.statToken FROM accountClansMounts AS am INNER JOIN clansMountStats AS ms ON ms.mountId = am.id WHERE am.accountId=" + accountId + ";"; + } + + @Override + public void processLoginResultSet(String playerName, UUID uuid, int accountId, ResultSet resultSet) throws SQLException + { + MountOwnerData data = new MountOwnerData(); + while (resultSet.next()) + { + MountToken token = new MountToken(); + token.Id = resultSet.getInt("id"); + token.Type = MountType.getFromId(resultSet.getInt("mountTypeId")); + token.Skin = SkinType.getFromId(resultSet.getInt("mountSkinId")); + MountStatToken statToken = Utility.deserialize(resultSet.getString("statToken"), MountStatToken.class); + data.acceptLoad(token, statToken); + } + Set(uuid, data); + } + + @Override + protected MountOwnerData addPlayer(UUID uuid) + { + return new MountOwnerData(); + } + + public static double getSpeed(int stars) + { + stars = Math.min(Math.max(1, stars), 3); + return SPEED_STARS[stars - 1]; + } + + public static double getJump(int stars) + { + stars = Math.min(Math.max(1, stars), 3); + return JUMP_STARS[stars - 1]; + } + + public static int getStrength(int stars) + { + stars = Math.min(Math.max(1, stars), 3); + return STRENGTH_STARS[stars - 1]; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountOwnerData.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountOwnerData.java new file mode 100644 index 000000000..9fdf52455 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountOwnerData.java @@ -0,0 +1,80 @@ +package mineplex.game.clans.clans.mounts; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import mineplex.core.common.Pair; +import mineplex.core.common.util.UtilMath; +import mineplex.game.clans.clans.mounts.Mount.MountType; + +public class MountOwnerData +{ + private Map _mounts = new LinkedHashMap<>(); + + public List> getOwnedMounts(boolean onlyInitialized) + { + return _mounts.entrySet().stream().filter(entry -> onlyInitialized ? entry.getKey().Id != -1 : true).map(entry -> Pair.create(entry.getKey(), entry.getValue())).collect(Collectors.toList()); + } + + public List> getOwnedMounts(boolean onlyInitialized, MountType type) + { + return _mounts.entrySet().stream().filter(entry -> (onlyInitialized ? entry.getKey().Id != -1 : true) && type == entry.getKey().Type).map(entry -> Pair.create(entry.getKey(), entry.getValue())).collect(Collectors.toList()); + } + + public MountStatToken getStatToken(MountToken mountToken) + { + return _mounts.get(mountToken); + } + + public boolean ownsMount(MountType type) + { + return getAmountOwned(type) > 0; + } + + public long getAmountOwned(MountType type) + { + return _mounts.keySet().stream().filter(token -> token.Type == type).count(); + } + + public void acceptLoad(MountToken token, MountStatToken statToken) + { + _mounts.put(token, statToken); + } + + public Pair grantMount(MountType type, int speed, int jump, int strength) + { + MountToken token = new MountToken(); + token.Type = type; + MountStatToken statToken = new MountStatToken(); + statToken.JumpStars = jump; + statToken.SpeedStars = speed; + statToken.StrengthStars = strength; + _mounts.put(token, statToken); + + return Pair.create(token, statToken); + } + + public Pair grantMount(MountType type) + { + int speed = UtilMath.rRange(1, 3); + int jump = UtilMath.rRange(1, 3); + int strength = UtilMath.rRange(1, 3); + + return grantMount(type, speed, jump, strength); + } + + public Integer[] removeMounts(MountType type) + { + Integer[] array = _mounts.keySet().stream().filter(token->token.Type == type).map(token->token.Id).toArray(size->new Integer[size]); + _mounts.keySet().removeIf(token->token.Type == type); + + return array; + } + + public void removeMount(int id) + { + _mounts.keySet().removeIf(token->token.Id == id); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountRepository.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountRepository.java new file mode 100644 index 000000000..821c887d2 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountRepository.java @@ -0,0 +1,180 @@ +package mineplex.game.clans.clans.mounts; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; +import java.util.function.Consumer; + +import org.bukkit.plugin.java.JavaPlugin; + +import mineplex.core.common.Pair; +import mineplex.serverdata.Utility; +import mineplex.serverdata.database.DBPool; +import mineplex.serverdata.database.RepositoryBase; +import mineplex.serverdata.database.column.ColumnInt; +import mineplex.serverdata.database.column.ColumnVarChar; + +/** + * Database repository class for mounts + */ +public class MountRepository extends RepositoryBase +{ + private static final String CREATE_MOUNTS_TABLE = "CREATE TABLE IF NOT EXISTS accountClansMounts (id INT NOT NULL AUTO_INCREMENT," + + "accountId INT NOT NULL," + + "mountTypeId INT NOT NULL," + + "mountSkinId INT NOT NULL," + + "INDEX typeIndex (mountTypeId)," + + "INDEX skinIndex (mountSkinId)," + + "PRIMARY KEY (id));"; + + private static final String CREATE_MOUNT_STATS_TABLE = "CREATE TABLE IF NOT EXISTS clansMountStats (mountId INT NOT NULL," + + "statToken VARCHAR(20) NOT NULL," + + "PRIMARY KEY (mountId));"; + + private static final String INSERT_MOUNT = "INSERT INTO accountClansMounts (accountId, mountTypeId, mountSkinId) VALUES (?, ?, ?);"; + private static final String SAVE_MOUNT = "UPDATE accountClansMounts SET mountSkinId=? WHERE id=?;"; + private static final String SAVE_MOUNT_STATS = "INSERT INTO clansMountStats (mountId, statToken) VALUES (?, ?) ON DUPLICATE KEY UPDATE statToken=VALUES(statToken);"; + private static final String DELETE_MOUNT = "DELETE FROM accountClansMounts WHERE id=?;"; + private static final String DELETE_MOUNT_STATS = "DELETE FROM clansMountStats WHERE mountId=?;"; + + private MountManager _mountManager; + + public MountRepository(JavaPlugin plugin, MountManager mountManager) + { + super(DBPool.getAccount()); + _mountManager = mountManager; + } + + /** + * Saves a mount into the database + * @param accountId The owner's account id + * @param token The mount token to save + * @param statToken The stat token to save + */ + public void saveMount(final int accountId, final MountToken token, final MountStatToken statToken) + { + _mountManager.runAsync(() -> + { + try (Connection connection = getConnection();) + { + if (token.Id == -1) + { + executeInsert(connection, INSERT_MOUNT, idResult -> + { + if (idResult.next()) + { + token.Id = idResult.getInt(1); + } + }, null, new ColumnInt("accountId", accountId), new ColumnInt("mountTypeId", token.Type.getId()), new ColumnInt("mountSkinId", token.Skin == null ? -1 : token.Skin.getId())); + } + else + { + executeUpdate(connection, SAVE_MOUNT, null, new ColumnInt("mountSkinId", token.Skin == null ? -1 : token.Skin.getId()), new ColumnInt("id", token.Id)); + } + if (token.Id == -1) + { + return; + } + executeUpdate(connection, SAVE_MOUNT_STATS, null, new ColumnInt("mountId", token.Id), new ColumnVarChar("statToken", 20, Utility.serialize(statToken))); + } + catch (SQLException e) + { + e.printStackTrace(); + } + }); + } + + /** + * Saves a list of mounts into the database + * @param accountId The owner's account id + * @param tokens The list of token pairs to save + */ + public void saveMounts(final int accountId, final List> tokens) + { + _mountManager.runAsync(() -> + { + try (Connection connection = getConnection()) + { + for (Pair tokenPair : tokens) + { + MountToken token = tokenPair.getLeft(); + MountStatToken statToken = tokenPair.getRight(); + + if (token.Id == -1) + { + executeInsert(connection, INSERT_MOUNT, idResult -> + { + if (idResult.next()) + { + token.Id = idResult.getInt(1); + } + }, null, new ColumnInt("accountId", accountId), new ColumnInt("mountTypeId", token.Type.getId()), new ColumnInt("mountSkinId", token.Skin == null ? -1 : token.Skin.getId())); + } + else + { + executeUpdate(connection, SAVE_MOUNT, null, new ColumnInt("mountSkinId", token.Skin == null ? -1 : token.Skin.getId()), new ColumnInt("id", token.Id)); + } + if (token.Id == -1) + { + continue; + } + executeUpdate(connection, SAVE_MOUNT_STATS, null, new ColumnInt("mountId", token.Id), new ColumnVarChar("statToken", 100, Utility.serialize(statToken))); + } + } + catch (SQLException e) + { + e.printStackTrace(); + } + }); + } + + /** + * Deletes a mount from the database + * @param token The mount to delete + */ + public void deleteMount(final MountToken token, final Consumer after) + { + if (token.Id == -1) + { + return; + } + _mountManager.runAsync(() -> + { + executeUpdate(DELETE_MOUNT, new ColumnInt("id", token.Id)); + executeUpdate(DELETE_MOUNT_STATS, new ColumnInt("mountId", token.Id)); + if (after != null) + { + _mountManager.runSync(() -> + { + after.accept(token.Id); + }); + } + }); + } + + /** + * Deletes an array from the database + * @param ids The mount ids to delete + */ + public void deleteMounts(final int[] ids, final Runnable after) + { + if (ids.length <= 0) + { + return; + } + _mountManager.runAsync(() -> + { + String idList = ids[0] + ""; + for (int i = 1; i < ids.length; i++) + { + idList += ("," + ids[i]); + } + executeUpdate(DELETE_MOUNT.replace("id=?;", "id IN (" + idList + ");")); + executeUpdate(DELETE_MOUNT_STATS.replace("mountId=?;", "mountId IN (" + idList + ");")); + if (after != null) + { + _mountManager.runSync(after); + } + }); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountSpawnEvent.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountSpawnEvent.java new file mode 100644 index 000000000..9d3e788aa --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountSpawnEvent.java @@ -0,0 +1,34 @@ +package mineplex.game.clans.clans.mounts; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Event called after a mount spawns + */ +public class MountSpawnEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + + private final Mount _mount; + + public MountSpawnEvent(Mount mount) + { + _mount = mount; + } + + public Mount getMount() + { + return _mount; + } + + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountStatToken.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountStatToken.java new file mode 100644 index 000000000..42517042e --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountStatToken.java @@ -0,0 +1,8 @@ +package mineplex.game.clans.clans.mounts; + +public class MountStatToken +{ + public int JumpStars = 1; + public int SpeedStars = 1; + public int StrengthStars = 1; +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountToken.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountToken.java new file mode 100644 index 000000000..8940344c0 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/MountToken.java @@ -0,0 +1,11 @@ +package mineplex.game.clans.clans.mounts; + +import mineplex.game.clans.clans.mounts.Mount.MountType; +import mineplex.game.clans.clans.mounts.Mount.SkinType; + +public class MountToken +{ + public int Id = -1; + public MountType Type = null; + public SkinType Skin = null; +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/gui/MountOverviewPage.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/gui/MountOverviewPage.java new file mode 100644 index 000000000..e3e1021ca --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/gui/MountOverviewPage.java @@ -0,0 +1,166 @@ +package mineplex.game.clans.clans.mounts.gui; + +import java.util.List; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.Pair; +import mineplex.core.common.util.C; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.shop.confirmation.ConfirmationCallback; +import mineplex.core.shop.confirmation.ConfirmationPage; +import mineplex.core.shop.confirmation.ConfirmationProcessor; +import mineplex.core.shop.item.IButton; +import mineplex.core.shop.page.ShopPageBase; +import mineplex.game.clans.clans.mounts.Mount.MountType; +import mineplex.game.clans.clans.mounts.MountManager; +import mineplex.game.clans.clans.mounts.MountStatToken; +import mineplex.game.clans.clans.mounts.MountToken; + +public class MountOverviewPage extends ShopPageBase +{ + private final String STAR = "✩"; + + public MountOverviewPage(MountManager plugin, MountShop shop, String name, Player player) + { + super(plugin, shop, plugin.getClientManager(), plugin.getDonationManager(), name, player, 27); + + buildPage(); + } + + private ItemStack toItem(MountToken mountToken, MountStatToken statToken, boolean overview) + { + ItemBuilder builder = new ItemBuilder(mountToken.Type.getDisplayType()); + builder.setTitle(mountToken.Type.getDisplayName() + " Mount"); + builder.addLore(C.cPurple + "Skin: " + (mountToken.Skin == null ? C.cYellow + "Default" : mountToken.Skin.getDisplayName())); + String strength = C.cYellow; + for (int i = 0; i < statToken.StrengthStars; i++) + { + strength += STAR; + } + builder.addLore(C.cPurple + "Strength: " + strength); + String speed = C.cYellow; + for (int i = 0; i < statToken.SpeedStars; i++) + { + speed += STAR; + } + builder.addLore(C.cPurple + "Speed: " + speed); + String jump = C.cYellow; + for (int i = 0; i < statToken.JumpStars; i++) + { + jump += STAR; + } + builder.addLore(C.cPurple + "Jump: " + jump); + if (overview) + { + builder.addLore(C.cRed); + builder.addLore(C.cDGreen + "Left-Click to Summon"); + builder.addLore(C.cDGreen + "Right-Click to Manage Skin"); + builder.addLore(C.cDRed + "Shift Right-Click to Destroy"); + } + + return builder.build(); + } + + @Override + protected void buildPage() + { + int[] horseSlots = {10, 11, 12}; + List> horses = getPlugin().Get(getPlayer()).getOwnedMounts(true, MountType.HORSE); + int[] donkeySlots = {14, 15, 16}; + List> donkeys = getPlugin().Get(getPlayer()).getOwnedMounts(true, MountType.DONKEY); + + for (int i = 0; i < horseSlots.length; i++) + { + int slot = horseSlots[i]; + ItemStack item = new ItemBuilder(Material.INK_SACK).setData((short)8).setTitle(C.cRed).build(); + IButton button = null; + if (horses.size() > i) + { + Pair tokens = horses.get(i); + item = toItem(tokens.getLeft(), tokens.getRight(), true); + button = (player, clickType) -> + { + if (clickType == ClickType.LEFT) + { + if (!getPlugin().summonMount(player, tokens.getLeft())) + { + playDenySound(player); + } + } + else if (clickType == ClickType.RIGHT) + { + getShop().openPageForPlayer(player, new MountSkinPage(this, player, tokens.getLeft())); + } + else if (clickType == ClickType.SHIFT_RIGHT) + { + getShop().openPageForPlayer(player, new ConfirmationPage(player, MountOverviewPage.this, new ConfirmationProcessor() + { + @Override + public void init(Inventory inventory) {} + + @Override + public void process(ConfirmationCallback callback) + { + getPlugin().removeMountToken(player, tokens.getLeft(), () -> + { + MountOverviewPage.this.refresh(); + callback.resolve("Mount successfully deleted!"); + }); + } + }, toItem(tokens.getLeft(), tokens.getRight(), false))); + } + }; + } + addButton(slot, item, button); + } + for (int i = 0; i < donkeySlots.length; i++) + { + int slot = donkeySlots[i]; + ItemStack item = new ItemBuilder(Material.INK_SACK).setData((short)8).setTitle(C.cRed).build(); + IButton button = null; + if (donkeys.size() > i) + { + Pair tokens = donkeys.get(i); + item = toItem(tokens.getLeft(), tokens.getRight(), true); + button = (player, clickType) -> + { + if (clickType == ClickType.LEFT) + { + if (!getPlugin().summonMount(player, tokens.getLeft())) + { + playDenySound(player); + } + } + else if (clickType == ClickType.RIGHT) + { + getShop().openPageForPlayer(player, new MountSkinPage(this, player, tokens.getLeft())); + } + else if (clickType == ClickType.SHIFT_RIGHT) + { + getShop().openPageForPlayer(player, new ConfirmationPage(player, new MountOverviewPage(getPlugin(), getShop(), getName(), getPlayer()), new ConfirmationProcessor() + { + @Override + public void init(Inventory inventory) {} + + @Override + public void process(ConfirmationCallback callback) + { + getPlugin().removeMountToken(player, tokens.getLeft(), () -> + { + MountOverviewPage.this.refresh(); + callback.resolve("Mount successfully deleted!"); + }); + } + }, toItem(tokens.getLeft(), tokens.getRight(), false))); + } + }; + } + addButton(slot, item, button); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/gui/MountShop.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/gui/MountShop.java new file mode 100644 index 000000000..d6dd454d5 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/gui/MountShop.java @@ -0,0 +1,21 @@ +package mineplex.game.clans.clans.mounts.gui; + +import org.bukkit.entity.Player; + +import mineplex.core.shop.ShopBase; +import mineplex.core.shop.page.ShopPageBase; +import mineplex.game.clans.clans.mounts.MountManager; + +public class MountShop extends ShopBase +{ + public MountShop(MountManager plugin) + { + super(plugin, plugin.getClientManager(), plugin.getDonationManager(), "Manage Mounts"); + } + + @Override + protected ShopPageBase> buildPagesFor(Player player) + { + return new MountOverviewPage(getPlugin(), this, "Manage Mounts", player); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/gui/MountSkinPage.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/gui/MountSkinPage.java new file mode 100644 index 000000000..64498e6c1 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/mounts/gui/MountSkinPage.java @@ -0,0 +1,142 @@ +package mineplex.game.clans.clans.mounts.gui; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.Rank; +import mineplex.core.common.util.C; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.shop.page.ShopPageBase; +import mineplex.game.clans.clans.mounts.Mount.SkinType; +import mineplex.game.clans.clans.mounts.MountManager; +import mineplex.game.clans.clans.mounts.MountToken; + +public class MountSkinPage extends ShopPageBase +{ + private MountOverviewPage _overview; + private MountToken _token; + + public MountSkinPage(MountOverviewPage overview, Player player, MountToken token) + { + super(overview.getPlugin(), overview.getShop(), overview.getClientManager(), overview.getDonationManager(), "Skin Management", player, 54); + + _overview = overview; + _token = token; + buildPage(); + } + + private List getAllowed() + { + List allowed = new LinkedList<>(); + + for (SkinType type : SkinType.values()) + { + if (Arrays.asList(type.getPossibleTypes()).contains(_token.Type)) + { + allowed.add(type); + } + } + + return allowed; + } + + private boolean hasUnlocked(Player player, SkinType type) + { + if (getClientManager().Get(player).GetRank().has(Rank.ADMIN)) + { + return true; + } + + return getDonationManager().Get(player).ownsUnknownSalesPackage(type.getPackageName()); + } + + private boolean hasUnlocked(SkinType type) + { + return hasUnlocked(getPlayer(), type); + } + + private ItemStack buildResetItem() + { + ItemBuilder builder = new ItemBuilder(Material.WATER_BUCKET); + + builder.setTitle(C.cYellow + "Default Skin"); + if (_token.Skin == null) + { + builder.setLore(C.cRed, C.cGreenB + "SELECTED"); + } + + return builder.build(); + } + + private ItemStack buildSkinItem(SkinType type) + { + ItemBuilder builder = new ItemBuilder(type.getBaseDisplay()); + + builder.setTitle(type.getDisplayName()); + builder.setLore(C.cRed); + if (_token.Skin == type) + { + builder.addLore(C.cGreenB + "SELECTED"); + } + else if (hasUnlocked(type)) + { + builder.addLore(C.cGreenB + "UNLOCKED"); + } + else + { + builder.addLore(C.cGray + "Available at http://www.mineplex.com/shop"); + builder.addLore(C.cRedB + "LOCKED"); + } + + return builder.build(); + } + + @Override + protected void buildPage() + { + addButton(0, new ItemBuilder(Material.BED).setTitle(C.cGreen + "Back").build(), (player, clickType) -> + { + _overview.refresh(); + getShop().openPageForPlayer(player, _overview); + }); + addButton(13, buildResetItem(), (player, clickType) -> + { + if (_token.Skin == null) + { + playDenySound(player); + } + else + { + playAcceptSound(player); + _token.Skin = null; + getPlugin().getRepository().saveMount(getClientManager().Get(player).getAccountId(), _token, getPlugin().Get(player).getStatToken(_token)); + refresh(); + } + }); + int[] skinSlots = {20, 21, 22, 23, 24, 29, 30, 31, 32, 33, 38, 39, 40, 41, 42}; + List allowed = getAllowed(); + for (int i = 0; i < skinSlots.length && i < allowed.size(); i++) + { + SkinType type = allowed.get(i); + addButton(skinSlots[i], buildSkinItem(type), (player, clickType) -> + { + if (hasUnlocked(player, type) && _token.Skin != type) + { + playAcceptSound(player); + _token.Skin = type; + getPlugin().getRepository().saveMount(getClientManager().Get(player).getAccountId(), _token, getPlugin().Get(player).getStatToken(_token)); + refresh(); + } + else + { + playDenySound(player); + } + }); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherManager.java index 79f0dab91..bca2c1acc 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/NetherManager.java @@ -1,5 +1,6 @@ package mineplex.game.clans.clans.nether; +import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -19,6 +20,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.entity.EntityPortalEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerDropItemEvent; @@ -52,11 +54,8 @@ import mineplex.game.clans.clans.nether.command.ForceTeleportCommand; import mineplex.game.clans.clans.nether.command.PortalCommand; import mineplex.game.clans.clans.nether.data.ClaimData; import mineplex.game.clans.clans.nether.miniboss.NetherMinibossManager; +import mineplex.game.clans.clans.worldevent.boss.BossDeathEvent; import mineplex.game.clans.spawn.Spawn; -import mineplex.minecraft.game.core.boss.EventCreatureDeathEvent; -import mineplex.minecraft.game.core.boss.broodmother.SpiderCreature; -import mineplex.minecraft.game.core.boss.ironwizard.GolemCreature; -import mineplex.minecraft.game.core.boss.skeletonking.SkeletonCreature; /** * Manager for all nether features @@ -75,9 +74,9 @@ public class NetherManager extends MiniPlugin private PortalRepository _repo; private NetherMinibossManager _miniboss; private World _netherWorld; - private List _portals = Lists.newArrayList(); - public List BossPortals = Lists.newArrayList(); - private List _returnPortals = Lists.newArrayList(); + private List _portals = new ArrayList<>(); + public List BossPortals = new ArrayList<>(); + private List _returnPortals = new ArrayList<>(); public Map InNether = new HashMap<>(); public Map OverworldOrigins = new HashMap<>(); public Map Claiming = new HashMap<>(); @@ -151,7 +150,17 @@ public class NetherManager extends MiniPlugin */ public boolean isInNether(Player player) { - return player.getWorld().equals(_netherWorld); + return isInNether(player.getLocation()); + } + + /** + * Checks if a location is in the nether + * @param location The location to check + * @return Whether the player is in the nether + */ + public boolean isInNether(Location location) + { + return location.getWorld().equals(_netherWorld); } /** @@ -298,6 +307,7 @@ public class NetherManager extends MiniPlugin } BossNetherPortal portal = new BossNetherPortal(bossSpawn.clone().add(-2, 5, 0), bossSpawn.clone().add(2, 0, 0), false); portal.open(PORTAL_OPEN_DURATION); + BossPortals.add(portal); for (NetherPortal returnPortal : _returnPortals) { returnPortal.open(-1); @@ -493,13 +503,19 @@ public class NetherManager extends MiniPlugin @EventHandler public void onTpHome(ClansCommandExecutedEvent event) { + if (!isInNether(event.getPlayer())) + { + return; + } if (event.getCommand().equalsIgnoreCase("tphome") || event.getCommand().equalsIgnoreCase("stuck")) { - if (isInNether(event.getPlayer())) - { - event.setCancelled(true); - UtilPlayer.message(event.getPlayer(), F.main(getName(), "You cannot teleport while in " + F.clansNether("The Nether") + "!")); - } + event.setCancelled(true); + UtilPlayer.message(event.getPlayer(), F.main(getName(), "You cannot teleport while in " + F.clansNether("The Nether") + "!")); + } + if (event.getCommand().equalsIgnoreCase("claim") || event.getCommand().equalsIgnoreCase("unclaim") || event.getCommand().equalsIgnoreCase("unclaimall") || event.getCommand().equalsIgnoreCase("homeset")) + { + event.setCancelled(true); + UtilPlayer.message(event.getPlayer(), F.main(getName(), "You cannot manage your clan's territory while in " + F.clansNether("The Nether") + "!")); } } @@ -555,11 +571,17 @@ public class NetherManager extends MiniPlugin } @EventHandler - public void onBossDeath(EventCreatureDeathEvent event) + public void onBossDeath(BossDeathEvent event) { - if (event.getCreature() instanceof GolemCreature || event.getCreature() instanceof SkeletonCreature || event.getCreature() instanceof SpiderCreature) + spawnBossPortal(event.getEvent().getCenterLocation().clone()); + } + + @EventHandler + public void onBlockDamage(EntityExplodeEvent event) + { + if (isInNether(event.getLocation())) { - spawnBossPortal(event.getCreature().getEvent().getCenterLocation().clone().subtract(0, 1, 0)); + event.setYield(0f); } } } \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/MinibossFireball.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/MinibossFireball.java index d33ad0de6..ea2976684 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/MinibossFireball.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/MinibossFireball.java @@ -1,11 +1,6 @@ package mineplex.game.clans.clans.nether.miniboss; -import java.util.HashMap; - -import mineplex.core.common.util.UtilAction; -import mineplex.core.common.util.UtilAlg; -import mineplex.core.common.util.UtilEnt; -import mineplex.game.clans.clans.ClansManager; +import java.util.Map; import org.bukkit.Bukkit; import org.bukkit.Sound; @@ -18,6 +13,11 @@ import org.bukkit.event.entity.ProjectileHitEvent; import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.util.Vector; +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilEnt; +import mineplex.game.clans.clans.ClansManager; + /** * Manager class for managing boss fireballs */ @@ -48,7 +48,7 @@ public class MinibossFireball implements Listener return; } - HashMap hitMap = UtilEnt.getInRadius(proj.getLocation(), FIREBALL_EXPLOSION_RANGE); + Map hitMap = UtilEnt.getInRadius(proj.getLocation(), FIREBALL_EXPLOSION_RANGE); for (LivingEntity cur : hitMap.keySet()) { double range = hitMap.get(cur); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/NetherMinibossManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/NetherMinibossManager.java index 3909e69c5..d93b5ba04 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/NetherMinibossManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/NetherMinibossManager.java @@ -1,8 +1,8 @@ package mineplex.game.clans.clans.nether.miniboss; -import java.util.Comparator; import java.util.HashMap; import java.util.List; +import java.util.Map; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -29,7 +29,7 @@ public class NetherMinibossManager implements Listener { private static final long MINIBOSS_SPAWN_RATE = 10000; private NetherManager _manager; - private HashMap _spawns = new HashMap<>(); + private Map _spawns = new HashMap<>(); private long _lastSpawned; private boolean _allowSpawn = false; private boolean _allowSpawnEvent = false; @@ -49,16 +49,13 @@ public class NetherMinibossManager implements Listener sort.add(new Location(manager.getNetherWorld(), 43, 134, 22)); sort.add(new Location(manager.getNetherWorld(), 102, 141, -31)); sort.add(new Location(manager.getNetherWorld(), 151, 136, 34)); - sort.sort(new Comparator() + sort.sort((o1, o2) -> { - public int compare(Location o1, Location o2) + if (UtilMath.offset2d(o1, manager.getNetherWorld().getSpawnLocation()) < UtilMath.offset(o2, manager.getNetherWorld().getSpawnLocation())) { - if (UtilMath.offset2d(o1, manager.getNetherWorld().getSpawnLocation()) < UtilMath.offset(o2, manager.getNetherWorld().getSpawnLocation())) - { - return -1; - } - return 1; + return -1; } + return 1; }); for (int i = 0; i < 3; i++) { diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/NetherMinibossType.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/NetherMinibossType.java index 938810015..3c48b7616 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/NetherMinibossType.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/NetherMinibossType.java @@ -17,12 +17,12 @@ public enum NetherMinibossType ARCHER("Undead Archer", 25D, EntityType.SKELETON, ArcherMiniboss.class) ; - private Class _code; + private Class> _code; private String _name; private Double _maxHealth; private EntityType _type; - private NetherMinibossType(String name, Double maxHealth, EntityType type, Class code) + private NetherMinibossType(String name, Double maxHealth, EntityType type, Class> code) { _name = name; _maxHealth = maxHealth; @@ -35,7 +35,7 @@ public enum NetherMinibossType * @param spawn The location to spawn the boss in * @return The instance of the miniboss */ - public NetherMiniBoss getNewInstance(Location spawn) + public NetherMiniBoss getNewInstance(Location spawn) { try { diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/ArcherMiniboss.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/ArcherMiniboss.java index d2a4e938c..b280f3393 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/ArcherMiniboss.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/ArcherMiniboss.java @@ -2,13 +2,6 @@ package mineplex.game.clans.clans.nether.miniboss.bosses; import java.util.Random; -import mineplex.core.common.util.UtilMath; -import mineplex.game.clans.clans.ClansManager; -import mineplex.game.clans.clans.amplifiers.AmplifierManager; -import mineplex.game.clans.clans.nether.miniboss.NetherMiniBoss; -import mineplex.game.clans.items.runes.RuneManager.RuneAttribute; -import mineplex.minecraft.game.core.damage.CustomDamageEvent; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Arrow; @@ -28,6 +21,13 @@ import org.bukkit.metadata.FixedMetadataValue; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; +import mineplex.core.common.util.UtilMath; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.amplifiers.AmplifierManager; +import mineplex.game.clans.clans.nether.miniboss.NetherMiniBoss; +import mineplex.game.clans.items.runes.RuneManager.RuneAttribute; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + /** * Class for running an individual Archer miniboss */ @@ -35,7 +35,10 @@ public class ArcherMiniboss extends NetherMiniBoss { private static final int BARBED_LEVEL = 1; private static final double RUNE_DROP_CHANCE = .02; - private static final int MAX_DIAMOND_DROPS = 5; + private static final int MAX_VALUABLE_DROPS = 5; + private static final Material[] VALUABLE_DROP_TYPES = new Material[] {Material.DIAMOND, Material.GOLD_INGOT, Material.IRON_INGOT, Material.LEATHER}; + private static final Material[] SET_DROP_TYPES = new Material[] {Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, Material.GOLD_HELMET, Material.GOLD_CHESTPLATE, Material.GOLD_LEGGINGS, Material.GOLD_BOOTS, Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS, Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS}; + private static final double SET_DROP_CHANCE = .02; public ArcherMiniboss(String displayName, Double maxHealth, Location spawn, EntityType type) { @@ -63,7 +66,7 @@ public class ArcherMiniboss extends NetherMiniBoss @Override public void customDeath(Location deathLocation) { - deathLocation.getWorld().dropItemNaturally(deathLocation, new ItemStack(Material.DIAMOND, UtilMath.r(MAX_DIAMOND_DROPS) + 1)); + deathLocation.getWorld().dropItemNaturally(deathLocation, new ItemStack(VALUABLE_DROP_TYPES[UtilMath.r(VALUABLE_DROP_TYPES.length)], UtilMath.r(MAX_VALUABLE_DROPS) + 1)); double runeDropChance = RUNE_DROP_CHANCE; if (ClansManager.getInstance().getAmplifierManager().hasActiveAmplifier()) { @@ -74,6 +77,10 @@ public class ArcherMiniboss extends NetherMiniBoss RuneAttribute runeType = RuneAttribute.values()[UtilMath.r(RuneAttribute.values().length)]; deathLocation.getWorld().dropItemNaturally(deathLocation, ClansManager.getInstance().getGearManager().getRuneManager().getRune(runeType)); } + if (new Random().nextDouble() <= SET_DROP_CHANCE) + { + deathLocation.getWorld().dropItemNaturally(deathLocation, new ItemStack(SET_DROP_TYPES[UtilMath.r(SET_DROP_TYPES.length)], 1)); + } } @EventHandler diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/GhastMiniboss.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/GhastMiniboss.java index 6ff341b58..d618923f5 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/GhastMiniboss.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/GhastMiniboss.java @@ -2,16 +2,6 @@ package mineplex.game.clans.clans.nether.miniboss.bosses; import java.util.Random; -import mineplex.core.common.util.UtilEnt; -import mineplex.core.common.util.UtilMath; -import mineplex.core.common.util.UtilPlayer; -import mineplex.core.common.util.UtilTime; -import mineplex.game.clans.clans.ClansManager; -import mineplex.game.clans.clans.amplifiers.AmplifierManager; -import mineplex.game.clans.clans.nether.miniboss.MinibossFireball; -import mineplex.game.clans.clans.nether.miniboss.NetherMiniBoss; -import mineplex.game.clans.items.runes.RuneManager.RuneAttribute; - import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; @@ -23,6 +13,16 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.inventory.ItemStack; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.amplifiers.AmplifierManager; +import mineplex.game.clans.clans.nether.miniboss.MinibossFireball; +import mineplex.game.clans.clans.nether.miniboss.NetherMiniBoss; +import mineplex.game.clans.items.runes.RuneManager.RuneAttribute; + /** * Class for running an individual Ghast miniboss */ @@ -32,8 +32,11 @@ public class GhastMiniboss extends NetherMiniBoss private static final long FIREBALL_LAUNCH_RATE = 500; private static final int FIREBALLS_PER_USE = 5; private static final double RUNE_DROP_CHANCE = .02; - private static final int MAX_DIAMOND_DROPS = 5; + private static final int MAX_VALUABLE_DROPS = 5; + private static final Material[] VALUABLE_DROP_TYPES = new Material[] {Material.DIAMOND, Material.GOLD_INGOT, Material.IRON_INGOT, Material.LEATHER}; private static final double MAX_TARGET_RANGE = 25; + private static final Material[] SET_DROP_TYPES = new Material[] {Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, Material.GOLD_HELMET, Material.GOLD_CHESTPLATE, Material.GOLD_LEGGINGS, Material.GOLD_BOOTS, Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS, Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS}; + private static final double SET_DROP_CHANCE = .02; private long _lastFireballUse; private int _fireballsRemaining; @@ -72,7 +75,7 @@ public class GhastMiniboss extends NetherMiniBoss @Override public void customDeath(Location deathLocation) { - deathLocation.getWorld().dropItemNaturally(deathLocation, new ItemStack(Material.DIAMOND, UtilMath.r(MAX_DIAMOND_DROPS) + 1)); + deathLocation.getWorld().dropItemNaturally(deathLocation, new ItemStack(VALUABLE_DROP_TYPES[UtilMath.r(VALUABLE_DROP_TYPES.length)], UtilMath.r(MAX_VALUABLE_DROPS) + 1)); double runeDropChance = RUNE_DROP_CHANCE; if (ClansManager.getInstance().getAmplifierManager().hasActiveAmplifier()) { @@ -83,6 +86,10 @@ public class GhastMiniboss extends NetherMiniBoss RuneAttribute runeType = RuneAttribute.values()[UtilMath.r(RuneAttribute.values().length)]; deathLocation.getWorld().dropItemNaturally(deathLocation, ClansManager.getInstance().getGearManager().getRuneManager().getRune(runeType)); } + if (new Random().nextDouble() <= SET_DROP_CHANCE) + { + deathLocation.getWorld().dropItemNaturally(deathLocation, new ItemStack(SET_DROP_TYPES[UtilMath.r(SET_DROP_TYPES.length)], 1)); + } } @Override diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/WarriorMiniboss.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/WarriorMiniboss.java index 248c9bf64..d978515d6 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/WarriorMiniboss.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/nether/miniboss/bosses/WarriorMiniboss.java @@ -2,15 +2,6 @@ package mineplex.game.clans.clans.nether.miniboss.bosses; import java.util.Random; -import mineplex.core.common.util.UtilAction; -import mineplex.core.common.util.UtilAlg; -import mineplex.core.common.util.UtilMath; -import mineplex.game.clans.clans.ClansManager; -import mineplex.game.clans.clans.amplifiers.AmplifierManager; -import mineplex.game.clans.clans.nether.miniboss.NetherMiniBoss; -import mineplex.game.clans.items.runes.RuneManager.RuneAttribute; -import mineplex.minecraft.game.core.damage.CustomDamageEvent; - import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; @@ -27,13 +18,25 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilMath; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.amplifiers.AmplifierManager; +import mineplex.game.clans.clans.nether.miniboss.NetherMiniBoss; +import mineplex.game.clans.items.runes.RuneManager.RuneAttribute; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + /** * Class for running an individual Warrior miniboss */ public class WarriorMiniboss extends NetherMiniBoss { private static final double RUNE_DROP_CHANCE = .02; - private static final int MAX_DIAMOND_DROPS = 5; + private static final int MAX_VALUABLE_DROPS = 5; + private static final Material[] VALUABLE_DROP_TYPES = new Material[] {Material.DIAMOND, Material.GOLD_INGOT, Material.IRON_INGOT, Material.LEATHER}; + private static final Material[] SET_DROP_TYPES = new Material[] {Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, Material.GOLD_HELMET, Material.GOLD_CHESTPLATE, Material.GOLD_LEGGINGS, Material.GOLD_BOOTS, Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS, Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS}; + private static final double SET_DROP_CHANCE = .02; private static final double LEAP_CHANCE = .9; private static final double LEAP_MIN_DIST = 3; private static final double LEAP_MAX_DIST = 16; @@ -66,7 +69,7 @@ public class WarriorMiniboss extends NetherMiniBoss @Override public void customDeath(Location deathLocation) { - deathLocation.getWorld().dropItemNaturally(deathLocation, new ItemStack(Material.DIAMOND, UtilMath.r(MAX_DIAMOND_DROPS) + 1)); + deathLocation.getWorld().dropItemNaturally(deathLocation, new ItemStack(VALUABLE_DROP_TYPES[UtilMath.r(VALUABLE_DROP_TYPES.length)], UtilMath.r(MAX_VALUABLE_DROPS) + 1)); double runeDropChance = RUNE_DROP_CHANCE; if (ClansManager.getInstance().getAmplifierManager().hasActiveAmplifier()) { @@ -77,6 +80,10 @@ public class WarriorMiniboss extends NetherMiniBoss RuneAttribute runeType = RuneAttribute.values()[UtilMath.r(RuneAttribute.values().length)]; deathLocation.getWorld().dropItemNaturally(deathLocation, ClansManager.getInstance().getGearManager().getRuneManager().getRune(runeType)); } + if (new Random().nextDouble() <= SET_DROP_CHANCE) + { + deathLocation.getWorld().dropItemNaturally(deathLocation, new ItemStack(SET_DROP_TYPES[UtilMath.r(SET_DROP_TYPES.length)], 1)); + } } @Override diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/regions/ClansRegions.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/regions/ClansRegions.java index 55debe953..3ea0964b8 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/regions/ClansRegions.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/regions/ClansRegions.java @@ -24,7 +24,7 @@ public class ClansRegions extends MiniPlugin public final static int SHOP_RADIUS = 6; // Radius of shop claim area (measured in chunks) public final static int FIELDS_RADIUS = 7; // Radius of fields claim area (measured in chunks) public final static int BORDERLANDS_RADIUS = 85; // Radius of borderlands claim area (measured in chunks) - public static final int BORDER_RADIUS = 1250; + public static final int BORDER_RADIUS = 1280; private ClansManager _manager; private World _world; diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/scoreboard/ClansPlayerScoreboard.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/scoreboard/ClansPlayerScoreboard.java index 29950b8db..5b2f870b6 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/scoreboard/ClansPlayerScoreboard.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/scoreboard/ClansPlayerScoreboard.java @@ -13,6 +13,7 @@ import mineplex.core.common.util.C; import mineplex.core.common.util.UtilText; import mineplex.core.thereallyoldscoreboardapiweshouldremove.PlayerScoreboard; import mineplex.core.thereallyoldscoreboardapiweshouldremove.ScoreboardManager; +import mineplex.game.clans.Clans; import mineplex.game.clans.clans.ClanInfo; import mineplex.game.clans.clans.ClansManager; import mineplex.game.clans.clans.ClansUtility.ClanRelation; @@ -112,17 +113,19 @@ public class ClansPlayerScoreboard extends PlayerScoreboard team.setPrefix(relation.getColor(false).toString()); } - - Objective domObjective; - if ((domObjective = scoreboard.getObjective(DisplaySlot.BELOW_NAME)) == null) + if (Clans.HARDCORE) { - domObjective = scoreboard.registerNewObjective("war", "dummy"); - domObjective.setDisplayName("War Points"); - domObjective.setDisplaySlot(DisplaySlot.BELOW_NAME); - } + Objective domObjective; + if ((domObjective = scoreboard.getObjective(DisplaySlot.BELOW_NAME)) == null) + { + domObjective = scoreboard.registerNewObjective("war", "dummy"); + domObjective.setDisplayName("War Points"); + domObjective.setDisplaySlot(DisplaySlot.BELOW_NAME); + } - if (clanInfo != null) - domObjective.getScore(otherPlayer.getName()).setScore(ownScore); + if (clanInfo != null) + domObjective.getScore(otherPlayer.getName()).setScore(ownScore); + } team.addPlayer(otherPlayer); } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/scoreboard/elements/ScoreboardElementPlayer.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/scoreboard/elements/ScoreboardElementPlayer.java index b5e11e8a1..75b8ef44d 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/scoreboard/elements/ScoreboardElementPlayer.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/scoreboard/elements/ScoreboardElementPlayer.java @@ -58,6 +58,11 @@ public class ScoreboardElementPlayer implements ScoreboardElement } } + if (_clansManager.getWorldEvent().getRaidManager().isInRaid(player.getLocation())) + { + regionString = C.cDRed + "Raid World"; + } + output.add(regionString); return output; diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/SiegeManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/SiegeManager.java index ab406664c..223266074 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/SiegeManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/SiegeManager.java @@ -10,8 +10,10 @@ 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.itemstack.ItemStackFactory; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.Clans; import mineplex.game.clans.clans.ClansManager; import mineplex.game.clans.clans.siege.command.GiveWeaponCommand; import mineplex.game.clans.clans.siege.outpost.OutpostManager; @@ -213,10 +215,24 @@ public class SiegeManager extends MiniPlugin @EventHandler public void onBlockPlace(BlockPlaceEvent event) { + if (!Clans.HARDCORE) + { + return; + } if (event.getItemInHand().isSimilar(Cannon.CANNON_ITEM)) { event.setCancelled(true); + int health = ItemStackFactory.Instance.GetLoreVar(event.getPlayer().getItemInHand(), "Health", 0); + if (health != 0) + { + if (trySpawnCannon(event.getPlayer(), event.getBlock().getLocation())) + { + event.getPlayer().setItemInHand(UtilInv.decrement(event.getPlayer().getItemInHand())); + } + return; + } + if (trySpawnCannon(event.getPlayer(), event.getBlock().getLocation())) { event.getPlayer().setItemInHand(UtilInv.decrement(event.getPlayer().getItemInHand())); @@ -236,6 +252,46 @@ public class SiegeManager extends MiniPlugin // } } + public boolean trySpawnCannon(Player player, Location location, int health) + { + if (_clansManager.getNetherManager().isInNether(player)) + { + _clansManager.message(player, "You are not allowed to place this in " + F.clansNether("The Nether") + "."); + + return false; + } + if (_clansManager.getWorldEvent().getRaidManager().isInRaid(player.getLocation())) + { + _clansManager.message(player, "You are not allowed to place this in a raid."); + + return false; + } + + if (!_clansManager.isInClan(player)) + { + UtilPlayer.message(player, F.main("Clans", "You must be in a Clan to place a Cannon.")); + return false; + } + + if (_clansManager.hasTimer(player)) + { + UtilPlayer.message(player, F.main("Clans", "You cannot place a Cannon whilst protected from pvp.")); + return false; + } + + ClanTerritory claim = _clansManager.getClanUtility().getClaim(location); + + if (claim != null && !claim.Owner.equals(_clansManager.getClan(player).getName())) + { + UtilPlayer.message(player, F.main("Clans", "You must place a Cannon in the Wilderness or your own Territory.")); + return false; + } + + spawnCannon(player, location).setHealth(health); + + return true; + } + public boolean trySpawnCannon(Player player, Location location) { if (_clansManager.getNetherManager().isInNether(player)) @@ -244,6 +300,12 @@ public class SiegeManager extends MiniPlugin return false; } + if (_clansManager.getWorldEvent().getRaidManager().isInRaid(player.getLocation())) + { + _clansManager.message(player, "You are not allowed to place this in a raid."); + + return false; + } if (!_clansManager.isInClan(player)) { diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/Outpost.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/Outpost.java index 09ed9dcbc..c20834e30 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/Outpost.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/Outpost.java @@ -8,6 +8,7 @@ import java.util.List; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; +import org.bukkit.block.Block; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -63,11 +64,13 @@ import net.minecraft.server.v1_8_R3.AxisAlignedBB; public class Outpost implements Listener { - protected static final long MAX_LIFETIME = 30 * 60 * 1000; // 30 minutes + protected static final long MAX_LIFETIME = 45 * 60 * 1000; // 30 minutes public static final ItemStack OUTPOST_ITEM = new ItemBuilder(Material.BEACON, 1).setRawTitle(C.Reset + C.cBlue + "Outpost").build(); public static final long PREP_TIME = 2 * 60 * 1000; + private static final int MAX_HEALTH = 100; + private OutpostManager _outpostManager; private final int _uniqueId; @@ -103,10 +106,18 @@ public class Outpost implements Listener private Hologram _lifetimeLeft; + private int _health; + + private long _lastDamage; + + private long _lastRegen; + public Outpost(OutpostManager outpostManager, OutpostToken token) { _outpostManager = outpostManager; + _health = MAX_HEALTH; + _uniqueId = token.UniqueId; _ownerClan = token.OwnerClan; @@ -137,7 +148,36 @@ public class Outpost implements Listener return; if (clickType == ClickType.LEFT || clickType == ClickType.SHIFT_LEFT) - kill(); + { + if (_outpostManager.getClansManager().hasTimer(player)) + { + UtilPlayer.message(player, F.main("Clans", "You cannot destroy an Outpost whilst protected from PvP.")); + return; + } + if (!UtilTime.elapsed(_lastDamage, 5000)) + { + return; + } + if (_health <= 2) + { + UtilPlayer.message(player, F.main("Clans", "You have destroyed " + F.elem(_ownerClan.getName()) + "'s Outpost!")); + + _core.getBlock().setType(Material.AIR); + + _ownerClan.inform("Your Outpost has been destroyed!", null); + UtilTextMiddle.display("Siege", "Your Outpost has been destroyed", 20, 100, 20, _ownerClan.getOnlinePlayersArray()); + + if (getState() == OutpostState.AWAITING) + cleanup(); + else + kill(); + + return; + } + + _lastDamage = System.currentTimeMillis(); + _health -= 2; + } } }); @@ -149,7 +189,7 @@ public class Outpost implements Listener _preHologram2.start(); } - _blocks = _type.createBuildQueue(_origin, _ownerClan.Clans); + _blocks = _type.createBuildQueue(_origin, _ownerClan.Clans, _ownerClan); _state = token.OutpostState; @@ -165,6 +205,8 @@ public class Outpost implements Listener { _outpostManager = outpostManager; + _health = MAX_HEALTH; + _uniqueId = outpostManager.getSiegeManager().randomId(); _ownerClan = clan; @@ -210,7 +252,36 @@ public class Outpost implements Listener return; if (clickType == ClickType.LEFT || clickType == ClickType.SHIFT_LEFT) - kill(); + { + if (_outpostManager.getClansManager().hasTimer(player)) + { + UtilPlayer.message(player, F.main("Clans", "You cannot destroy an Outpost whilst protected from PvP.")); + return; + } + if (!UtilTime.elapsed(_lastDamage, 5000)) + { + return; + } + if (_health <= 2) + { + UtilPlayer.message(player, F.main("Clans", "You have destroyed " + F.elem(_ownerClan.getName()) + "'s Outpost!")); + + _core.getBlock().setType(Material.AIR); + + _ownerClan.inform("Your Outpost has been destroyed!", null); + UtilTextMiddle.display("Siege", "Your Outpost has been destroyed", 20, 100, 20, _ownerClan.getOnlinePlayersArray()); + + if (getState() == OutpostState.AWAITING) + cleanup(); + else + kill(); + + return; + } + + _lastDamage = System.currentTimeMillis(); + _health -= 2; + } } }); } @@ -280,6 +351,20 @@ public class Outpost implements Listener return; } + for (Block block : UtilBlock.getBlocksInRadius(event.getClickedBlock().getLocation(), 5)) + { + if (block.getType() == Material.WATER || block.getType() == Material.STATIONARY_WATER) + { + UtilPlayer.message(event.getPlayer(), F.main("Clans", "You cannot activate an Outpost that close to water!")); + return; + } + if (block.getType() == Material.LAVA || block.getType() == Material.STATIONARY_LAVA) + { + UtilPlayer.message(event.getPlayer(), F.main("Clans", "You cannot activate an Outpost that close to lava!")); + return; + } + } + _origin.getBlock().setType(Material.AIR); beginConstruction(); } @@ -291,26 +376,35 @@ public class Outpost implements Listener { if (event.getBlock().getLocation().equals(_core) && getState() == OutpostState.LIVE) { - - if(_outpostManager.getClansManager().hasTimer(event.getPlayer())) + event.setCancelled(true); + if (_outpostManager.getClansManager().hasTimer(event.getPlayer())) { UtilPlayer.message(event.getPlayer(), F.main("Clans", "You cannot destroy an Outpost whilst protected from PvP.")); - event.setCancelled(true); return; } - UtilPlayer.message(event.getPlayer(), F.main("Clans", "You have destroyed " + F.elem(_ownerClan.getName()) + "'s Outpost!")); + if (!UtilTime.elapsed(_lastDamage, 5000)) + { + return; + } + if (_health <= 2) + { + UtilPlayer.message(event.getPlayer(), F.main("Clans", "You have destroyed " + F.elem(_ownerClan.getName()) + "'s Outpost!")); + + _core.getBlock().setType(Material.AIR); + + _ownerClan.inform("Your Outpost has been destroyed!", null); + UtilTextMiddle.display("Siege", "Your Outpost has been destroyed", 20, 100, 20, _ownerClan.getOnlinePlayersArray()); + + if (getState() == OutpostState.AWAITING) + cleanup(); + else + kill(); + + return; + } - _core.getBlock().setType(Material.AIR); - - _ownerClan.inform("Your Outpost has been destroyed!", null); - UtilTextMiddle.display("Siege", "Your Outpost has been destroyed", 20, 100, 20, _ownerClan.getOnlinePlayersArray()); - - if (getState() == OutpostState.AWAITING) - cleanup(); - else - kill(); - - event.setCancelled(true); + _lastDamage = System.currentTimeMillis(); + _health -= 2; } } @@ -329,20 +423,35 @@ public class Outpost implements Listener if (event.getBlock().getLocation().equals(_core) && getState() == OutpostState.LIVE) { - UtilPlayer.message(event.getPlayer(), F.main("Clans", "You have destroyed " + F.elem(_ownerClan.getName()) + "'s Outpost!")); - - _core.getBlock().setType(Material.AIR); - - _ownerClan.inform("Your Outpost has been destroyed!", null); - UtilTextMiddle.display("Siege", "Your Outpost has been destroyed", 20, 100, 20, _ownerClan.getOnlinePlayersArray()); - - if (getState() == OutpostState.AWAITING) - cleanup(); - else - kill(); - event.setCancelled(true); - return; + if (_outpostManager.getClansManager().hasTimer(event.getPlayer())) + { + UtilPlayer.message(event.getPlayer(), F.main("Clans", "You cannot destroy an Outpost whilst protected from PvP.")); + return; + } + if (!UtilTime.elapsed(_lastDamage, 5000)) + { + return; + } + if (_health <= 2) + { + UtilPlayer.message(event.getPlayer(), F.main("Clans", "You have destroyed " + F.elem(_ownerClan.getName()) + "'s Outpost!")); + + _core.getBlock().setType(Material.AIR); + + _ownerClan.inform("Your Outpost has been destroyed!", null); + UtilTextMiddle.display("Siege", "Your Outpost has been destroyed", 20, 100, 20, _ownerClan.getOnlinePlayersArray()); + + if (getState() == OutpostState.AWAITING) + cleanup(); + else + kill(); + + return; + } + + _lastDamage = System.currentTimeMillis(); + _health -= 2; } if (UtilAlg.inBoundingBox(event.getBlock().getLocation(), _startCorner.clone().subtract(.5, 0, .5), _endCorner)) @@ -410,7 +519,9 @@ public class Outpost implements Listener } if (_lifetimeLeft != null) - _lifetimeLeft.setText("Despawning in " + F.time(UtilTime.MakeStr(MAX_LIFETIME - (System.currentTimeMillis() - _timeSpawned)))); + { + _lifetimeLeft.setText("Health: " + _health, "Despawning in " + F.time(UtilTime.MakeStr(MAX_LIFETIME - (System.currentTimeMillis() - _timeSpawned)))); + } if (_state == OutpostState.CONSTRUCTING) { @@ -467,6 +578,11 @@ public class Outpost implements Listener { kill(); } + if (_health < MAX_HEALTH && UtilTime.elapsed(_lastDamage, 15000) && UtilTime.elapsed(_lastRegen, 1000)) + { + _lastRegen = System.currentTimeMillis(); + _health++; + } } } @@ -498,12 +614,13 @@ public class Outpost implements Listener _lifetimeLeft.start(); _state = OutpostState.CONSTRUCTING; - _blocks = new LinkedHashMap<>(_buildQueue = _type.createBuildQueue(_origin, _ownerClan.Clans)); + _blocks = new LinkedHashMap<>(_buildQueue = _type.createBuildQueue(_origin, _ownerClan.Clans, _ownerClan)); _ownerClan.inform("Siege", "Your Outpost is now being constructed.", null); //Inform nearby Clans for (int chunkX = -3; chunkX < 3; chunkX++) + { for (int chunkZ = -3; chunkZ < 3; chunkZ++) { ClanTerritory territory = _ownerClan.Clans.getClanUtility().getClaim(_origin.getWorld().getChunkAt(_origin.getChunk().getX() + chunkX, _origin.getChunk().getZ() + chunkZ)); @@ -516,6 +633,7 @@ public class Outpost implements Listener UtilTextMiddle.display("Siege", "A Siege has been declared on your Clan!", 20, 100, 20, clan.getOnlinePlayersArray()); } } + } } public void kill() diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/OutpostManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/OutpostManager.java index 559fc6b4b..c962a829d 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/OutpostManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/OutpostManager.java @@ -24,6 +24,7 @@ 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.game.clans.Clans; import mineplex.game.clans.clans.ClanInfo; import mineplex.game.clans.clans.ClansManager; import mineplex.game.clans.clans.event.PlayerClaimTerritoryEvent; @@ -61,6 +62,10 @@ public class OutpostManager extends MiniPlugin @EventHandler(priority = EventPriority.LOWEST) public void onPlaceBlock(BlockPlaceEvent event) { + if (!Clans.HARDCORE) + { + return; + } if (event.getItemInHand().isSimilar(Outpost.OUTPOST_ITEM)) if (!spawnOutpost(event.getPlayer(), event.getBlock().getLocation(), OutpostType.MK_III)) event.setCancelled(true); @@ -75,13 +80,20 @@ public class OutpostManager extends MiniPlugin return false; } + if (_clansManager.getWorldEvent().getRaidManager().isInRaid(player.getLocation())) + { + _clansManager.message(player, "You are not allowed to place this in a raid."); + + return false; + } + if (!_clansManager.isInClan(player)) { UtilPlayer.message(player, F.main("Clans", "You must be in a Clan to place an Outpost.")); return false; } - if(_clansManager.hasTimer(player)) + if (_clansManager.hasTimer(player)) { UtilPlayer.message(player, F.main("Clans", "You can't place an Outpost whilst protected from PvP.")); return false; @@ -123,6 +135,7 @@ public class OutpostManager extends MiniPlugin } for (int x = -2; x < 2; x++) + { for (int z = -2; z < 2; z++) { Chunk chunk = location.getWorld().getChunkAt(location.getChunk().getX() + x, location.getChunk().getZ() + z); @@ -138,10 +151,12 @@ public class OutpostManager extends MiniPlugin } } } + } boolean gut = false; for (int x = -6; x < 6; x++) + { for (int z = -6; z < 6; z++) { Chunk chunk = location.getWorld().getChunkAt(location.getChunk().getX() + x, location.getChunk().getZ() + z); @@ -159,6 +174,7 @@ public class OutpostManager extends MiniPlugin } } } + } /* das ist schlecht */ if (!gut) @@ -168,7 +184,9 @@ public class OutpostManager extends MiniPlugin } for (int x = -type._size; x < type._size; x++) + { for (int y = -1; y < type._ySize; y++) + { for (int z = -type._size; z < type._size; z++) { Location loc = location.clone().add(x, y, z); @@ -179,6 +197,8 @@ public class OutpostManager extends MiniPlugin return false; } } + } + } _outposts.put(clan.getName(), new Outpost(this, clan, location, type)); _idToOutpost.put(Integer.valueOf(_outposts.get(clan.getName()).getUniqueId()), _outposts.get(clan.getName())); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/OutpostType.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/OutpostType.java index 134e6b000..c14bc04d5 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/OutpostType.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/outpost/OutpostType.java @@ -1,27 +1,30 @@ package mineplex.game.clans.clans.siege.outpost; import java.io.File; -import java.io.FileInputStream; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +import java.util.Objects; -import org.bukkit.DyeColor; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.block.banner.Pattern; import mineplex.core.common.block.schematic.Schematic; import mineplex.core.common.block.schematic.UtilSchematic; import mineplex.core.common.util.UtilWorld; +import mineplex.game.clans.clans.ClanInfo; import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.banners.BannerManager; +import mineplex.game.clans.clans.banners.BannerPattern; +import mineplex.game.clans.clans.banners.ClanBanner; import mineplex.game.clans.clans.siege.outpost.build.OutpostBlock; import mineplex.game.clans.clans.siege.outpost.build.OutpostBlockBanner; -import net.minecraft.server.v1_8_R3.NBTTagCompound; public enum OutpostType { MK_I(1, 3, 6) { - public LinkedHashMap createBuildQueue(Location location, ClansManager clans) + public LinkedHashMap createBuildQueue(Location location, ClansManager clans, ClanInfo owner) { LinkedHashMap build = new LinkedHashMap<>(); @@ -232,7 +235,7 @@ public enum OutpostType } }, MK_II(2, 5, 25) { - public LinkedHashMap createBuildQueue(Location location, ClansManager clans) + public LinkedHashMap createBuildQueue(Location location, ClansManager clans, ClanInfo owner) { try { @@ -292,7 +295,7 @@ public enum OutpostType } }, MK_III(3, 5, 25) { - public LinkedHashMap createBuildQueue(Location location, ClansManager clans) + public LinkedHashMap createBuildQueue(Location location, ClansManager clans, ClanInfo owner) { try { @@ -300,6 +303,8 @@ public enum OutpostType File file = new File("schematic" + File.separator + "outpost_mk_III.schematic"); Schematic schematic = UtilSchematic.loadSchematic(file); + BannerManager bm = clans.getBannerManager(); + ClanBanner cb = bm.LoadedBanners.get(owner.getName()); for (int y = 0; y < schematic.getHeight(); y++) { @@ -319,10 +324,16 @@ public enum OutpostType if (Material.getMaterial(schematic.getBlock(x, y, z)).name().contains("BANNER")) { - build.put(UtilWorld.locToStr(loc), new OutpostBlockBanner(build, loc, schematic.getBlock(x, y, z), schematic.getData(x, y, z), DyeColor.RED)); + if (cb == null) + { + continue; + } + build.put(UtilWorld.locToStr(loc), new OutpostBlockBanner(build, loc, schematic.getBlock(x, y, z), schematic.getData(x, y, z), cb.getBaseColor(), cb.getPatterns().stream().map(BannerPattern::getBukkitPattern).filter(Objects::nonNull).toArray(size -> new Pattern[size]))); } else + { build.put(UtilWorld.locToStr(loc), new OutpostBlock(build, loc, schematic.getBlock(x, y, z), schematic.getData(x, y, z))); + } } } } @@ -374,7 +385,7 @@ public enum OutpostType return _id; } - public abstract LinkedHashMap createBuildQueue(Location location, ClansManager clans); + public abstract LinkedHashMap createBuildQueue(Location location, ClansManager clans, ClanInfo owner); public abstract Location getCoreLocation(Location location); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/repository/tokens/SiegeWeaponToken.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/repository/tokens/SiegeWeaponToken.java index 638aa800c..274039ed8 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/repository/tokens/SiegeWeaponToken.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/repository/tokens/SiegeWeaponToken.java @@ -1,8 +1,5 @@ package mineplex.game.clans.clans.siege.repository.tokens; -import java.util.Map; -import java.util.UUID; - import org.bukkit.Location; import mineplex.game.clans.clans.ClanInfo; @@ -15,6 +12,5 @@ public class SiegeWeaponToken public Location Location; public int Health; public int Yaw; - public long LastFired; - -} + public long LastFired; +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/projectile/Crater.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/projectile/Crater.java index 0b1630995..c8bbf60ca 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/projectile/Crater.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/projectile/Crater.java @@ -1,7 +1,7 @@ package mineplex.game.clans.clans.siege.weapon.projectile; -import java.util.HashMap; import java.util.List; +import java.util.Map; import org.bukkit.Location; import org.bukkit.Material; @@ -110,7 +110,7 @@ public class Crater } }, 1L); - HashMap hitMap = UtilEnt.getInRadius(_origin, 3.5); + Map hitMap = UtilEnt.getInRadius(_origin, 3.5); for (LivingEntity hit : hitMap.keySet()) { ClansManager.getInstance().getDamageManager().NewDamageEvent(hit, _cause, null, DamageCause.ENTITY_EXPLOSION, 7 / hitMap.get(hit), true, true, false, _cause.getName(), "Siege Cannon"); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/projectile/WeaponProjectile.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/projectile/WeaponProjectile.java index 75cd73e49..2cfa6e336 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/projectile/WeaponProjectile.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/projectile/WeaponProjectile.java @@ -3,20 +3,13 @@ package mineplex.game.clans.clans.siege.weapon.projectile; import org.bukkit.Location; import org.bukkit.Sound; import org.bukkit.entity.Entity; -import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Player; import org.bukkit.entity.TNTPrimed; import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.util.Vector; -import mineplex.core.common.util.UtilAlg; import mineplex.core.common.util.UtilBlock; -import mineplex.core.common.util.UtilItem; import mineplex.core.common.util.UtilServer; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/war/WarManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/war/WarManager.java index 592c61a42..05011fe57 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/war/WarManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/war/WarManager.java @@ -18,6 +18,7 @@ import mineplex.core.thereallyoldscoreboardapiweshouldremove.ScoreboardManager; import mineplex.core.thereallyoldscoreboardapiweshouldremove.elements.ScoreboardElement; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.Clans; import mineplex.game.clans.clans.ClanInfo; import mineplex.game.clans.clans.ClanTips.TipType; import mineplex.game.clans.clans.ClansManager; @@ -107,6 +108,10 @@ public class WarManager extends MiniPlugin implements ScoreboardElement @EventHandler public void handleDeath(final ClansPlayerDeathEvent event) { + if (!Clans.HARDCORE) + { + return; + } ClanInfo deathClan = event.getPlayer().getClan(); if (deathClan == null) diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/war/command/WarPointsCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/war/command/WarPointsCommand.java index efe673ca6..e44c0f21c 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/war/command/WarPointsCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/war/command/WarPointsCommand.java @@ -7,6 +7,7 @@ import mineplex.core.common.Rank; import mineplex.core.common.util.F; import mineplex.core.common.util.UtilPlayer; import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.Clans; import mineplex.game.clans.clans.ClanInfo; import mineplex.game.clans.clans.ClansManager; import mineplex.game.clans.core.war.ClanWarData; @@ -22,6 +23,11 @@ public class WarPointsCommand extends CommandBase @Override public void Execute(Player caller, String[] args) { + if (!Clans.HARDCORE) + { + UtilPlayer.message(caller, F.main("Clans", "This is not a hardcore server!")); + return; + } ClansManager clansManager = Plugin.getClansManager(); ClanInfo clan = clansManager.getClan(caller); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/warpoints/WarPointEvasion.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/warpoints/WarPointEvasion.java index 04be2a159..409658256 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/warpoints/WarPointEvasion.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/warpoints/WarPointEvasion.java @@ -72,7 +72,7 @@ public class WarPointEvasion extends MiniPlugin { Chunk chunk = event.getClaimedChunk(); - if(_chunkCooldown.containsKey(chunk)) + if (_chunkCooldown.containsKey(chunk)) { event.setCancelled(true); event.getClaimer().sendMessage(F.main("Clans", "You cannot claim this chunk for another " + UtilTime.convertString(COOLDOWN_TIME - (System.currentTimeMillis() - _chunkCooldown.get(chunk)), 1, UtilTime.TimeUnit.MINUTES))); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventManager.java index 3dd3cd94e..032d86c2f 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventManager.java @@ -5,11 +5,19 @@ import java.util.LinkedList; import java.util.List; import java.util.Random; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.plugin.java.JavaPlugin; + +import com.google.common.collect.Lists; + import mineplex.core.MiniPlugin; import mineplex.core.blockrestore.BlockRestore; +import mineplex.core.blood.Blood; import mineplex.core.common.util.C; -import mineplex.core.common.util.UtilMath; import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilWorld; import mineplex.core.disguise.DisguiseManager; import mineplex.core.thereallyoldscoreboardapiweshouldremove.ScoreboardManager; import mineplex.core.thereallyoldscoreboardapiweshouldremove.elements.ScoreboardElement; @@ -18,33 +26,23 @@ import mineplex.core.updater.event.UpdateEvent; import mineplex.game.clans.clans.ClansManager; import mineplex.game.clans.clans.loot.LootManager; import mineplex.game.clans.clans.regions.ClansRegions; +import mineplex.game.clans.clans.worldevent.api.EventState; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.game.clans.clans.worldevent.boss.BossArenaLocationFinder; import mineplex.game.clans.clans.worldevent.command.WorldEventCommand; +import mineplex.game.clans.clans.worldevent.raid.RaidManager; import mineplex.minecraft.game.classcombat.Skill.SkillFactory; import mineplex.minecraft.game.classcombat.Skill.event.SkillTriggerEvent; -import mineplex.minecraft.game.core.boss.EventCreatureDeathEvent; -import mineplex.minecraft.game.core.boss.EventState; -import mineplex.minecraft.game.core.boss.WorldEvent; -import mineplex.minecraft.game.core.boss.broodmother.SpiderCreature; -import mineplex.minecraft.game.core.boss.ironwizard.GolemCreature; -import mineplex.minecraft.game.core.boss.skeletonking.SkeletonCreature; import mineplex.minecraft.game.core.damage.DamageManager; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.HandlerList; -import org.bukkit.plugin.java.JavaPlugin; - -import com.google.common.collect.Lists; - public class WorldEventManager extends MiniPlugin implements ScoreboardElement { - private static final double ARENA_RADIUS = 40; private final List _runningEvents; private Random _random; private ClansManager _clansManager; private EventTerrainFinder _terrainFinder; + private BossArenaLocationFinder _bossFinder; private DamageManager _damageManager; private LootManager _lootManager; private BlockRestore _blockRestore; @@ -53,20 +51,27 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement private long _nextEventStart; + private RaidManager _raidManager; + public WorldEventManager(JavaPlugin plugin, ClansManager clansManager, DamageManager damageManager, LootManager lootManager, BlockRestore blockRestore, ClansRegions clansRegions, SkillFactory skillFactory) { super("World Event", plugin); _random = new Random(); _terrainFinder = new EventTerrainFinder(clansManager); + _bossFinder = new BossArenaLocationFinder(UtilWorld.getWorld("world")); _clansManager = clansManager; _damageManager = damageManager; _lootManager = lootManager; _blockRestore = blockRestore; - _runningEvents = new LinkedList(); + _runningEvents = new LinkedList<>(); _skillFactory = skillFactory; + new Blood(plugin); + + _raidManager = new RaidManager(plugin); + updateNextEventTime(); } @@ -75,24 +80,22 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement addCommand(new WorldEventCommand(this)); } - // PS: This never gets called @Override public void disable() { for (WorldEvent event : _runningEvents) { - event.cancel(); + event.stop(true); } + _runningEvents.clear(); + _raidManager.onDisable(); } public boolean isInEvent(Location location) { for (WorldEvent event : _runningEvents) { - if (UtilMath.offset2d(location, event.getCenterLocation()) <= ARENA_RADIUS) - { - return true; - } + event.isInBounds(location, true); } return false; @@ -103,28 +106,9 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement { if (event.GetSkillName().equalsIgnoreCase("Ice Prison")) { - for (WorldEvent e : _runningEvents) + if (isInEvent(event.GetPlayer().getLocation())) { - if (isInEvent(event.GetPlayer().getLocation())) - { - event.SetCancelled(true); - } - } - } - } - - @EventHandler - public void onBossDeath(EventCreatureDeathEvent event) - { - if (event.getCreature() instanceof GolemCreature || event.getCreature() instanceof SkeletonCreature || event.getCreature() instanceof SpiderCreature) - { - Location drop = event.getCreature().getLastKnownLocation(); - if (drop != null) - { - runSyncLater(() -> - { - ClansManager.getInstance().getLootManager().dropRare(drop); - }, 20 * 2); + event.SetCancelled(true); } } } @@ -137,26 +121,7 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement return; } - boolean removed = false; - - Iterator iterator = _runningEvents.iterator(); - while (iterator.hasNext()) - { - WorldEvent worldEvent = iterator.next(); - if (worldEvent.getState() == EventState.COMPLETE || worldEvent.getState() == EventState.CANCELLED) - { - HandlerList.unregisterAll(worldEvent); - iterator.remove(); - - // If the event was cancelled, cleanup was already done. - if (worldEvent.getState() == EventState.COMPLETE) - { - worldEvent.cleanup(); - } - - removed = true; - } - } + boolean removed = _runningEvents.removeIf(e -> e.getState() == EventState.STOPPED); if (removed && _runningEvents.size() == 0) { @@ -191,19 +156,25 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement private WorldEventType tryStartEvent() { WorldEventType[] types = WorldEventType.values(); - WorldEventType type = types[_random.nextInt(types.length)]; - Location location = _terrainFinder.findAreaInBorderlands(false); - if (location != null) + if (types.length == 0) { - initializeEvent(type.createInstance(this, location, _skillFactory)); - return type; + return null; } else { - // Try again in 5 minutes - _nextEventStart = System.currentTimeMillis() + (5 * 60 * 1000); + WorldEventType type = types[_random.nextInt(types.length)]; + //Location location = _terrainFinder.findAreaInBorderlands(false); + //if (location != null) + { + initializeEvent(type.createInstance(this)); + return type; + } + //else + //{ + // Try again in 5 minutes + //_nextEventStart = System.currentTimeMillis() + (5 * 60 * 1000); + //} } - return null; } private void initializeEvent(WorldEvent event) @@ -213,30 +184,33 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement throw new RuntimeException("WorldEvent may not be null"); } - event.loadMap(); event.start(); - getPlugin().getServer().getPluginManager().registerEvents(event, getPlugin()); _runningEvents.add(event); } - - public WorldEvent startEventFromName(Location location, String name) + + public WorldEvent startEventFromName(String name) { WorldEventType eventType = WorldEventType.valueOf(name); if (eventType != null) { - WorldEvent event = eventType.createInstance(this, location, _skillFactory); + WorldEvent event = eventType.createInstance(this); + if (event == null) + { + return null; + } initializeEvent(event); return event; } return null; } + public WorldEvent startEventFromType(WorldEventType eventType) { if (eventType != null) { - Location location = _terrainFinder.findAreaInBorderlands(true); - WorldEvent event = eventType.createInstance(this, location, _skillFactory); + //Location location = _terrainFinder.findAreaInBorderlands(true); + WorldEvent event = eventType.createInstance(this); if (event != null) { initializeEvent(event); @@ -253,8 +227,7 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement while (iterator.hasNext()) { WorldEvent event = iterator.next(); - if (event.getState() != EventState.COMPLETE) event.cancel(); - HandlerList.unregisterAll(event); + event.stop(true); iterator.remove(); } @@ -281,6 +254,16 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement return _terrainFinder; } + public BossArenaLocationFinder getBossArenaLocationFinder() + { + return _bossFinder; + } + + public RaidManager getRaidManager() + { + return _raidManager; + } + private void updateNextEventTime() { // 45 Minutes + (0 - 15 Minutes) @@ -341,4 +324,4 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement { return getClans().getDisguiseManager(); } -} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventType.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventType.java index 0110ae6c9..2580c7a9e 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventType.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/WorldEventType.java @@ -1,73 +1,45 @@ package mineplex.game.clans.clans.worldevent; -import java.lang.reflect.Constructor; - -import org.bukkit.Location; - -import mineplex.minecraft.game.classcombat.Skill.SkillFactory; -import mineplex.minecraft.game.core.boss.WorldEvent; -import mineplex.minecraft.game.core.boss.ironwizard.GolemBoss; -import mineplex.minecraft.game.core.boss.skeletonking.SkeletonBoss; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemBoss; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonBoss; public enum WorldEventType { //SLIME_KING("Slime King", SlimeBoss.class, 30), //KING_OF_THE_HILL("King of The Hill", KingHill.class, 30), //UNDEAD_CAMP("Undead Camp", UndeadCamp.class, 30), - IRON_WIZARD("Iron Wizard",GolemBoss.class, 30), + //IRON_WIZARD("Iron Wizard", GolemBoss.class, 30), //BROOD_MOTHER("Brood Mother", SpiderBoss.class, 30), - SKELETON_KING("Skeleton King", SkeletonBoss.class, 30); + //SKELETON_KING("Skeleton King", SkeletonBoss.class, 30) + IRON_WIZARD("Iron Wizard", GolemBoss.class, (man) -> + { + return new GolemBoss(man); + }), + SKELETON_KING("Skeleton King", SkeletonBoss.class, (man) -> + { + return new SkeletonBoss(man); + }) + ; private String _name; private Class _clazz; - private int _areaNeeded; + private EventCreator _creator; - WorldEventType(String name, Class clazz, int areaNeeded) + WorldEventType(String name, Class clazz, EventCreator creator) { _name = name; _clazz = clazz; - _areaNeeded = areaNeeded; + _creator = creator; } - public int getAreaNeeded() - { - return _areaNeeded; - } - - public WorldEvent createInstance(WorldEventManager eventManager, Location centerLocation, SkillFactory skillFactory) + public WorldEvent createInstance(WorldEventManager eventManager) { WorldEvent worldEvent = null; - try + if (_creator != null) { - for (Constructor con : _clazz.getConstructors()) - { - Class[] classes = con.getParameterTypes(); - - if (classes[0] == WorldEventManager.class) - { - if (classes.length == 3) - { - worldEvent = (WorldEvent) con.newInstance(eventManager, centerLocation, skillFactory); - } - else - { - worldEvent = (WorldEvent) con.newInstance(eventManager, centerLocation); - } - } - else if (classes.length == 4) - { - worldEvent = (WorldEvent) con.newInstance(eventManager.getDamage(), eventManager.getBlockRestore(), eventManager.getClans().getCondition(), centerLocation); - } - else - { - worldEvent = (WorldEvent) con.newInstance(eventManager.getDisguiseManager(), eventManager.getDamage(), eventManager.getBlockRestore(), eventManager.getClans().getCondition(), eventManager.getClans().getProjectile(), centerLocation); - } - } - } - catch (Exception e) - { - e.printStackTrace(); + worldEvent = _creator.createEvent(eventManager); } return worldEvent; @@ -75,6 +47,11 @@ public enum WorldEventType public String getName() { - return this._name; + return _name; } -} + + private static interface EventCreator + { + WorldEvent createEvent(WorldEventManager manager); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/BossAbility.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/BossAbility.java new file mode 100644 index 000000000..8ed1186c1 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/BossAbility.java @@ -0,0 +1,109 @@ +package mineplex.game.clans.clans.worldevent.api; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; + +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; + +public abstract class BossAbility, Y extends LivingEntity> implements Listener +{ + private T _creature; + private Map _damaged = new HashMap<>(); + + public BossAbility(T creature) + { + _creature = creature; + } + + public abstract boolean canMove(); + + public abstract boolean inProgress(); + + public abstract boolean hasFinished(); + + public abstract void setFinished(); + + public abstract void tick(); + + public boolean canDamage(Entity player) + { + if (_damaged.containsKey(player.getUniqueId())) + { + + if (!UtilTime.elapsed(_damaged.get(player.getUniqueId()), 400)) + { + return false; + } + } + + _damaged.put(player.getUniqueId(), System.currentTimeMillis()); + return true; + } + + public int getCooldown() + { + return 3; + } + + public Y getEntity() + { + return getBoss().getEntity(); + } + + public T getBoss() + { + return _creature; + } + + public Location getLocation() + { + return getEntity().getLocation(); + } + + public Player getTarget() + { + return getTarget(30); + } + + public Player getTarget(double minDistance, double maxDistance) + { + Player target = null; + double dist = 0; + + for (Player player : UtilPlayer.getNearby(getLocation(), maxDistance, true)) + { + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + double d = player.getLocation().distance(getLocation()); + + if (d < minDistance) + { + continue; + } + + if (target == null || dist > d) + { + target = player; + dist = d; + } + } + + return target; + } + + public Player getTarget(double maxDistance) + { + return getTarget(0, maxDistance); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/BossPassive.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/BossPassive.java new file mode 100644 index 000000000..c2387ea0d --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/BossPassive.java @@ -0,0 +1,50 @@ +package mineplex.game.clans.clans.worldevent.api; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.Listener; + +import mineplex.core.common.util.UtilServer; + +public abstract class BossPassive, Y extends LivingEntity> implements Listener +{ + private T _creature; + private final int _cooldown; + + public BossPassive(T creature) + { + this(creature, 30); + } + + public BossPassive(T creature, int cooldown) + { + _creature = creature; + _cooldown = cooldown; + Bukkit.getPluginManager().registerEvents(this, UtilServer.getPlugin()); + } + + public abstract boolean isProgressing(); + + public abstract void tick(); + + public int getCooldown() + { + return _cooldown; + } + + public Y getEntity() + { + return getBoss().getEntity(); + } + + public T getBoss() + { + return _creature; + } + + public Location getLocation() + { + return getEntity().getLocation(); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventArena.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventArena.java new file mode 100644 index 000000000..3169e9532 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventArena.java @@ -0,0 +1,44 @@ +package mineplex.game.clans.clans.worldevent.api; + +import org.bukkit.Location; + +import mineplex.core.common.util.UtilMath; + +public class EventArena +{ + private final Location _centerLocation; + private final double _radius; + private final double _radiusSquared; + + public EventArena(Location center, double radius) + { + _centerLocation = center; + _radius = radius; + _radiusSquared = Math.pow(radius, 2); + } + + public Location getCenterLocation() + { + return _centerLocation; + } + + public double getRadius() + { + return _radius; + } + + public double getRadiusSquared() + { + return _radiusSquared; + } + + public boolean isInArena(Location checkLocation, boolean flat) + { + if (flat) + { + return UtilMath.offset2dSquared(checkLocation, _centerLocation) <= _radiusSquared; + } + + return UtilMath.offsetSquared(checkLocation, _centerLocation) <= _radiusSquared; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventCreature.java new file mode 100644 index 000000000..43326c031 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventCreature.java @@ -0,0 +1,412 @@ +package mineplex.game.clans.clans.worldevent.api; + +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityCombustEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.world.ChunkUnloadEvent; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilTime; +import mineplex.core.disguise.disguises.DisguiseBase; +import mineplex.core.disguise.disguises.DisguiseInsentient; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.condition.Condition.ConditionType; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public abstract class EventCreature implements Listener +{ + protected static final boolean DEBUG_MODE = true; + private static final long TELEPORT_HOME_WARMUP = 5000; + private static final long HEALTH_REGEN_COOLDOWN = 1500; + private static final long SAFE_TO_HEALTH_REGEN_COOLDOWN = 15000; + private static final double HEALTH_PER_REGEN = 1.5; + + private WorldEvent _event; + + // Spawn Data + private T _entity; + private Class _entityClass; + private Location _spawnLocation, _lastLocation; + + // Creature Data + private String _name; + private String _displayName; + private boolean _useName; + private double _health; + private double _maxHealth; + private boolean _showHealthName; + private long _teleportHome; + private double _walkRange; + private boolean _healthRegen; + + // Fight Data + private long _lastDamaged; + private UUID _lastDamager; + private long _lastRegen; + + public EventCreature(WorldEvent event, Location spawnLocation, String name, boolean useName, double health, double walkRange, boolean healthRegen, Class entityClass) + { + _event = event; + + _entityClass = entityClass; + _spawnLocation = spawnLocation; + + _name = name; + _displayName = name; + _useName = useName; + _health = health; + _maxHealth = health; + _showHealthName = true; + _teleportHome = -1L; + _walkRange = walkRange; + _healthRegen = healthRegen; + } + + public double getDifficulty() + { + return getEvent().getDifficulty(); + } + + protected void spawnEntity() + { + Location spawnLocation = _entity == null ? _spawnLocation : _entity.getLocation(); + T entity = _spawnLocation.getWorld().spawn(spawnLocation, getEntityClass()); + + setEntity(entity); + updateEntityHealth(); + entity.setRemoveWhenFarAway(false); + spawnCustom(); + updateName(); + } + + protected abstract void spawnCustom(); + + protected void updateEntityHealth() + { + _entity.setMaxHealth(500d); + _entity.setHealth(500d); + } + + protected void updateName() + { + String name = _displayName; + + if (_showHealthName) + { + String healthString = (int) _health + "/" + (int) _maxHealth; + double per =_health / _maxHealth; + if (per > 0.5) healthString = C.cGreen + healthString; + if (per > 0.2) healthString = C.cYellow + healthString; + else healthString = C.cRed + healthString; + + name += " " + C.cWhite + "(" + healthString + C.cWhite + ")"; + } + + DisguiseBase disguise = getEvent().getDisguiseManager().getActiveDisguise(getEntity()); + + if (disguise != null && disguise instanceof DisguiseInsentient) + { + ((DisguiseInsentient) disguise).setName(name); + ((DisguiseInsentient) disguise).setCustomNameVisible(_useName); + } + + _entity.setCustomName(name); + _entity.setCustomNameVisible(_useName); + } + + public void remove() + { + remove(true); + } + + public void remove(boolean removeFromEvent) + { + if (_entity != null) + { + if (getHealth() > 0) + { + _entity.remove(); + } + else + { + _entity.setHealth(0); + _entity.setCustomName(""); + _entity.setCustomNameVisible(false); + } + } + + if (removeFromEvent) + { + _event.removeCreature(this); + } + } + + protected final void die() + { + dieCustom(); + remove(); + } + + public abstract void dieCustom(); + + public WorldEvent getEvent() + { + return _event; + } + + public void setEvent(WorldEvent event) + { + _event = event; + } + + public T getEntity() + { + return _entity; + } + + public void setEntity(T entity) + { + if (_entity != null) _entity.remove(); + + _entity = entity; + } + + public Class getEntityClass() + { + return _entityClass; + } + + public void setEntityClass(Class clazz) + { + _entityClass = clazz; + } + + public double getHealthPercent() + { + return getHealth() / getMaxHealth(); + } + + public Location getSpawnLocation() + { + return _spawnLocation; + } + + public Location getLastKnownLocation() + { + return _lastLocation; + } + + public void setSpawnLocation(Location spawnLocation) + { + _spawnLocation = spawnLocation; + } + + public String getDisplayName() + { + return _displayName; + } + + public String getName() + { + return _name; + } + + public void setName(String name) + { + _displayName = name == null ? _name : name; + updateName(); + } + + public boolean isUseName() + { + return _useName; + } + + public void setUseName(boolean useName) + { + _useName = useName; + updateName(); + } + + public void applyDamage(double damage) + { + setHealth(getHealth() - damage); + } + + public void applyRegen(double regen) + { + setHealth(getHealth() + regen); + } + + public double getHealth() + { + return _health; + } + + public void setHealth(double health) + { + _health = Math.min(health, getMaxHealth()); + + if (_health <= 0) + { + die(); + } + else + { + updateName(); + } + } + + public double getMaxHealth() + { + return _maxHealth; + } + + public void setMaxHealth(double maxHealth) + { + _maxHealth = maxHealth; + } + + public void setShowHealthName(boolean showHealthName) + { + _showHealthName = showHealthName; + updateName(); + } + + /** + * Event listeners + */ + + @EventHandler + public void onChunkUnload(ChunkUnloadEvent event) + { + if (_entity != null && _entity.getLocation().getChunk().equals(event.getChunk())) + { + event.setCancelled(true); + } + } + + @EventHandler + public void update(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + { + return; + } + + if (_entity == null || _entity.isDead() || !_entity.isValid()) + { + if (DEBUG_MODE) + { + System.out.println("Respawning " + getName() + " because it is null or dead"); + } + spawnEntity(); + } + + if (_healthRegen && getHealth() < getMaxHealth() && UtilTime.elapsed(_lastDamaged, SAFE_TO_HEALTH_REGEN_COOLDOWN) && UtilTime.elapsed(_lastRegen, HEALTH_REGEN_COOLDOWN)) + { + _lastRegen = System.currentTimeMillis(); + applyRegen(HEALTH_PER_REGEN); + } + + if (_walkRange != -1 && UtilMath.offset2d(_entity.getLocation(), _spawnLocation) > _walkRange) + { + if (_teleportHome != -1 && System.currentTimeMillis() >= _teleportHome) + { + _entity.teleport(_spawnLocation); + _teleportHome = -1; + } + else + { + _entity.setVelocity(UtilAlg.getTrajectory(_entity.getLocation(), _spawnLocation).normalize().multiply(2)); + if (_teleportHome == -1) + { + _teleportHome = System.currentTimeMillis() + TELEPORT_HOME_WARMUP; + } + } + } + else + { + if (_teleportHome != -1) + { + _teleportHome = -1; + } + } + + _lastLocation = _entity.getLocation(); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onDamage(CustomDamageEvent event) + { + if (_entity == null) + { + return; + } + + if (!event.GetDamageeEntity().equals(_entity)) + { + return; + } + + updateEntityHealth(); + + applyDamage(event.GetDamage()); + updateName(); + + _lastDamaged = System.currentTimeMillis(); + + _event.updateLastActive(); + } + + @EventHandler + public void damageType(CustomDamageEvent event) + { + if (_entity == null) + { + return; + } + + if (!event.GetDamageeEntity().equals(_entity)) + { + return; + } + + DamageCause cause = event.GetCause(); + + if (cause == DamageCause.FALL && !getEvent().getCondition().HasCondition(_entity, ConditionType.FALLING, null)) + { + event.SetCancelled("Cancel"); + } + + if (cause == DamageCause.DROWNING || cause == DamageCause.SUFFOCATION) + { + event.SetCancelled("Cancel"); + } + } + + @EventHandler + public void cancelCombust(EntityCombustEvent event) + { + if (_entity == null) + { + return; + } + + if (!event.getEntity().equals(_entity)) + { + return; + } + + event.setCancelled(true); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventCreatureDeathEvent.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventCreatureDeathEvent.java new file mode 100644 index 000000000..8141b4745 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventCreatureDeathEvent.java @@ -0,0 +1,31 @@ +package mineplex.game.clans.clans.worldevent.api; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class EventCreatureDeathEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + + private final EventCreature _creature; + + public EventCreatureDeathEvent(EventCreature creature) + { + _creature = creature; + } + + public EventCreature getCreature() + { + return _creature; + } + + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventState.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventState.java new file mode 100644 index 000000000..bdee54454 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/EventState.java @@ -0,0 +1,9 @@ +package mineplex.game.clans.clans.worldevent.api; + +public enum EventState +{ + LOADING, + LIVE, + STOPPED, + REMOVED +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/WorldEvent.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/WorldEvent.java new file mode 100644 index 000000000..1790cc269 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/api/WorldEvent.java @@ -0,0 +1,337 @@ + package mineplex.game.clans.clans.worldevent.api; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; + +import mineplex.core.blockrestore.BlockRestore; +import mineplex.core.blockrestore.BlockRestoreMap; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTextMiddle; +import mineplex.core.common.util.UtilWorld; +import mineplex.core.disguise.DisguiseManager; +import mineplex.core.projectile.ProjectileManager; +import mineplex.core.thereallyoldscoreboardapiweshouldremove.ScoreboardManager; +import mineplex.core.thereallyoldscoreboardapiweshouldremove.elements.ScoreboardElement; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.condition.ConditionManager; +import mineplex.minecraft.game.core.damage.DamageManager; + +public abstract class WorldEvent implements Listener, ScoreboardElement +{ + // 20 Minutes + private static final int ACTIVE_TIMEOUT = 1200000; + private static final int LOADING_TIMEOUT = 300000; + + private DamageManager _damageManager; + private ConditionManager _conditionManager; + private DisguiseManager _disguiseManager; + private ProjectileManager _projectileManager; + + private String _name; + private EventState _state; + private EventArena _arena; + private Random _random; + private long _timeStarted; + private long _lastActive; + private boolean _announceStart; + + // Creatures + private List> _creatures; + // Block Restore + private BlockRestoreMap _blockRestoreMap; + private double _difficulty = 1; + + public WorldEvent(String name, Location centerLocation, double radius, boolean announceStart, DisguiseManager disguiseManager, ProjectileManager projectileManager, DamageManager damageManager, BlockRestore blockRestore, ConditionManager conditionManager) + { + _disguiseManager = disguiseManager; + _projectileManager = projectileManager; + _damageManager = damageManager; + _conditionManager = conditionManager; + + _name = name; + _state = EventState.LOADING; + _arena = new EventArena(centerLocation, radius); + _random = new Random(); + _announceStart = announceStart; + + _creatures = new ArrayList<>(); + _blockRestoreMap = blockRestore.createMap(); + } + + public String getName() + { + return _name; + } + + public void setName(String name) + { + _name = name; + } + + public EventArena getEventArena() + { + return _arena; + } + + public EventState getState() + { + return _state; + } + + protected void setState(EventState state) + { + _state = state; + } + + public double getDifficulty() + { + return _difficulty; + } + + public void setDifficulty(double difficulty) + { + _difficulty = difficulty; + } + + public Location getCenterLocation() + { + return _arena.getCenterLocation(); + } + + public List> getCreatures() + { + return _creatures; + } + + public void registerCreature(EventCreature creature) + { + UtilServer.RegisterEvents(creature); + _creatures.add(creature); + } + + public void removeCreature(EventCreature creature) + { + Bukkit.getPluginManager().callEvent(new EventCreatureDeathEvent(creature)); + HandlerList.unregisterAll(creature); + _creatures.remove(creature); + } + + public void clearCreatures() + { + for (EventCreature creature : _creatures) + { + creature.remove(false); + HandlerList.unregisterAll(creature); + } + + _creatures.clear(); + } + + public long getTimeRunning() + { + return System.currentTimeMillis() - _timeStarted; + } + + public long getLastActive() + { + return _lastActive; + } + + public void updateLastActive() + { + _lastActive = System.currentTimeMillis(); + } + + public boolean isInBounds(Location location, boolean flat) + { + return _arena.isInArena(location, flat); + } + + protected Random getRandom() + { + return _random; + } + + public DisguiseManager getDisguiseManager() + { + return _disguiseManager; + } + + public ProjectileManager getProjectileManager() + { + return _projectileManager; + } + + public DamageManager getDamageManager() + { + return _damageManager; + } + + public ConditionManager getCondition() + { + return _conditionManager; + } + + protected BlockRestoreMap getBlockRestoreMap() + { + return _blockRestoreMap; + } + + public void setBlock(Block block, Material material) + { + setBlock(block, material, (byte) 0); + } + + @SuppressWarnings("deprecation") + public void setBlock(Block block, Material material, byte data) + { + setBlock(block, material.getId(), data); + } + + public void setBlock(Block block, int id, byte data) + { + _blockRestoreMap.set(block, id, data); + } + + public void restoreBlocks() + { + _blockRestoreMap.restore(); + } + + public final void start() + { + _timeStarted = System.currentTimeMillis(); + _lastActive = System.currentTimeMillis(); + if (_announceStart) + { + announceStart(); + } + setState(EventState.LIVE); + customStart(); + UtilServer.RegisterEvents(this); + } + + public void announceStart() + { + UtilTextMiddle.display(C.cGreen + getName(), UtilWorld.locToStrClean(getCenterLocation()), 10, 100, 40); + + UtilServer.broadcast(F.main("Event", F.elem(getName()) + " has started at coordinates " + F.elem(UtilWorld.locToStrClean(getCenterLocation())))); + } + + protected abstract void customStart(); + + protected abstract void customTick(); + + public final void cleanup(boolean onDisable) + { + clearCreatures(); + restoreBlocks(); + customCleanup(onDisable); + } + + public abstract void customCleanup(boolean onDisable); + + public final void stop() + { + stop(false); + } + + public final void stop(boolean onDisable) + { + cleanup(onDisable); + if (onDisable) + { + setState(EventState.REMOVED); + } + else + { + setState(EventState.STOPPED); + } + customStop(); + HandlerList.unregisterAll(this); + } + + protected abstract void customStop(); + + public int getRandomRange(int min, int max) + { + return min + _random.nextInt(UtilMath.clamp(max - min, min, max)); + } + + public void announceMessage(String message) + { + UtilServer.broadcast(F.main("Event", F.elem(getName()) + ": " + message)); + } + + public void sendMessage(Player player, String message) + { + UtilPlayer.message(player, F.main("Event", F.elem(getName()) + ": " + message)); + } + + @EventHandler + public void tick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + customTick(); + } + + @EventHandler + public void endInactive(UpdateEvent event) + { + if (event.getType() != UpdateType.SEC) + { + return; + } + + long diff = System.currentTimeMillis() - getLastActive(); + if (diff > ACTIVE_TIMEOUT) + { + stop(); + } + } + + @EventHandler + public void prepareTimeout(UpdateEvent event) + { + if (event.getType() != UpdateType.SEC) + { + return; + } + + if (getState() != EventState.LOADING) + { + return; + } + + // Event was preparing for more than 5 minutes + if (getTimeRunning() > LOADING_TIMEOUT) + { + stop(); + } + } + + @Override + public List getLines(ScoreboardManager manager, Player player, List out) + { + return null; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossArenaLocationFinder.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossArenaLocationFinder.java new file mode 100644 index 000000000..a4c6bbc62 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossArenaLocationFinder.java @@ -0,0 +1,66 @@ +package mineplex.game.clans.clans.worldevent.boss; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.util.Vector; + +import mineplex.core.common.Pair; + +public class BossArenaLocationFinder +{ + private World _world; + + public BossArenaLocationFinder(World world) + { + _world = world; + } + + public Location getIronWizardCenter() + { + return new Location(_world, 1057, 63, -77); + } + + public Pair, List> getIronWizardPads() + { + List in = new ArrayList<>(); + List out = new ArrayList<>(); + + in.add(new Vector(1006, 62, -77)); + in.add(new Vector(1057, 62, -26)); + in.add(new Vector(1108, 62, -77)); + in.add(new Vector(1057, 62, -128)); + + out.add(new Vector(1035, 63, -77)); + out.add(new Vector(1057, 63, -99)); + out.add(new Vector(1079, 63, -77)); + out.add(new Vector(1057, 63, -55)); + + return Pair.create(in, out); + } + + public Location getSkeletonKingCenter() + { + return new Location(_world, -1043, 58, 159); + } + + public Pair, List> getSkeletonKingPads() + { + List in = new ArrayList<>(); + List out = new ArrayList<>(); + + in.add(new Vector(-1094, 57, 159)); + in.add(new Vector(-1043, 57, 210)); + in.add(new Vector(-992, 57, 159)); + in.add(new Vector(-1043, 57, 108)); + + out.add(new Vector(-1021, 58, 159)); + out.add(new Vector(-1043, 58, 137)); + out.add(new Vector(-1065, 58, 159)); + out.add(new Vector(-1043, 58, 181)); + + return Pair.create(in, out); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossDeathEvent.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossDeathEvent.java new file mode 100644 index 000000000..caf9109b3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossDeathEvent.java @@ -0,0 +1,39 @@ +package mineplex.game.clans.clans.worldevent.boss; + +import org.bukkit.Location; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class BossDeathEvent extends Event +{ + private static final HandlerList handlers = new HandlerList(); + + private final BossWorldEvent _event; + private final Location _deathLocation; + + public BossDeathEvent(BossWorldEvent event, Location location) + { + _event = event; + _deathLocation = location; + } + + public BossWorldEvent getEvent() + { + return _event; + } + + public Location getDeathLocation() + { + return _deathLocation; + } + + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossWorldEvent.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossWorldEvent.java new file mode 100644 index 000000000..817850ac7 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/BossWorldEvent.java @@ -0,0 +1,114 @@ +package mineplex.game.clans.clans.worldevent.boss; + +import java.util.List; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.util.Vector; + +import mineplex.core.blockrestore.BlockRestore; +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.disguise.DisguiseManager; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.projectile.ProjectileManager; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.api.EventCreatureDeathEvent; +import mineplex.game.clans.clans.worldevent.api.EventState; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.minecraft.game.classcombat.Skill.ISkill; +import mineplex.minecraft.game.classcombat.Skill.Assassin.Recall; +import mineplex.minecraft.game.core.condition.ConditionManager; +import mineplex.minecraft.game.core.damage.DamageManager; + +public abstract class BossWorldEvent> extends WorldEvent +{ + private static final double TELEPORT_PAD_RANGE = 1.5; + private static final long DELAY_TILL_DROP_REWARD = 40; + + private T _boss; + private List _teleportFrom; + private List _teleportTo; + + public BossWorldEvent(String name, Location centerLocation, double radius, List teleportFrom, List teleportTo, DisguiseManager disguiseManager, ProjectileManager projectileManager, DamageManager damageManager, BlockRestore blockRestore, ConditionManager conditionManager) + { + super(name, centerLocation, radius, true, disguiseManager, projectileManager, damageManager, blockRestore, conditionManager); + + _teleportFrom = teleportFrom.stream().map(vec -> vec.toLocation(centerLocation.getWorld())).collect(Collectors.toList()); + _teleportTo = teleportTo.stream().map(vec -> vec.toLocation(centerLocation.getWorld())).collect(Collectors.toList()); + } + + public abstract String getDeathMessage(); + + public T getBossCreature() + { + return _boss; + } + + public void setBossCreature(T boss) + { + _boss = boss; + } + + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + { + return; + } + if (getState() != EventState.LIVE) + { + return; + } + if (_teleportFrom.isEmpty() || _teleportTo.isEmpty()) + { + return; + } + for (Location from : _teleportFrom) + { + for (Player player : UtilPlayer.getInRadius(from, TELEPORT_PAD_RANGE).keySet()) + { + player.teleport(UtilMath.randomElement(_teleportTo)); + for (ISkill skill : ClansManager.getInstance().getClassManager().Get(player).GetSkills()) + { + if (skill instanceof Recall) + { + ((Recall)skill).Reset(player); + } + } + sendMessage(player, "You have teleported inside the arena!"); + } + } + } + + @EventHandler + public void onBossDeath(EventCreatureDeathEvent event) + { + if (_boss == null) + { + return; + } + if (event.getCreature().equals(_boss)) + { + Location drop = event.getCreature().getLastKnownLocation(); + UtilServer.CallEvent(new BossDeathEvent(this, drop)); + ClansManager.getInstance().runSyncLater(() -> + { + ClansManager.getInstance().getLootManager().dropRare(drop); + drop.getWorld().dropItem(drop, new ItemBuilder(Material.IRON_INGOT).setTitle(C.cDRedB + "Old Silver Token").setLore(C.cRed + "This token pulses with an evil aura.").setGlow(true).build()); + }, DELAY_TILL_DROP_REWARD); + Bukkit.broadcastMessage(getDeathMessage()); + stop(); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemBoss.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemBoss.java new file mode 100644 index 000000000..2d79eea2d --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemBoss.java @@ -0,0 +1,46 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard; + +import org.bukkit.Bukkit; +import org.bukkit.Location; + +import mineplex.core.common.util.F; +import mineplex.game.clans.clans.worldevent.WorldEventManager; +import mineplex.game.clans.clans.worldevent.boss.BossWorldEvent; + +public class GolemBoss extends BossWorldEvent +{ + public GolemBoss(WorldEventManager manager) + { + super("Iron Wizard", manager.getBossArenaLocationFinder().getIronWizardCenter(), 50, manager.getBossArenaLocationFinder().getIronWizardPads().getLeft(), manager.getBossArenaLocationFinder().getIronWizardPads().getRight(), manager.getDisguiseManager(), manager.getClans().getProjectile(), manager.getClans().getDamageManager(), manager.getBlockRestore(), manager.getClans().getCondition()); + } + + @Override + protected void customStart() + { + Bukkit.broadcastMessage(F.main(getName(), "The mighty " + getName() + " challenges you to face him!")); + spawnGolem(getCenterLocation()); + } + + @Override + public String getDeathMessage() + { + return F.main(getName(), "The mighty " + getName() + " has fallen!"); + } + + private GolemCreature spawnGolem(Location location) + { + GolemCreature golemCreature = new GolemCreature(this, location); + registerCreature(golemCreature); + setBossCreature(golemCreature); + return golemCreature; + } + + @Override + protected void customTick() {} + + @Override + public void customCleanup(boolean onDisable) {} + + @Override + protected void customStop() {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemCreature.java new file mode 100644 index 000000000..216ede265 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/GolemCreature.java @@ -0,0 +1,599 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemBlockHail; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemBlockShot; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemDeadlyTremor; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemEarthquake; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemExplodingAura; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemIronHook; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemMeleeAttack; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemRupture; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemSlam; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities.GolemSpike; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class GolemCreature extends EventCreature +{ + private int _lastAbility; + private long _lastWalked; + private Location _standing; + private long _spawnDelay = System.currentTimeMillis(); + private long _reverseWalk; + private Map>, Class[]> _preferredCombos = new HashMap<>(); + private Class> _lastAttack; + private boolean _usedFinalAttack; + private List> _currentAbilities = new ArrayList<>(); + private double _canDeadlyTremor = 225; + private Vector _afkWalk = new Vector(); + private long _lastSlam; + + public GolemCreature(GolemBoss boss, Location location) + { + super(boss, location, "Iron Wizard", true, 3000, 30, true, IronGolem.class); + + spawnEntity(); + + _preferredCombos.put(GolemEarthquake.class, new Class[] + { + GolemBlockHail.class, GolemRupture.class + }); + _preferredCombos.put(GolemMeleeAttack.class, new Class[] + { + GolemEarthquake.class, GolemRupture.class + }); + _preferredCombos.put(GolemDeadlyTremor.class, new Class[] + { + GolemMeleeAttack.class + }); + _preferredCombos.put(GolemBlockShot.class, new Class[] + { + GolemEarthquake.class + }); + _preferredCombos.put(GolemRupture.class, new Class[] + { + GolemBlockShot.class + }); + _preferredCombos.put(GolemBlockHail.class, new Class[] + { + GolemDeadlyTremor.class + }); + } + + private boolean hasFurther(Map distances, double range) + { + for (Player player : distances.keySet()) + { + if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + + Double dist = distances.get(player); + if (dist >= range) + { + return true; + } + } + + return false; + } + + @Override + protected void spawnCustom() + { + UtilEnt.vegetate(getEntity()); + _standing = getEntity().getLocation(); + } + + @SuppressWarnings("unchecked") + @EventHandler + public void abilityTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (!UtilTime.elapsed(_spawnDelay, 5000)) + { + _standing = getEntity().getLocation(); + return; + } + + Iterator> itel = _currentAbilities.iterator(); + boolean canDoNew = _currentAbilities.size() < 3; + + while (itel.hasNext()) + { + BossAbility ability = itel.next(); + + if (ability.hasFinished()) + { + itel.remove(); + ability.setFinished(); + _lastAbility = 20; + + HandlerList.unregisterAll(ability); + if (DEBUG_MODE) + { + System.out.print("Unregistered golem ability " + ability.getClass().getSimpleName()); + } + } + else if (!ability.inProgress()) + { + canDoNew = false; + } + } + + if (_lastAbility-- <= 0 && canDoNew && UtilBlock.solid(getEntity().getLocation().getBlock().getRelative(BlockFace.DOWN))) + { + Map>, Integer> weight = new HashMap<>(); + Map dist = new HashMap<>(); + + for (Player player : UtilPlayer.getNearby(getEntity().getLocation(), 50, true)) + { + if (player.hasLineOfSight(getEntity())) + { + dist.put(player, player.getLocation().distance(getEntity().getLocation())); + } + } + + if (!dist.isEmpty()) + { + double hp = getHealthPercent(); + + { // Melee + List players = getPlayers(dist, UtilMath.r(10) == 0 ? 4 : 3); + + if (!players.isEmpty()) + { + if (players.size() >= 4) + { + weight.put(GolemEarthquake.class, 999); + } + else + { + weight.put(GolemMeleeAttack.class, 999); + } + } + } + + if (hasFurther(dist, 15)) + { // Iron Hook + weight.put(GolemIronHook.class, 6); //6 + } + + if (hp < 0.7) + { // Earthquake + List players = getPlayers(dist, 10); + + double score = 0; + + for (Player player : players) + { + score += (8 - dist.get(player)) / 2; + } + + if (players.size() >= 3) + { + score += 7; + } + + if (score > 0) + { + weight.put(GolemEarthquake.class, (int) Math.ceil(score)); + } + } + + { // Wall explode + if (!getPlayers(dist, 20).isEmpty() && getPlayers(dist, 4).isEmpty()) + { + weight.put(GolemSpike.class, 8); + } + } + + { // Block Shot + List players = getPlayers(dist, 30); + + for (Player player : players) + { + if (dist.get(player) > 4) + { + weight.put(GolemBlockShot.class, 6); + break; + } + } + } + + { // Rupture + List players = getPlayers(dist, 30); + + if (!players.isEmpty()) + { + weight.put(GolemRupture.class, (int) Math.min(5, dist.get(players.get(0)))); + } + } + + { // Slam + List players = getPlayers(dist, 30); + + if (!players.isEmpty() && UtilTime.elapsed(_lastSlam, 20000)) + { + weight.put(GolemSlam.class, 6); + } + } + + if (_canDeadlyTremor <= 0) // Deadly Tremor + { + List players = getPlayers(dist, 80); + + for (BossAbility ability : _currentAbilities) + { + if (ability instanceof GolemExplodingAura) + { + players.clear(); + } + } + + if (!players.isEmpty()) + { + weight.put(GolemDeadlyTremor.class, (int) 30); + } + } + + {// Block Hail + List players = getPlayers(dist, 30); + + if (!players.isEmpty()) + { + int we = _lastAttack == GolemEarthquake.class ? 20 : UtilMath.r(15) - 2; + + if (we > 0) + { + weight.put(GolemBlockHail.class, we); + } + } + } + + if (!_usedFinalAttack && getHealth() < 90) + { + _usedFinalAttack = true; + weight.clear(); + + weight.put(GolemExplodingAura.class, 999); + } + + if (_lastAttack != null && _preferredCombos.containsKey(_lastAttack)) + { + weight.remove(_lastAttack); + + for (Class c : _preferredCombos.get(_lastAttack)) + { + if (weight.containsKey(c)) + { + weight.put((Class>)c, weight.get(c) * 4); + } + } + } + + for (BossAbility ability : _currentAbilities) + { + weight.remove(ability.getClass()); + } + + BossAbility ability = null; + + if (!weight.isEmpty()) + { + int i = 0; + + for (Integer entry : weight.values()) + { + i += entry; + } + + for (int a = 0; a < 10; a++) + { + int luckyNumber = UtilMath.r(i); + + for (Entry>, Integer> entry : weight.entrySet()) + { + luckyNumber -= entry.getValue(); + + if (luckyNumber <= 0) + { + try + { + ability = entry.getKey().getConstructor(GolemCreature.class).newInstance(this); + + if (ability.getTarget() == null) + { + ability = null; + } + else + { + break; + } + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + break; + } + } + } + } + + if (ability != null && ability.getTarget() != null) + { + _lastAttack = (Class>) ability.getClass(); + + if (ability instanceof GolemDeadlyTremor) + { + _canDeadlyTremor = 225; + } + else if (ability instanceof GolemSlam) + { + _lastSlam = System.currentTimeMillis(); + } + + Bukkit.getPluginManager().registerEvents(ability, UtilServer.getPlugin()); + + if (DEBUG_MODE) + { + System.out.print("Golem boss is using " + ability.getClass().getSimpleName()); + } + + _currentAbilities.add(ability); + } + + _lastAbility = 10; + } + + _lastAttack = null; + } + + boolean canMove = true; + + for (BossAbility ability : _currentAbilities) + { + try + { + ability.tick(); + } + catch (Exception e) + { + e.printStackTrace(); //Keeps the boss from getting stuck if one of the moves throws an error in progression + } + + if (!ability.canMove()) + { + canMove = false; + } + } + + if (canMove) + { + Player target = null; + double dist = 0; + + for (Player player : UtilPlayer.getNearby(getEntity().getLocation(), 50, true)) + { + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + double d = player.getLocation().distance(getEntity().getLocation()); + + if (d > 1.5 && (d < 7 || d > 15) && (target == null || (d < 50 && dist > d))) + { + target = player; + dist = d; + } + } + + Vector vec = null; + boolean superWalk = false; + + if (target != null) + { + vec = target.getLocation().subtract(getEntity().getLocation()).toVector(); + vec.setY(getEntity().getLocation().getY()); + + double len = vec.length(); + + vec.setX(vec.getX() * (UtilMath.random.nextDouble() / 3D)); + vec.setZ(vec.getZ() * (UtilMath.random.nextDouble() / 3D)); + + vec.multiply(len); + + if (target != null && dist < 8) + { + vec.multiply(-1); + superWalk = true; + } + + if (!UtilAlg.HasSight(getEntity().getLocation(), + getEntity().getLocation().add(vec.clone().normalize().multiply(2)))) + { + _reverseWalk = System.currentTimeMillis(); + } + + if (!UtilTime.elapsed(_reverseWalk, 4000)) + { + vec.multiply(-1); + } + + } + else if (!UtilTime.elapsed(_lastWalked, 7000)) + { + vec = _afkWalk; + } + else if (UtilTime.elapsed(_lastWalked, 12000)) + { + _afkWalk = new Vector(); + + for (int i = 0; i < 10; i++) + { + Vector vector = new Vector(UtilMath.r(20) - 10, 0, UtilMath.r(20) - 10); + + if (UtilAlg.HasSight(getEntity().getLocation(), + getEntity().getLocation().add(vector.clone().normalize().multiply(2)))) + { + vec = _afkWalk = vector; + break; + } + } + + _lastWalked = System.currentTimeMillis(); + } + + if (vec != null) + { + { + UtilEnt.CreatureMoveFast(getEntity(), getEntity().getLocation().add(vec), + (target != null ? 1.8F : 1.1F) + (superWalk ? 0.4F : 0)); + } + } + + _standing = getEntity().getLocation(); + } + else + { + Location l = getEntity().getLocation(); + + _standing.setYaw(l.getYaw()); + _standing.setPitch(l.getPitch()); + _standing.setY(l.getY()); + + getEntity().teleport(_standing); + } + } + + private List getPlayers(final Map map, double maxDist) + { + List list = new ArrayList(); + + for (Player p : map.keySet()) + { + if (map.get(p) <= maxDist) + { + list.add(p); + } + } + + Collections.sort(list, (o1, o2) -> + { + return Double.compare(map.get(o2), map.get(o1)); + }); + + return list; + } + + @EventHandler + public void onGolemDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().equals(getEntity())) + { + event.AddKnockback("Heavy Golem", 0.3); + } + } + + @EventHandler + public void onRangedAttack(CustomDamageEvent event) + { + if (event.GetDamageeEntity().equals(getEntity())) + { + if (event.GetDamageePlayer() != null) + { + if (event.GetProjectile() != null && event.GetProjectile() instanceof Arrow) + { + if (new Random().nextDouble() <= .5) + { + event.SetCancelled("Iron Skin Reflection"); + getEntity().getWorld().playSound(getEntity().getLocation(), Sound.ZOMBIE_METAL, 0.5f, 1.6f); + return; + } + } + + double dist = event.GetDamageePlayer().getLocation().distance(getEntity().getLocation()); + + double maxRange = _usedFinalAttack ? 20 : 45; + + double modifier = (maxRange - dist) / maxRange; + + if (modifier > 0) + { + event.AddMod("Ranged Resistance", 1 - modifier); + } + else + { + event.SetCancelled("Range too far"); + } + } + } + } + + @Override + public void dieCustom() + { + endAbility(); + } + + private void endAbility() + { + for (BossAbility ability : _currentAbilities) + { + ability.setFinished(); + HandlerList.unregisterAll(ability); + } + + _currentAbilities.clear(); + } + + @Override + public void setHealth(double health) + { + _canDeadlyTremor -= getHealth() - health; + super.setHealth(health); + if (getHealth() <= 100 && !_usedFinalAttack) + { + endAbility(); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/BlockHailBlock.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/BlockHailBlock.java new file mode 100644 index 000000000..d837321c9 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/BlockHailBlock.java @@ -0,0 +1,88 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.IronGolem; + +import mineplex.core.common.util.UtilEnt; +import net.minecraft.server.v1_8_R3.DataWatcher; +import net.minecraft.server.v1_8_R3.Entity; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayOutAttachEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving; + +public class BlockHailBlock +{ + private int _block = UtilEnt.getNewEntityId(); + private int _silverfish = UtilEnt.getNewEntityId(); + private Location _location; + private Material _mat; + + public BlockHailBlock(Location loc, Material mat) + { + _location = loc; + _mat = mat; + } + + public PacketPlayOutEntityDestroy getDestroyPacket() + { + return new PacketPlayOutEntityDestroy(new int[] + { + _silverfish, _block + }); + } + + public Location getLocation() + { + return _location; + } + + public Material getMaterial() + { + return _mat; + } + + @SuppressWarnings("deprecation") + public Packet[] getSpawnPackets(IronGolem entity) + { + Packet[] packets = new Packet[3]; + + PacketPlayOutSpawnEntityLiving packet1 = new PacketPlayOutSpawnEntityLiving(); + + DataWatcher watcher = new DataWatcher(null); + watcher.a(0, (byte) 32, Entity.META_ENTITYDATA, (byte) 0); + watcher.a(1, 0, Entity.META_AIR, 0); + + packet1.a = _silverfish; + packet1.b = EntityType.SILVERFISH.getTypeId(); + packet1.c = (int) Math.floor(_location.getX() * 32); + packet1.d = (int) Math.floor(_location.getY() * 32); + packet1.e = (int) Math.floor(_location.getZ() * 32); + packet1.l = watcher; + + packets[0] = packet1; + + PacketPlayOutSpawnEntity packet2 = new PacketPlayOutSpawnEntity(((CraftEntity) entity).getHandle(), 70, _mat.getId()); + + packet2.a = _block; + + packet2.b = (int) Math.floor(_location.getX() * 32); + packet2.c = (int) Math.floor(entity.getLocation().getY() * 32); + packet2.d = (int) Math.floor(_location.getZ() * 32); + + packets[1] = packet2; + + PacketPlayOutAttachEntity packet3 = new PacketPlayOutAttachEntity(); + + packet3.b = _block; + packet3.c = _silverfish; + + packets[2] = packet3; + + return packets; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockHail.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockHail.java new file mode 100644 index 000000000..99c437774 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockHail.java @@ -0,0 +1,475 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilShapes; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.EntityIronGolem; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemBlockHail extends BossAbility +{ + private int _currentBlock; + private int _currentLevel; + private List _fallingBlocks = new ArrayList<>(); + private Map> _floatingBlocks = new HashMap<>(); + private Map _blocks = new HashMap<>(); + private int _levelToReach; + private boolean _spawned; + private List _spawnLocs = new ArrayList<>(); + private Player _target; + private Location _center; + private int _ticks; + + public GolemBlockHail(GolemCreature creature) + { + super(creature); + + _center = getLocation(); + + if (creature.getHealthPercent() > 0.75) + { + _levelToReach = 1; + } + else if (creature.getHealthPercent() > 0.5) + { + _levelToReach = 2; + } + else + { + _levelToReach = 3; + } + + _target = getTarget(); + } + + @Override + public Player getTarget() + { + Player target = null; + double dist = 0; + + if (inProgress()) + { + for (Player player : UtilPlayer.getNearby(_center, 40, true)) + { + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + if (target != null && _blocks.containsKey(player.getName()) && _blocks.get(player.getName()) > 8) + { + continue; + } + + double d = player.getLocation().distance(_center); + + if (target == null || dist > d) + { + target = player; + dist = d; + } + } + } + + return target; + } + + @Override + public boolean canMove() + { + return _spawned && _floatingBlocks.isEmpty(); + } + + @Override + public boolean hasFinished() + { + return _target == null || !_target.isValid() || ((_fallingBlocks.isEmpty() && _spawned) && _ticks >= 8 * 9) + || _center.distance(_target.getLocation()) > 100; + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + Iterator fallingIterator = _fallingBlocks.iterator(); + + while (fallingIterator.hasNext()) + { + FallingBlock cur = fallingIterator.next(); + + if (cur.isDead() || !cur.isValid() || cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + fallingIterator.remove(); + + Block block = cur.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + // Expire + if (cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + cur.remove(); + continue; + } + + cur.remove(); + continue; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) cur).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, + nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) cur.getWorld()).getHandle().getEntities(((CraftEntity) cur).getHandle(), + ((CraftEntity) cur).getHandle().getBoundingBox().a(((CraftEntity) cur).getHandle().motX, + ((CraftEntity) cur).getHandle().motY, ((CraftEntity) cur).getHandle().motZ).grow(2, 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + continue; + + // Creative or Spec + if (ent instanceof Player) + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + continue; + + // float f1 = (float)(nmsEntity.boundingBox.a() * 0.6f); + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + cur.getWorld().playEffect(victim.getEyeLocation().subtract(0, 0.5, 0), Effect.STEP_SOUND, cur.getBlockId()); + { + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) victim, getEntity(), null, + DamageCause.CONTACT, 10 * getBoss().getDifficulty(), true, true, false, "Iron Wizard Block Hail", + "Iron Wizard Block Hail"); + } + + if (victim instanceof Player) + { + getBoss().getEvent().getCondition().Factory().Slow("Iron Wizard Block Hail", (LivingEntity) victim, + getEntity(), 3, 2, false, false, false, false); + } + + fallingIterator.remove(); + cur.remove(); + } + else if (finalObjectPosition != null) + { + Block block = cur.getWorld().getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt( + nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + fallingIterator.remove(); + cur.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + cur.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + @Override + public void setFinished() + { + for (List floatingBlocks : _floatingBlocks.values()) + { + for (BlockHailBlock falling : floatingBlocks) + { + PacketPlayOutEntityDestroy packet = falling.getDestroyPacket(); + + for (Player player : UtilServer.getPlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + } + } + + for (FallingBlock block : _fallingBlocks) + { + block.remove(); + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (inProgress()) + { + for (Player player : UtilPlayer.getNearby(_center, 5, true)) + { + Location loc = player.getLocation(); + + if (Math.abs(loc.getY() - (_center.getY() + 1)) <= 1) + { + loc.setY(_center.getY()); + + if (loc.distance(_center) < 2.8 + (_currentLevel * 0.75)) + { + if (canDamage(player)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getEntity(), null, + DamageCause.CONTACT, 10 * getBoss().getDifficulty(), true, true, false, + "Iron Wizard Protection", "Iron Wizard Protection"); + + loc.getWorld().playEffect(player.getLocation(), Effect.STEP_SOUND, Material.OBSIDIAN.getId()); + loc.getWorld().playEffect(player.getEyeLocation(), Effect.STEP_SOUND, Material.OBSIDIAN.getId()); + } + } + } + } + } + + if (!_spawned) + { + if (_currentBlock >= _spawnLocs.size()) + { + + if (_currentLevel + 1 <= _levelToReach) + { + _currentLevel++; + _currentBlock = 0; + + _spawnLocs = UtilShapes.getDistancedCircle(_center.clone().add(0, 2.8 + (_currentLevel * 0.75), 0), 1.3, + 1 + (_currentLevel * 1.3)); + + for (int i = UtilMath.r(_spawnLocs.size()); i > 0; i--) + { + _spawnLocs.add(_spawnLocs.remove(0)); + } + } + } + + if (_currentBlock < _spawnLocs.size()) + { + if (_ticks % 2 == 0) + { + IronGolem entity = getEntity(); + + Location loc = _spawnLocs.get(_currentBlock++); + + List floatingBlocks = new ArrayList<>(); + + if (_floatingBlocks.containsKey(_currentLevel)) + { + floatingBlocks = _floatingBlocks.get(_currentLevel); + } + else + { + _floatingBlocks.put(_currentLevel, floatingBlocks); + } + + if (loc.getBlock().getType() == Material.AIR && UtilAlg.HasSight(entity.getLocation(), loc)) + { + + BlockHailBlock floating = new BlockHailBlock(loc, Material.STONE); + UtilEnt.CreatureLook(entity, _target); + + floatingBlocks.add(floating); + + Packet[] packets = floating.getSpawnPackets(entity); + + for (Player player : UtilPlayer.getNearby(loc, 100)) + { + UtilPlayer.sendPacket(player, packets); + } + + entity.getWorld().playSound(entity.getLocation(), Sound.DIG_GRASS, 3, 0.9F); + } + + if (_floatingBlocks.size() % 2 == 0) + { + Collections.reverse(floatingBlocks); + } + } + } + else + { + _spawned = true; + _ticks = -20; + } + } + else if (_ticks > 0 && _ticks % 2 == 0 && !_floatingBlocks.isEmpty()) + { + IronGolem entity = getEntity(); + + if (_ticks % 16 == 0) + { + _target = getTarget(); + + if (_target == null) + return; + } + + EntityIronGolem golem = ((CraftIronGolem) entity).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + UtilEnt.CreatureLook(entity, _target); + + BlockHailBlock floatingBlock = null; + + for (int i = 1; i <= _currentLevel; i++) + { + if (_floatingBlocks.containsKey(i) && !_floatingBlocks.get(i).isEmpty()) + { + floatingBlock = _floatingBlocks.get(i).remove(0); + + if (_floatingBlocks.get(i).isEmpty()) + { + _floatingBlocks.remove(i); + } + + break; + } + } + + PacketPlayOutEntityDestroy packet = floatingBlock.getDestroyPacket(); + + for (Player player : UtilServer.getPlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + + Location loc = floatingBlock.getLocation(); + + FallingBlock b = loc.getWorld().spawnFallingBlock(loc, floatingBlock.getMaterial(), (byte) 0); + b.setDropItem(false); + + Vector vec = UtilAlg.calculateVelocity(loc.toVector(), + _target.getLocation().toVector().add(new Vector(UtilMath.r(6 + (_currentLevel * 2)) - (2 + _currentLevel), 0, + UtilMath.r(6 + (_currentLevel * 2)) - (2 + _currentLevel))), + 6); + + b.setVelocity(vec); + + _fallingBlocks.add(b); + + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 3, 0.9F); + + _blocks.put(_target.getName(), _blocks.containsKey(_target.getName()) ? _blocks.get(_target.getName()) + 1 : 1); + } + + List points = new ArrayList<>(); + + for (int i = _currentLevel; i <= _currentLevel; i++) + { + points.addAll(UtilShapes.getDistancedCircle(_center.clone().add(0, 3.3 + (i * 0.75), 0), 0.3, 1 + (i * 1.3))); + } + + for (int i = 0; i < points.size(); i++) + { + if (_spawned || i < _ticks) + { + Location loc = points.get(i); + + UtilParticle.PlayParticle( + ParticleType.BLOCK_DUST.getParticle(_spawned && i < _ticks ? Material.STONE : Material.DIRT, 0), loc, 0, + 0, 0, 0, 0, UtilParticle.ViewDist.LONG, UtilServer.getPlayers()); + } + } + + _ticks++; + } + + @Override + public boolean inProgress() + { + return !_spawned || !_floatingBlocks.isEmpty(); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockShot.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockShot.java new file mode 100644 index 000000000..4f652b4a8 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemBlockShot.java @@ -0,0 +1,442 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.EntityIronGolem; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityVelocity; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemBlockShot extends BossAbility +{ + private Map _blockLoc = new HashMap<>(); + private Map _blockType = new HashMap<>(); + private List _current = new ArrayList<>(); + private Map _preshoot = new HashMap<>(); + private Player _target; + private Map _targetBlock = new HashMap<>(); + private Map _shotAt = new HashMap<>(); + private int _thrown; + private int _tick; + private int _toThrow; + + public GolemBlockShot(GolemCreature creature) + { + super(creature); + + if (creature.getHealthPercent() > 0.75) + { + _toThrow = 3; + } + else if (creature.getHealthPercent() > 0.5) + { + _toThrow = 6; + } + else + { + _toThrow = 9; + } + + _target = getTarget(); + } + + @Override + public boolean canMove() + { + return _current.isEmpty() && _thrown == _toThrow; + } + + @Override + public Player getTarget() + { + Player target = null; + double dist = 0; + + Location loc1 = getLocation(); + Location loc2 = loc1.clone().add(loc1.getDirection().setY(0).normalize()); + + List players = UtilPlayer.getNearby(getLocation(), 40, true); + + for (Player player : players) + { + if (_shotAt.containsKey(player.getUniqueId()) && _shotAt.get(player.getUniqueId()) >= 3) + { + continue; + } + + double dist1 = player.getLocation().distance(loc1); + double dist2 = player.getLocation().distance(loc2); + + double dist3 = dist1 - dist2; + + if (dist3 < 0.6 || dist1 > 30 || (target != null && dist3 < dist)) + { + continue; + } + + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + target = player; + dist = dist3; + } + + return target; + } + + @Override + public boolean hasFinished() + { + return _current.isEmpty() && _preshoot.isEmpty() && (_target == null || _thrown >= _toThrow); + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + Iterator fallingIterator = _current.iterator(); + + while (fallingIterator.hasNext()) + { + FallingBlock cur = fallingIterator.next(); + + if (cur.isDead() || !cur.isValid() || cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + fallingIterator.remove(); + + Block block = cur.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + // Expire + if (cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + cur.remove(); + continue; + } + + cur.remove(); + continue; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) cur).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, + nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) cur.getWorld()).getHandle().getEntities(((CraftEntity) cur).getHandle(), + ((CraftEntity) cur).getHandle().getBoundingBox().a(((CraftEntity) cur).getHandle().motX, + ((CraftEntity) cur).getHandle().motY, ((CraftEntity) cur).getHandle().motZ).grow(2, 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + continue; + + // Creative or Spec + if (ent instanceof Player) + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + continue; + + // float f1 = (float)(nmsEntity.boundingBox.a() * 0.6f); + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + cur.getWorld().playEffect(victim.getEyeLocation().subtract(0, 0.5, 0), Effect.STEP_SOUND, cur.getBlockId()); + + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) victim, getEntity(), null, + DamageCause.CONTACT, 10 * getBoss().getDifficulty(), true, true, false, "Iron Wizard Block Shot", + "Iron Wizard Block Shot"); + + cur.remove(); + fallingIterator.remove(); + + Vector vec = UtilAlg.getTrajectory(getEntity(), victim); + vec.setY(0).normalize(); + + double strength = 1; + + if (!(victim instanceof Player) || !((Player) victim).isBlocking()) + { + strength = 1.3; + } + + UtilAction.velocity(victim, vec, strength, true, 0, 0.2, 1, true); + } + else if (finalObjectPosition != null) + { + Block block = cur.getWorld().getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt( + nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + cur.remove(); + fallingIterator.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + cur.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + @Override + public void setFinished() + { + for (FallingBlock falling : _current) + { + falling.remove(); + } + + int[] ids = new int[_preshoot.size()]; + + int a = 0; + for (int id : _preshoot.keySet()) + { + ids[a++] = id; + } + + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ids); + + for (Player player : Bukkit.getOnlinePlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (_target == null || _target.getLocation().distance(getLocation()) > 30 || !_target.hasLineOfSight(getEntity())) + { + _target = getTarget(); + } + + Entity entity = getEntity(); + + if (_tick++ % 16 == 0 && _target != null && _thrown < _toThrow) + { + _thrown++; + + UtilEnt.CreatureLook(entity, _target); + EntityIronGolem golem = ((CraftIronGolem) entity).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 2, 1); + + Location loc = entity.getLocation(); + loc.setYaw(loc.getYaw() + (UtilMath.r(150) - 75)); + loc.add(loc.getDirection().setY(0).normalize()); + + Block block = loc.getBlock(); + + if (block.getType() == Material.AIR) + { + block = block.getRelative(BlockFace.DOWN); + } + + Material mat = block.getType(); + + if (!UtilBlock.solid(block)) + { + mat = Material.STONE; + } + + int id = UtilEnt.getNewEntityId(); + + _preshoot.put(id, System.currentTimeMillis()); + _blockType.put(id, mat); + _blockLoc.put(id, loc.clone().add(0, 0.6, 0)); + _targetBlock.put(id, _target); + + PacketPlayOutSpawnEntity packet = new PacketPlayOutSpawnEntity(((CraftEntity) entity).getHandle(), 70, mat.getId()); + + packet.a = id; + + packet.b = (int) Math.floor(loc.getX() * 32); + packet.c = (int) Math.floor(loc.getY() * 32); + packet.d = (int) Math.floor(loc.getZ() * 32); + + packet.g = (int) ((0.45) * 8000); + + PacketPlayOutEntityVelocity packet2 = new PacketPlayOutEntityVelocity(id, 0, 0.45D, 0); + + for (Player player : UtilPlayer.getNearby(loc, 70)) + { + UtilPlayer.sendPacket(player, packet, packet2); + } + + _shotAt.put(_target.getUniqueId(), + (_shotAt.containsKey(_target.getUniqueId()) ? _shotAt.get(_target.getUniqueId()) : 0) + 1); + + _target = getTarget(); + } + else + { + Iterator> itel = _preshoot.entrySet().iterator(); + + while (itel.hasNext()) + { + Entry entry = itel.next(); + + if (UtilTime.elapsed(entry.getValue(), 920)) + { + itel.remove(); + + int id = entry.getKey(); + + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(new int[] + { + id + }); + + for (Player player : Bukkit.getOnlinePlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + + Location loc = _blockLoc.get(id); + FallingBlock falling = loc.getWorld().spawnFallingBlock(loc, _blockType.get(id), (byte) 0); + falling.setDropItem(false); + + _current.add(falling); + + Player target = _targetBlock.get(id); + + UtilEnt.CreatureLook(entity, target); + EntityIronGolem golem = ((CraftIronGolem) entity).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 2, 1.2F); + entity.getWorld().playEffect(falling.getLocation(), Effect.STEP_SOUND, falling.getBlockId()); + + Location l = falling.getLocation(); + l.setY(entity.getLocation().getY()); + + Location loc1 = target.getEyeLocation(); + + if (loc1.getY() - l.getY() > 1) + { + loc1.setY(l.getY() + 1); + } + + int dist = (int) Math.ceil(loc1.toVector().setY(0).distance(l.toVector().setY(0))); + + Vector vector = UtilAlg.calculateVelocity(l.toVector(), loc1.toVector(), dist / 13); + + falling.setVelocity(vector); + } + } + } + + if (_thrown >= 3 && !UtilPlayer.getNearby(getLocation(), 10, true).isEmpty()) + { + _thrown = 99; + } + } + + @Override + public boolean inProgress() + { + return _thrown < _toThrow || !_current.isEmpty(); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemCaveIn.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemCaveIn.java new file mode 100644 index 000000000..5656844ad --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemCaveIn.java @@ -0,0 +1,336 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilShapes; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemCaveIn extends BossAbility +{ + private List _blocks = new ArrayList<>(); + private List _fallingBlocks = new ArrayList<>(); + private int _tick; + + public GolemCaveIn(GolemCreature creature) + { + super(creature); + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public Player getTarget() + { + if (getTarget(4) == null) + { + return getTarget(40); + } + + return null; + } + + @Override + public boolean hasFinished() + { + return _tick > 60 && _fallingBlocks.isEmpty(); + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + Iterator fallingIterator = _fallingBlocks.iterator(); + + while (fallingIterator.hasNext()) + { + FallingBlock cur = fallingIterator.next(); + + if (cur.isDead() || !cur.isValid() || cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + fallingIterator.remove(); + + Block block = cur.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + // Expire + if (cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + cur.remove(); + continue; + } + + cur.remove(); + continue; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) cur).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, + nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) cur.getWorld()).getHandle().getEntities(((CraftEntity) cur).getHandle(), + ((CraftEntity) cur).getHandle().getBoundingBox().a(((CraftEntity) cur).getHandle().motX, + ((CraftEntity) cur).getHandle().motY, ((CraftEntity) cur).getHandle().motZ).grow(2, 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + continue; + + // Creative or Spec + if (ent instanceof Player) + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + continue; + + // float f1 = (float)(nmsEntity.boundingBox.a() * 0.6f); + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + cur.getWorld().playEffect(victim.getEyeLocation().subtract(0, 0.5, 0), Effect.STEP_SOUND, cur.getBlockId()); + + if (canDamage(victim)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) victim, getEntity(), null, + DamageCause.CONTACT, 10 * getBoss().getDifficulty(), true, true, false, "Iron Wizard Cave In", + "Iron Wizard Cave In"); + } + + cur.remove(); + fallingIterator.remove(); + } + else if (finalObjectPosition != null) + { + Block block = cur.getWorld().getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt( + nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + cur.remove(); + fallingIterator.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + cur.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + @SuppressWarnings("deprecation") + @Override + public void setFinished() + { + for (FallingBlock block : _fallingBlocks) + { + block.remove(); + } + + for (Block block : _blocks) + { + block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getTypeId()); + block.setType(Material.AIR); + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (_tick++ == 0) + { + Location l = getLocation(); + + List blocks = UtilShapes.getSphereBlocks(l, 3, 3, true); + + for (Location loc : blocks) + { + if (loc.getBlockY() >= l.getBlockY()) + { + Block b = loc.getBlock(); + + if (b.getType() == Material.AIR) + { + _blocks.add(b); + + loc.setY(l.getY() - 1); + + b.setType(loc.getBlock().getType()); + + b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, loc.getBlock().getTypeId()); + } + } + } + } + + if (_tick % 5 == 0) + + { + for (Player player : UtilPlayer.getNearby(getLocation(), 2.5, true)) + { + player.teleport(player.getLocation().add(0, 4, 0)); + UtilAction.velocity(player, new Vector(UtilMath.r(10) - 5, 3, UtilMath.r(10) - 5).normalize()); + } + } + + if (_tick < 200) + + { + Location loc = getLocation(); + loc.setY(loc.getY() + 4); + + for (int i = 0; i < 30; i++) + { + loc.setY(loc.getY() + 1); + Block b = loc.getBlock(); + + if (UtilBlock.solid(b)) + { + break; + } + } + + if (!UtilBlock.solid(loc.getBlock())) + { + return; + } + + List players = UtilPlayer.getNearby(getLocation(), 50, true); + + for (int i = 0; i < players.size() * 2; i++) + { + int dist = UtilMath.r(10); + + if (dist < 3) + { + dist = 2; + } + else if (dist < 5) + { + dist = 5; + } + else + { + dist = 10; + } + + Location l = players.get(UtilMath.r(players.size())).getLocation().add(UtilMath.r(dist * 2) - dist, 0, + UtilMath.r(dist * 2) - dist); + l.setY(loc.getY()); + + Block b = l.getBlock(); + l.subtract(0, 1, 0); + + if (UtilBlock.solid(b)) + { + if (l.getBlock().getType() == Material.AIR) + { + if (UtilAlg.HasSight(l, getLocation().add(0, 4, 0))) + { + FallingBlock block = b.getWorld().spawnFallingBlock(b.getLocation().add(0.5, -1, 0.5), b.getTypeId(), + b.getData()); + + block.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, block.getBlockId()); + block.setDropItem(false); + + _fallingBlocks.add(block); + } + } + } + } + } + + } + + @Override + public boolean inProgress() + { + return true; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemDeadlyTremor.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemDeadlyTremor.java new file mode 100644 index 000000000..d9934e3c9 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemDeadlyTremor.java @@ -0,0 +1,89 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import org.bukkit.Effect; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.recharge.Recharge; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; + +public class GolemDeadlyTremor extends BossAbility +{ + private static final long ATTACK_DURATION = 10000; + private long _start; + + public GolemDeadlyTremor(GolemCreature creature) + { + super(creature); + _start = System.currentTimeMillis(); + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public boolean hasFinished() + { + return UtilTime.elapsed(_start, ATTACK_DURATION); + } + + @Override + public void setFinished() + { + _start = System.currentTimeMillis() - ATTACK_DURATION; + } + + @Override + public void tick() + { + for (Player player : UtilPlayer.getInRadius(getLocation(), 30).keySet()) + { + player.playSound(player.getLocation(), Sound.MINECART_BASE, 0.2f, 0.2f); + + if (UtilEnt.isGrounded(player)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getBoss().getEntity(), null, DamageCause.CUSTOM, (1 + 2 * Math.random()) * getBoss().getDifficulty(), false, false, false, getBoss().getEntity().getName(), "Deadly Tremor"); + + if (Recharge.Instance.use(player, "Deadly Tremor Hit", 400, false, false)) + { + UtilAction.velocity(player, new Vector(Math.random() - 0.5, Math.random() * 0.2, Math.random() - 0.5), + Math.random() * 1 + 1, false, 0, 0.1 + Math.random() * 0.2, 2, true); + } + } + + for (Block block : UtilBlock.getInRadius(player.getLocation(), 5).keySet()) + { + if (Math.random() < 0.98) + continue; + + if (!UtilBlock.solid(block)) + continue; + + if (!UtilBlock.airFoliage(block.getRelative(BlockFace.UP))) + continue; + + player.playEffect(block.getLocation(), Effect.STEP_SOUND, block.getType()); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemEarthquake.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemEarthquake.java new file mode 100644 index 000000000..ae4563a0a --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemEarthquake.java @@ -0,0 +1,168 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Entity; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilServer; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; + +public class GolemEarthquake extends BossAbility +{ + private Location _center; + private float _range; + private int _tick; + private List _damaged = new ArrayList<>(); + private boolean _earthquake; + + public GolemEarthquake(GolemCreature creature) + { + super(creature); + _center = getLocation(); + } + + @Override + public boolean canMove() + { + return !UtilEnt.isGrounded(getEntity()) && _tick > 1; + } + + @Override + public Player getTarget() + { + return getTarget(7); + } + + @Override + public boolean hasFinished() + { + return _range > 19; + } + + @Override + public void setFinished() + { + } + + @Override + public void tick() + { + Entity entity = getEntity(); + + if (_tick == 0) + { + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 4, 0); + + entity.setVelocity(new Vector(0, 1, 0)); + } + else if (!_earthquake) + { + _earthquake = _tick > 10 && UtilEnt.isGrounded(entity); + } + + if (_earthquake) + { + _range += 0.7; + + for (float range = _range - 2; range <= _range; range++) + { + if (range <= 0) + { + continue; + } + + for (int x = -1; x <= 1; x++) + { + for (int z = -1; z <= 1; z++) + { + if ((x != 0) == (z != 0)) + { + continue; + } + + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.DIRT, 0), + _center.clone().add(x * range, 0.1, z * range), (x != 0) ? 0 : (range / 2), 0.1F, + (z != 0) ? 0 : (range / 2), 0, (int) (range * 4), UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + _center.getWorld().playSound(_center, Sound.DIG_STONE, 2, 0.8F); + + HashSet toDamage = new HashSet(); + + Location cornerA = _center.clone().add(-_range, -1, -_range); + Location cornerB = _center.clone().add(_range, 1, _range); + Location cornerA1 = _center.clone().add(-(_range - 1.5), -1, -(_range - 1.5)); + Location cornerB1 = _center.clone().add(_range - 1.5, 1, _range - 1.5); + + for (Player player : Bukkit.getOnlinePlayers()) + { + Location pLoc = player.getLocation(); + + if (_damaged.contains(player.getUniqueId())) + { + continue; + } + + if (!UtilAlg.inBoundingBox(pLoc, cornerA, cornerB)) + { + continue; + } + + if (UtilAlg.inBoundingBox(pLoc, cornerA1, cornerB1)) + { + continue; + } + + toDamage.add(player); + } + + for (Player player : toDamage) + { + _damaged.add(player.getUniqueId()); + + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) player, getEntity(), null, + DamageCause.CONTACT, 14 * getBoss().getDifficulty(), false, true, false, "Iron Wizard Earthquake", + "Iron Wizard Earthquake"); + + getBoss().getEvent().getCondition().Factory().Slow("Earthquake", (LivingEntity) player, getEntity(), 3, 1, false, + false, false, false); + + // Velocity + UtilAction.velocity(player, UtilAlg.getTrajectory2d(getLocation().toVector(), player.getLocation().toVector()), + 1.8, true, 0, 0.5, 0.5, true); + + // Condition + getBoss().getEvent().getCondition().Factory().Falling("Earthquake", player, getEntity(), 10, false, true); + } + } + + _tick++; + } + + @Override + public boolean inProgress() + { + return !_earthquake; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplodingAura.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplodingAura.java new file mode 100644 index 000000000..ff9fe2c67 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplodingAura.java @@ -0,0 +1,400 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.DataWatcher; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayOutAttachEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemExplodingAura extends BossAbility +{ + private Map _blocks = new HashMap<>(); + private Map _blocksLoc = new HashMap<>(); + private List _fallingBlocks = new ArrayList<>(); + private Map _blockMaterial = new HashMap<>(); + private int _tick; + + public GolemExplodingAura(GolemCreature creature) + { + super(creature); + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean hasFinished() + { + return _tick > 20 * 30 && _blocks.isEmpty() && _fallingBlocks.isEmpty(); + } + + @Override + public void setFinished() + { + for (FallingBlock block : _fallingBlocks) + { + block.remove(); + } + + int[] ids = new int[_blocks.size() * 2]; + + int i = 0; + + for (Entry id : _blocks.entrySet()) + { + ids[i] = id.getKey(); + ids[i + 1] = id.getValue(); + + i += 2; + } + + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ids); + + for (Player player : UtilServer.getPlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (_tick < 25 * 25 && getBoss().getHealth() > 30) + { + double angle = (2 * Math.PI) / UtilMath.random.nextDouble(); + double x = 1.7 * Math.cos(angle); + double z = 1.7 * Math.sin(angle); + + Location loc = getLocation().add(x, 1 + (UtilMath.random.nextDouble() * 1.6), z); + + loc.getWorld().playEffect(loc, Effect.STEP_SOUND, Material.DIRT.getId()); + + for (Player player : UtilPlayer.getNearby(getLocation(), 3, true)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getEntity(), null, DamageCause.CONTACT, + 6 * getBoss().getDifficulty(), true, true, false, "Iron Wizard Protection", "Iron Wizard Protection"); + UtilAction.velocity(player, UtilAlg.getTrajectory(getEntity(), player), 1, true, 0.3, 0, 0.3, false); + } + } + + if (_tick < 20 * 30) + { + int key = UtilEnt.getNewEntityId(); + int value = UtilEnt.getNewEntityId(); + + Location loc = null; + + for (int i = 0; i < 30; i++) + { + double angle = (2 * Math.PI) / UtilMath.random.nextDouble(); + double x = 1.7 * Math.cos(angle); + double z = 1.7 * Math.sin(angle); + + loc = getLocation().add(x, 1 + (UtilMath.random.nextDouble() * 1.6), z); + boolean found = false; + + for (Location l : _blocksLoc.values()) + { + if (l.distance(loc) < 0.3) + { + found = true; + break; + } + } + + if (found) + { + loc = null; + } + else + { + break; + } + } + + if (loc != null) + { + _blocks.put(key, value); + _blocksLoc.put(key, loc); + _blockMaterial.put(key, UtilMath.random.nextBoolean() ? Material.DIRT : Material.STONE); + + Packet[] packets = new Packet[3]; + + PacketPlayOutSpawnEntityLiving packet1 = new PacketPlayOutSpawnEntityLiving(); + + DataWatcher watcher = new DataWatcher(null); + watcher.a(0, (byte) 32, net.minecraft.server.v1_8_R3.Entity.META_ENTITYDATA, (byte) 0); + watcher.a(1, 0, net.minecraft.server.v1_8_R3.Entity.META_AIR, 0); + + packet1.a = key; + packet1.b = EntityType.SILVERFISH.getTypeId(); + packet1.c = (int) Math.floor(loc.getX() * 32); + packet1.d = (int) Math.floor((loc.getY() - 0.125) * 32); + packet1.e = (int) Math.floor(loc.getZ() * 32); + packet1.l = watcher; + + packets[0] = packet1; + + PacketPlayOutSpawnEntity packet2 = new PacketPlayOutSpawnEntity(((CraftEntity) getEntity()).getHandle(), 70, + _blockMaterial.get(key).getId()); + + packet2.a = value; + + packet2.b = (int) Math.floor(loc.getX() * 32); + packet2.c = (int) Math.floor(loc.getY() * 32); + packet2.d = (int) Math.floor(loc.getZ() * 32); + + packets[1] = packet2; + + PacketPlayOutAttachEntity packet3 = new PacketPlayOutAttachEntity(); + + packet3.b = value; + packet3.c = key; + + packets[2] = packet3; + + for (Player player : UtilPlayer.getNearby(getLocation(), 70)) + { + UtilPlayer.sendPacket(player, packets); + } + } + } + + if (_tick % 25 == 0) + { + for (int i = 0; i < 3; i++) + getLocation().getWorld().playSound(getLocation(), Sound.DIG_GRASS, 3, 2); + + for (int key : new ArrayList(_blocksLoc.keySet())) + { + + PacketPlayOutEntityDestroy destroyPacket = new PacketPlayOutEntityDestroy(new int[] + { + key, _blocks.remove(key) + }); + + for (Player player : UtilServer.getPlayers()) + { + UtilPlayer.sendPacket(player, destroyPacket); + } + + Location loc = _blocksLoc.remove(key); + + FallingBlock falling = loc.getWorld().spawnFallingBlock(loc, _blockMaterial.remove(key), (byte) 0); + + _fallingBlocks.add(falling); + + Vector vec = UtilAlg.getTrajectory(getLocation().add(0, 1, 0), loc); + + vec.setY(Math.max(0.05, vec.getY())); + + falling.setVelocity(vec); + + loc.getWorld().playEffect(loc, Effect.STEP_SOUND, Material.DIRT.getId()); + } + } + + _tick++; + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + Iterator fallingIterator = _fallingBlocks.iterator(); + + while (fallingIterator.hasNext()) + { + FallingBlock cur = fallingIterator.next(); + + if (cur.isDead() || !cur.isValid() || cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + fallingIterator.remove(); + + Block block = cur.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + // Expire + if (cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + cur.remove(); + continue; + } + + cur.remove(); + continue; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) cur).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, + nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) cur.getWorld()).getHandle().getEntities(((CraftEntity) cur).getHandle(), + ((CraftEntity) cur).getHandle().getBoundingBox().a(((CraftEntity) cur).getHandle().motX, + ((CraftEntity) cur).getHandle().motY, ((CraftEntity) cur).getHandle().motZ).grow(2, 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + { + continue; + } + + // Creative or Spec + if (ent instanceof Player) + { + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + { + continue; + } + } + + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + cur.getWorld().playEffect(victim.getEyeLocation().subtract(0, 0.5, 0), Effect.STEP_SOUND, cur.getBlockId()); + + { + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) victim, getEntity(), null, + DamageCause.CONTACT, 6 * getBoss().getDifficulty(), true, true, false, "Blocky Iron Wizard Aura", + "Blocky Iron Wizard Aura"); + } + + fallingIterator.remove(); + cur.remove(); + + Vector vec = UtilAlg.getTrajectory(getEntity(), victim); + vec.setY(0).normalize(); + + double strength = 1; + + if (!(victim instanceof Player) || !((Player) victim).isBlocking()) + { + strength = 1.3; + } + + UtilAction.velocity(victim, vec, strength, true, 0, 0.2, 1, true); + } + else if (finalObjectPosition != null) + { + Block block = cur.getWorld().getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt( + nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + fallingIterator.remove(); + cur.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + cur.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + @Override + public boolean inProgress() + { + return false; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplosiveBlock.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplosiveBlock.java new file mode 100644 index 000000000..fd76b19e0 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemExplosiveBlock.java @@ -0,0 +1,590 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Bukkit; +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Item; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.DataWatcher; +import net.minecraft.server.v1_8_R3.EntityIronGolem; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.Packet; +import net.minecraft.server.v1_8_R3.PacketPlayOutAttachEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntity; +import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemExplosiveBlock extends BossAbility +{ + private Map _blocksLocation = new HashMap<>(); + private Location _center; + private int _explosionsLeft; + private FallingBlock _fallingBlock; + private Map _fallingBlocks = new HashMap<>(); + private List _items = new ArrayList<>(); + private int _strength; + private Player _target; + private int _tick; + + public GolemExplosiveBlock(GolemCreature creature, int strength) + { + super(creature); + + _strength = strength; + _center = getLocation().add(0, 3, 0); + _target = getTarget(); + + if (_target != null) + { + UtilEnt.CreatureLook(getEntity(), _target); + } + } + + @Override + public boolean canMove() + { + return _fallingBlock != null; + } + + private int clamp(int value) + { + if (value < -127) + { + return -127; + } + + if (value > 127) + { + return 127; + } + + return value; + } + + @Override + public Player getTarget() + { + HashMap locs = new HashMap(); + + for (Player player : UtilServer.getPlayers()) + { + double dist = player.getLocation().distance(_center); + + if (dist < 30) + { + double score = (dist > 10 ? 30 - dist : 10); + + for (Player p : UtilServer.getPlayers()) + { + if (player.getLocation().distance(p.getLocation()) < 4) + { + score += 7; + } + } + + if (player.hasLineOfSight(getEntity())) + { + score += 10; + } + + locs.put(player, score); + } + } + + Player lowest = null; + + for (Entry entry : locs.entrySet()) + { + if (lowest == null || locs.get(lowest) > locs.get(entry.getKey())) + { + lowest = entry.getKey(); + } + } + + return lowest; + } + + @Override + public boolean hasFinished() + { + return _target == null || (_fallingBlock != null && !_fallingBlock.isValid() && _explosionsLeft == 0); + } + + @EventHandler + public void onDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().equals(getEntity())) + { + if (_tick >= 40 + (40 * _strength) && _tick <= 50 + (40 * _strength)) + { + event.SetCancelled("Iron Wizard charging bomb"); + } + + event.SetKnockback(false); + } + } + + public void onExplode(final Location loc) + { + for (int i = 0; i < _strength * 2; i++) + { + if (i == 0) + { + onSubExplode(loc); + } + else + { + _explosionsLeft++; + + Bukkit.getScheduler().scheduleSyncDelayedTask(UtilServer.getPlugin(), () -> + { + onSubExplode(loc); + _explosionsLeft--; + }, 2 * i); + } + } + } + + public void onSubExplode(Location loc) + { + for (int i = 0; i < 2; i++) + { + Location l = loc.clone().add(UtilMath.r(_strength * 4) - (_strength * 2), UtilMath.r(_strength * 2), + UtilMath.r(_strength * 4) - (_strength * 2)); + + UtilParticle.PlayParticle(ParticleType.LARGE_EXPLODE, l, _strength * 3, 1, _strength * 3, 0, _strength * 4, + ViewDist.LONG, UtilServer.getPlayers()); + } + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_fallingBlock == null) + { + return; + } + + if (_fallingBlock.isDead() + || !_fallingBlock.isValid() + || _fallingBlock.getTicksLived() > 400 + || !_fallingBlock.getWorld().isChunkLoaded(_fallingBlock.getLocation().getBlockX() >> 4, + _fallingBlock.getLocation().getBlockZ() >> 4)) + { + Block block = _fallingBlock.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + _fallingBlock.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, _fallingBlock.getBlockId()); + + // Expire + if (_fallingBlock.getTicksLived() > 400 + || !_fallingBlock.getWorld().isChunkLoaded(_fallingBlock.getLocation().getBlockX() >> 4, + _fallingBlock.getLocation().getBlockZ() >> 4)) + { + _fallingBlock.remove(); + return; + } + + _fallingBlock.remove(); + return; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) _fallingBlock).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) _fallingBlock.getWorld()).getHandle().getEntities( + ((CraftEntity) _fallingBlock).getHandle(), + ((CraftEntity) _fallingBlock).getHandle().getBoundingBox().a(((CraftEntity) _fallingBlock).getHandle().motX, + ((CraftEntity) _fallingBlock).getHandle().motY, ((CraftEntity) _fallingBlock).getHandle().motZ).grow(2, + 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + { + continue; + } + + // Creative or Spec + if (ent instanceof Player) + { + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + { + continue; + } + } + + // float f1 = (float)(nmsEntity.boundingBox.a() * 0.6f); + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + onExplode(victim.getEyeLocation()); + + _fallingBlock.remove(); + } + else if (finalObjectPosition != null) + { + Block block = _fallingBlock.getWorld() + .getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt(nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ + * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + onExplode(block.getLocation().add(0.5, 0.5, 0.5)); + + _fallingBlock.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + _fallingBlock.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + + @Override + public void setFinished() + { + int[] ids = new int[_fallingBlocks.size() * 2]; + + int index = 0; + + for (Entry entry : _fallingBlocks.entrySet()) + { + ids[index] = entry.getKey(); + ids[index + 1] = entry.getValue(); + index += 2; + } + + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ids); + + for (Player player : Bukkit.getOnlinePlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + + for (Item item : _items) + { + item.remove(); + } + + if (_fallingBlock != null) + { + _fallingBlock.remove(); + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + IronGolem entity = getEntity(); + + Iterator itel = _items.iterator(); + + while (itel.hasNext()) + { + Item item = itel.next(); + + Vector vec = item.getVelocity(); + Location loc = item.getLocation(); + + if (item.getTicksLived() > 100 || vec.getY() <= 0 || loc.distance(_center) > loc.add(vec).distance(_center) + || UtilEnt.isGrounded(item)) + { + itel.remove(); + } + } + + // This spawns a floating block + if (_tick >= 20 && _tick % 60 == 0 && _fallingBlocks.size() < _strength) + { + int id = UtilEnt.getNewEntityId(); + int id2 = UtilEnt.getNewEntityId(); + + _fallingBlocks.put(id, id2); + _blocksLocation.put(id, _center.toVector()); + + Packet[] packets = new Packet[3]; + + PacketPlayOutSpawnEntityLiving packet1 = new PacketPlayOutSpawnEntityLiving(); + + DataWatcher watcher = new DataWatcher(null); + watcher.a(0, (byte) 32, net.minecraft.server.v1_8_R3.Entity.META_ENTITYDATA, (byte) 0); + watcher.a(1, 0, net.minecraft.server.v1_8_R3.Entity.META_AIR, 0); + + packet1.a = id; + packet1.b = EntityType.SILVERFISH.getTypeId(); + packet1.c = (int) Math.floor(_center.getX() * 32); + packet1.d = (int) Math.floor((_center.getY() - 0.125) * 32); + packet1.e = (int) Math.floor(_center.getZ() * 32); + packet1.l = watcher; + + packets[0] = packet1; + + PacketPlayOutSpawnEntity packet2 = new PacketPlayOutSpawnEntity(((CraftEntity) entity).getHandle(), 70, + Material.DIRT.getId()); + + packet2.a = id2; + + packet2.b = (int) Math.floor(_center.getX() * 32); + packet2.c = (int) Math.floor(_center.getY() * 32); + packet2.d = (int) Math.floor(_center.getZ() * 32); + + packets[1] = packet2; + + PacketPlayOutAttachEntity packet3 = new PacketPlayOutAttachEntity(); + + packet3.b = id2; + packet3.c = id; + + packets[2] = packet3; + + for (Player player : UtilServer.getPlayers()) + { + if (player.getLocation().distance(_center) < 80) + { + UtilPlayer.sendPacket(player, packets); + } + } + } + + // This spawns a item that flies above the golem's head and disappears + if (UtilMath.r(6) == 0 && _tick < 40 + (_strength * 40)) + { + double angle = ((2 * Math.PI) / 30) * UtilMath.r(30); + double x = 5 * Math.cos(angle); + double z = 5 * Math.sin(angle); + Location loc = _center.clone().add(x, -3, z); + + Material mat = null; + + switch (UtilMath.r(3)) + { + case 0: + mat = Material.DIRT; + break; + case 1: + mat = Material.STONE; + break; + case 2: + mat = Material.COBBLESTONE; + break; + default: + break; + } + + Item item = loc.getWorld().dropItem(loc, new ItemBuilder(mat).setTitle(System.currentTimeMillis() + "").build()); + + item.setPickupDelay(999999); + + Vector vec = UtilAlg.getTrajectory(_center, item.getLocation()); + + vec.normalize().multiply(5); + + item.setVelocity(vec); + + // TODO Fix velocity + + _items.add(item); + } + + // 10 being when items no longer fly in, 0 being when its shot. + int ticksTillFired = (60 + (40 * _strength)) - _tick; + + if (ticksTillFired > 20) + { + int strength = (int) Math.floor(_tick / 20D); + + int nine = 8 - strength; + + if (_tick % nine == 0) + { + _center.getWorld().playSound(_center, Sound.DIG_GRASS, strength + 1, 1F); + } + } + else if (ticksTillFired < 0) + { + if (_tick % 3 == 0) + { + _center.getWorld().playSound(_fallingBlock.getLocation(), Sound.WOOD_CLICK, _strength + 1, 0.4F); + } + } + + // The location the falling blocks need to stick by + Vector blockCenter = _center.toVector(); + + if (ticksTillFired >= 0 && ticksTillFired <= 20) + { + Vector vec = entity.getLocation().add(entity.getLocation().getDirection().setY(0).normalize().multiply(1.2)) + .add(0, 1, 0).toVector(); + + blockCenter = UtilAlg.getTrajectory(_center.toVector(), blockCenter); + vec.multiply(ticksTillFired / 10D); + + _center.getWorld().playSound(_center, Sound.DIG_SNOW, _strength + 1, 0); + } + else if (_fallingBlock != null) + { + blockCenter = _fallingBlock.getLocation().add(0, 0.5, 0).toVector(); + } + + // Move the fake floating blocks + for (Entry entry : _fallingBlocks.entrySet()) + { + int id = entry.getKey(); + Vector vec = _blocksLocation.get(id); + + int x = clamp((int) ((blockCenter.getX() - vec.getX()) * 32) + (UtilMath.r(8) - 4)); + int y = clamp((int) ((blockCenter.getY() - vec.getY()) * 32) + (UtilMath.r(8) - 4)); + int z = clamp((int) ((blockCenter.getZ() - vec.getZ()) * 32) + (UtilMath.r(8) - 4)); + + vec.add(new Vector(x, y, z)); + + PacketPlayOutEntity.PacketPlayOutRelEntityMove packet = new PacketPlayOutEntity.PacketPlayOutRelEntityMove(); + + packet.a = id; + + packet.b = (byte) x; + packet.c = (byte) y; + packet.d = (byte) z; + + for (Player player : UtilServer.getPlayers()) + { + if (player.getLocation().distance(_center) < 70) + { + UtilPlayer.sendPacket(player, packet); + + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + vec.toLocation(_center.getWorld()), 0.7F, 0.7F, 0.7F, 0, 11, ViewDist.NORMAL, player); + } + } + } + + if (ticksTillFired == 0) + { + int id = _fallingBlocks.keySet().iterator().next(); + + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(new int[] + { + id, _fallingBlocks.get(id) + }); + + for (Player player : Bukkit.getOnlinePlayers()) + { + UtilPlayer.sendPacket(player, packet); + } + + _fallingBlocks.remove(id); + + _fallingBlock = _center.getWorld().spawnFallingBlock(_blocksLocation.get(id).toLocation(_center.getWorld()), + Material.STONE, (byte) 0); + + Vector vec1 = _fallingBlock.getLocation().toVector(); + Vector vec2 = _target.getLocation().toVector(); + + Vector vec = UtilAlg.calculateVelocity(vec1, vec2, (int) (vec1.distanceSquared(vec2) / 4)); + + _fallingBlock.setVelocity(vec); + + EntityIronGolem golem = ((CraftIronGolem) entity).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + } + + _tick++; + } + + @Override + public boolean inProgress() + { + return false; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemIronHook.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemIronHook.java new file mode 100644 index 000000000..18c94e4cd --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemIronHook.java @@ -0,0 +1,163 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Sound; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.itemstack.ItemStackFactory; +import mineplex.core.updater.UpdateType; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; + +public class GolemIronHook extends BossAbility +{ + private static final Integer MAX_TARGETS = 3; + private boolean _shot, _complete; + + private List _hooks = new ArrayList<>(); + + public GolemIronHook(GolemCreature creature) + { + super(creature); + _shot = false; + _complete = false; + } + + private int getPosition(Player toAdd, List ordered, Map distances) + { + int position = ordered.size(); + int index = 0; + for (Player player : ordered) + { + if (distances.get(player) < distances.get(toAdd)) + { + position = index; + } + index++; + } + + return position; + } + + private void shoot() + { + IronGolem wizard = getBoss().getEntity(); + List selections = new LinkedList<>(); + List targeted = new ArrayList<>(); + + Map near = UtilPlayer.getInRadius(wizard.getLocation(), 40D); + + for (Player nearby : near.keySet()) + { + if (nearby.getGameMode() == GameMode.CREATIVE || nearby.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + + if (selections.isEmpty()) + { + selections.add(nearby); + } + else + { + selections.add(getPosition(nearby, selections, near), nearby); + } + } + + for (int i = 0; i < MAX_TARGETS; i++) + { + if (i < selections.size()) + { + targeted.add(selections.get(i)); + } + } + + if (targeted.isEmpty()) + { + _complete = true; + setFinished(); + return; + } + + for (Player target : targeted) + { + Item item = wizard.getWorld().dropItem(wizard.getEyeLocation().add(UtilAlg.getTrajectory(wizard, target)), ItemStackFactory.Instance.CreateStack(131)); + UtilAction.velocity(item, UtilAlg.getTrajectory(wizard, target).normalize(), + 2, false, 0, 0.2, 20, false); + + getBoss().getEvent().getProjectileManager().AddThrow(item, getBoss().getEntity(), new IronHook(getBoss().getEvent()), -1, true, true, true, true, + Sound.FIRE_IGNITE, 1.4f, 0.8f, ParticleType.CRIT, UpdateType.TICK, 1f); + + item.getWorld().playSound(item.getLocation(), Sound.IRONGOLEM_THROW, 2f, 0.8f); + _hooks.add(item); + } + } + + @Override + public int getCooldown() + { + return 10; + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public boolean inProgress() + { + return false; + } + + @Override + public boolean hasFinished() + { + return _complete; + } + + @Override + public void setFinished() + { + for (Item hook : _hooks) + { + if (!hook.isDead() && hook.isValid()) + { + getBoss().getEvent().getProjectileManager().deleteThrown(hook); + hook.remove(); + } + } + + _hooks.clear(); + } + + @Override + public void tick() + { + if (_shot) + { + return; + } + shoot(); + _shot = true; + Bukkit.getScheduler().runTaskLater(UtilServer.getPlugin(), () -> + { + _complete = true; + setFinished(); + }, 2 * 20); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemMeleeAttack.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemMeleeAttack.java new file mode 100644 index 000000000..a045429dc --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemMeleeAttack.java @@ -0,0 +1,90 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import org.bukkit.Sound; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.EntityIronGolem; + +public class GolemMeleeAttack extends BossAbility +{ + private boolean _attacked; + + public GolemMeleeAttack(GolemCreature creature) + { + super(creature); + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public int getCooldown() + { + return 20; + } + + @Override + public Player getTarget() + { + return getTarget(4); + } + + @Override + public boolean hasFinished() + { + return _attacked; + } + + @Override + public void setFinished() {} + + @Override + public void tick() + { + _attacked = true; + + for (Player target : UtilPlayer.getNearby(getLocation(), 4, true)) + { + if (target.getVelocity().length() > 0.5) + { + continue; + } + + UtilEnt.CreatureLook(getEntity(), target); + + getBoss().getEvent().getDamageManager().NewDamageEvent(target, getEntity(), null, DamageCause.ENTITY_ATTACK, + 10 * getBoss().getDifficulty(), false, true, false, "Iron Wizard Melee Attack", "Iron Wizard Melee Attack"); + + Vector vec = getLocation().getDirection(); + vec.setY(0).normalize().setY(0.5).multiply(2.4); + + UtilAction.velocity(target, vec); + + getBoss().getEvent().getCondition().Factory().Falling("Iron Wizard Throw", target, getEntity(), 3, false, false); + + target.getWorld().playSound(target.getLocation(), Sound.IRONGOLEM_THROW, 3, 0.9F); + + EntityIronGolem golem = ((CraftIronGolem) getEntity()).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + } + } + + @Override + public boolean inProgress() + { + return _attacked; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRumble.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRumble.java new file mode 100644 index 000000000..d9cb7cc70 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRumble.java @@ -0,0 +1,238 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.Damageable; +import org.bukkit.entity.Entity; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.EntityIronGolem; + +/** + * Rumble is where the golem picks a target then starts playing a animation for a second where its obviously preparing to use it. + * Copy this from Wizards + */ +public class GolemRumble extends BossAbility +{ + private Location _loc; + private int _ticks; + private int _travelled; + private Vector _vec; + private int _width = 1; + private Location _target; + + public GolemRumble(GolemCreature creature) + { + super(creature); + + Player target = getTarget(); + + if (target != null) + { + _target = target.getLocation(); + + UtilEnt.CreatureLook(getEntity(), _target); + } + } + + @Override + public boolean canMove() + { + return _ticks >= 20; + } + + @Override + public boolean hasFinished() + { + return _travelled > 35; + } + + @Override + public void setFinished() {} + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (_ticks++ < 14) + { + IronGolem entity = getEntity(); + EntityIronGolem golem = ((CraftIronGolem) entity).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + + if (_ticks % 2 == 0) + { + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 3, 2F); + } + } + else if (_ticks % 2 == 0) + { + int oldWidth = _width; + + if ((_width <= 3 || _ticks % 4 == 0) && _width <= 6) + { + _width++; + } + + Location newLoc; + boolean validBlock = false; + List current = new ArrayList<>(); + + if (_vec == null) + { + _vec = _target.subtract(getLocation()).toVector().setY(0).normalize(); + _loc = getLocation().subtract(0, 1, 0).getBlock().getLocation().add(0, 0.99, 0); + newLoc = _loc; + current.add(_loc.getBlock()); + + validBlock = true; + } + else + { // Move rumble + newLoc = _loc.clone().add(_vec); + + // Check if the rumble needs to go up or drop a block or two + for (int y : new int[] {0, 1, -1}) + { + for (int a = 1; a <= 2; a++) + { + Block b = newLoc.clone().add(_vec.clone().multiply(a)).getBlock().getRelative(0, y, 0); + + if (UtilBlock.solid(b) && !UtilBlock.solid(b.getRelative(0, 1, 0))) + { + validBlock = true; + newLoc.add(0, y, 0); + + break; + } + } + + if (validBlock) + { + break; + } + } + + for (int width = -_width; width <= _width; width++) + { + if (Math.abs(width) <= oldWidth) + { + Block b = _loc.clone().add(UtilAlg.getRight(_vec).multiply(width)).getBlock(); + + if (!current.contains(b)) + { + current.add(b); + } + } + + if (validBlock) + { + Block b = newLoc.clone().add(UtilAlg.getRight(_vec).multiply(width)).getBlock(); + + if (!current.contains(b)) + { + current.add(b); + + b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getTypeId()); + } + } + } + } + + UtilEnt.CreatureLook(getEntity(), _loc); + + for (Entity entity : getEntity().getWorld().getEntities()) + { + if (entity instanceof Damageable && !UtilPlayer.isSpectator(entity) && entity != getEntity()) + { + Block b = entity.getLocation().getBlock(); + boolean canDamage = false; + + for (int y = -1; y <= 0; y++) + { + if (current.contains(b.getRelative(0, y, 0))) + { + canDamage = true; + break; + } + } + + if (!canDamage) + { + continue; + } + + if (canDamage(entity)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) entity, getEntity(), null, + DamageCause.CONTACT, 8 * getBoss().getDifficulty(), false, true, false, "Iron Wizard Rumble", + "Iron Wizard Rumble"); + } + + UtilAction.velocity(entity, _vec.clone(), 1.5, true, 0, 0.2, 1, true); + + if (entity instanceof Player) + { + getBoss().getEvent().getCondition().Factory().Slow("Rumble", (LivingEntity) entity, getEntity(), 3, 1, + false, false, false, false); + } + } + } + + if (_travelled++ > 35 || !validBlock) + { + _travelled = 100; + } + + _loc = newLoc; + } + } + + public Player getTarget() + { + Player target = null; + double dist = 0; + + for (Player player : UtilPlayer.getNearby(getLocation(), 30, true)) + { + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + double d = player.getLocation().distance(getLocation()); + + if (d > 2 && (target == null || dist > d)) + { + target = player; + dist = d; + } + } + + return target; + } + + @Override + public boolean inProgress() + { + return _ticks < 14; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRupture.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRupture.java new file mode 100644 index 000000000..2ecf4c46b --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemRupture.java @@ -0,0 +1,367 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftIronGolem; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Item; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.inventory.InventoryPickupItemEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import mineplex.core.common.Pair; +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.EntityIronGolem; + +public class GolemRupture extends BossAbility +{ + private List> _ruptures = new ArrayList<>(); + private Map _ruptureTime = new HashMap<>(); + private List _targetted = new ArrayList<>(); + private int _rupturesLeft; + private int _tick; + private List _items = new ArrayList<>(); + private int _ticksFinished; + + public GolemRupture(GolemCreature creature) + { + super(creature); + + if (creature.getHealthPercent() > 0.75) + { + _rupturesLeft = 2; + } + else if (creature.getHealthPercent() > 0.5) + { + _rupturesLeft = 5; + } + else + { + _rupturesLeft = 10; + } + } + + @Override + public boolean canMove() + { + return false; + } + + @EventHandler + public void HopperPickup(InventoryPickupItemEvent event) + { + if (_items.contains(event.getItem())) + { + event.setCancelled(true); + } + } + + @SuppressWarnings("deprecation") + @EventHandler + public void ItemDestroy(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_items.isEmpty()) + { + return; + } + + Iterator itemIterator = _items.iterator(); + + while (itemIterator.hasNext()) + { + Item item = itemIterator.next(); + + if (item.isDead() || !item.isValid()) + { + item.remove(); + itemIterator.remove(); + } + else if (UtilEnt.isGrounded(item) || item.getTicksLived() > 60) + { + item.getWorld().playEffect(item.getLocation(), Effect.STEP_SOUND, item.getItemStack().getTypeId()); + item.remove(); + itemIterator.remove(); + } + } + } + + @Override + public boolean inProgress() + { + return false; + } + + @Override + public boolean hasFinished() + { + return _rupturesLeft <= 0 && _ruptures.isEmpty() && --_ticksFinished <= 0; + } + + @Override + public void setFinished() + { + for (Item item : _items) + { + item.remove(); + } + } + + @Override + public void tick() + { + Iterator> itel = _ruptures.iterator(); + + while (itel.hasNext()) + { + Pair pair = itel.next(); + + if (pair.getLeft().distance(pair.getRight()) > 0) + { + Vector vec = pair.getRight().toVector().subtract(pair.getLeft().toVector()); + + if (vec.length() > 1) + { + vec = vec.normalize(); + } + + pair.getLeft().add(vec); + } + + if (pair.getLeft().distance(pair.getRight()) < 0.1) + { + if (!_ruptureTime.containsKey(pair.getLeft())) + { + _ruptureTime.put(pair.getLeft(), System.currentTimeMillis()); + } + else if (UtilTime.elapsed(_ruptureTime.get(pair.getLeft()), 150)) + { + itel.remove(); + + explodeRupture(pair.getLeft()); + } + } + } + + if (_tick % 10 == 0 && _rupturesLeft > 0) + { + _rupturesLeft--; + + Location loc = getLocation().add(UtilMath.random.nextFloat() - 0.5, 0, UtilMath.random.nextFloat() - 0.5); + + loc.setY(loc.getBlockY()); + + for (int y = 0; y > -3; y--) + { + if (!UtilBlock.airFoliage(loc.getBlock().getRelative(0, y, 0))) + { + loc.setY(loc.getY() + y); + break; + } + } + + Player player = getTarget(); + + if (player != null) + { + _targetted.add(player.getName()); + + Location target = player.getLocation(); + target.setY(loc.getY()); + + _ruptures.add(Pair.create(loc, target)); + + UtilEnt.CreatureLook(getEntity(), player.getLocation()); + + EntityIronGolem golem = ((CraftIronGolem) getEntity()).getHandle(); + + golem.world.broadcastEntityEffect(golem, (byte) 4); + } + else + { + _rupturesLeft = 0; + } + } + + for (Pair pair : _ruptures) + { + pair.getLeft().getWorld().playSound(pair.getLeft(), Sound.DIG_GRAVEL, 2.5F, 0.9F); + + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.DIRT, 0), + pair.getLeft().clone().add(0, 1.1, 0), 1F, 0, 1F, 0, 70, ViewDist.NORMAL, UtilServer.getPlayers()); + } + } + + _tick++; + } + + @Override + public Player getTarget() + { + Player target = null; + double dist = 0; + + for (Player player : UtilPlayer.getNearby(getLocation(), 30, true)) + { + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + if (_targetted.contains(player.getName())) + { + continue; + } + + double d = player.getLocation().distance(getLocation()); + + if (d < 7) + { + continue; + } + + boolean valid = true; + + for (Pair loc : _ruptures) + { + if (loc.getRight().distance(player.getLocation()) < 1.5) + { + valid = false; + break; + } + } + + if (!valid) + { + continue; + } + + if (target == null || dist > d) + { + target = player; + dist = d; + } + } + + return target; + } + + @SuppressWarnings("deprecation") + private void explodeRupture(Location loc) + { + loc.add(0, 1.1, 0); + loc.setX(loc.getBlockX() + 0.5); + loc.setZ(loc.getBlockZ() + 0.5); + + // Fling + HashMap targets = UtilEnt.getInRadius(loc, 3.5); + for (LivingEntity cur : targets.keySet()) + { + // Velocity + UtilAction.velocity(cur, + UtilAlg.getTrajectory2d(loc.toVector().add(new Vector(0.5, 0, 0.5)), cur.getLocation().toVector()), + 0.8 + 0.8 * targets.get(cur), true, 0, 0.4 + 1.0 * targets.get(cur), 1.4, true); + + // Condition + getBoss().getEvent().getCondition().Factory().Falling("Rupture", cur, getEntity(), 10, false, true); + + // Damage Event + getBoss().getEvent().getDamageManager().NewDamageEvent(cur, getEntity(), null, DamageCause.CUSTOM, + 8 * getBoss().getDifficulty(), false, true, false, "Iron Wizard", "Rupture"); + } + + List blocks = new ArrayList<>(); + + for (int x = -3; x <= 3; x++) + { + for (int z = -3; z <= 3; z++) + { + for (int y = 0; y <= 1; y++) + { + for (int i = 0; i < 2; i++) + { + if (Math.sqrt(x * x + z * z + y * y) <= 3) + { + blocks.add(loc.clone().add(x, y, z).getBlock()); + } + } + } + } + } + + Collections.shuffle(blocks); + + // Blocks + int done = 0; + Iterator itel = blocks.iterator(); + + while (done < 30 && itel.hasNext()) + { + Block block = itel.next(); + + Vector vec = new Vector(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5).normalize(); + + if (!UtilBlock.airFoliage(block)) + { + continue; + } + + // Add Directional + vec.add(UtilAlg.getTrajectory(loc.getBlock().getLocation(), block.getLocation().add(0.5, 0, 0.5))); + + // Add Up + vec.add(new Vector(0, 1.6, 0)); + + vec.normalize(); + + // Scale + vec.multiply(0.1 + 0.3 * Math.random() + 0.6); + + // Block! + Item item = loc.getWorld().dropItem(block.getLocation().add(0.5, 0, 0.5), new ItemStack(Material.DIRT, 0)); + item.setVelocity(vec); + item.setPickupDelay(50000); + _items.add(item); + + // Effect + loc.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, Material.STONE.getId()); + + done++; + } + + _ticksFinished = 20; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSlam.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSlam.java new file mode 100644 index 000000000..c4a5a01ab --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSlam.java @@ -0,0 +1,271 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.Block; +import org.bukkit.entity.Entity; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Item; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.inventory.InventoryPickupItemEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; + +public class GolemSlam extends BossAbility +{ + private List _items = new ArrayList<>(); + private int _ticksFinished; + private int _stage; + private Vector _target; + private int _ticksJumped; + + public GolemSlam(GolemCreature creature) + { + super(creature); + + Player target = getTarget(); + + if (target != null) + { + _target = UtilAlg.calculateVelocity(getLocation().toVector(), + target.getLocation().toVector().setY(getLocation().getY()), 2, getEntity()); + } + } + + @Override + public boolean canMove() + { + return !UtilEnt.isGrounded(getEntity()) && _stage == 1; + } + + @Override + public boolean hasFinished() + { + return _stage == 2 && --_ticksFinished <= 0; + } + + @Override + public void setFinished() + { + for (Item item : _items) + { + item.remove(); + } + } + + @Override + public void tick() + { + Entity entity = getEntity(); + + if (_stage == 0) + { + UtilEnt.CreatureLook(getEntity(), getLocation().add(_target)); + + entity.getWorld().playSound(entity.getLocation(), Sound.IRONGOLEM_THROW, 4, 0); + + entity.setVelocity(_target); + _stage++; + } + else if (_stage == 1) + { + _ticksJumped++; + + if (_ticksJumped > 4 && getLocation().subtract(0, 0.2, 0).getBlock().getType() != Material.AIR) + { + explodeRupture(getLocation()); + + _stage = 2; + } + } + } + + @EventHandler + public void HopperPickup(InventoryPickupItemEvent event) + { + if (_items.contains(event.getItem())) + { + event.setCancelled(true); + } + } + + @SuppressWarnings("deprecation") + @EventHandler + public void ItemDestroy(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_items.isEmpty()) + { + return; + } + + Iterator itemIterator = _items.iterator(); + + while (itemIterator.hasNext()) + { + Item item = itemIterator.next(); + + if (item.isDead() || !item.isValid()) + { + item.remove(); + itemIterator.remove(); + } + else if (UtilEnt.isGrounded(item) || item.getTicksLived() > 60) + { + item.getWorld().playEffect(item.getLocation(), Effect.STEP_SOUND, item.getItemStack().getTypeId()); + item.remove(); + itemIterator.remove(); + } + } + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public Player getTarget() + { + Player target = null; + double dist = 0; + + for (Player player : UtilPlayer.getNearby(getLocation(), 30, true)) + { + if (!player.hasLineOfSight(getEntity())) + { + continue; + } + + double d = player.getLocation().distance(getLocation()); + + if (d < 10) + { + continue; + } + + if (target == null || dist > d) + { + target = player; + dist = d; + } + } + + return target; + } + + @SuppressWarnings("deprecation") + private void explodeRupture(Location loc) + { + loc.add(0, 1.1, 0); + loc.setX(loc.getBlockX() + 0.5); + loc.setZ(loc.getBlockZ() + 0.5); + + // Fling + Map targets = UtilEnt.getInRadius(loc, 3.5); + for (LivingEntity cur : targets.keySet()) + { + if (cur.equals(getEntity())) + { + continue; + } + + // Velocity + UtilAction.velocity(cur, + UtilAlg.getTrajectory2d(loc.toVector().add(new Vector(0.5, 0, 0.5)), cur.getLocation().toVector()), + 0.8 + 0.8 * targets.get(cur), true, 0, 0.4 + 1.0 * targets.get(cur), 1.4, true); + + // Condition + getBoss().getEvent().getCondition().Factory().Falling("Rupture", cur, getEntity(), 10, false, true); + + // Damage Event + getBoss().getEvent().getDamageManager().NewDamageEvent(cur, getEntity(), null, DamageCause.CUSTOM, + 8 * getBoss().getDifficulty(), false, true, false, "Iron Wizard", "Rupture"); + } + + List blocks = new ArrayList(); + + for (int x = -3; x <= 3; x++) + { + for (int z = -3; z <= 3; z++) + { + for (int y = 0; y <= 1; y++) + { + for (int i = 0; i < 2; i++) + { + if (Math.sqrt(x * x + z * z + y * y) <= 3) + { + blocks.add(loc.clone().add(x, y, z).getBlock()); + } + } + } + } + } + + Collections.shuffle(blocks); + + // Blocks + int done = 0; + Iterator itel = blocks.iterator(); + + while (done < 30 && itel.hasNext()) + { + Block block = itel.next(); + + Vector vec = new Vector(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5).normalize(); + + if (!UtilBlock.airFoliage(block)) + continue; + + // Add Directional + vec.add(UtilAlg.getTrajectory(loc.getBlock().getLocation(), block.getLocation().add(0.5, 0, 0.5))); + + // Add Up + vec.add(new Vector(0, 1.6, 0)); + + vec.normalize(); + + // Scale + vec.multiply(0.1 + 0.3 * Math.random() + 0.6); + + // Block! + Item item = loc.getWorld().dropItem(block.getLocation().add(0.5, 0, 0.5), new ItemStack(Material.DIRT, 0)); + item.setVelocity(vec); + item.setPickupDelay(50000); + _items.add(item); + + // Effect + loc.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, Material.DIRT.getId()); + + done++; + } + + _ticksFinished = 20; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSpike.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSpike.java new file mode 100644 index 000000000..4f5dad106 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemSpike.java @@ -0,0 +1,104 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.bukkit.Sound; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; + +public class GolemSpike extends BossAbility +{ + private static final int SPIKE_HEIGHT = 2; + private static final long ATTACK_DURATION = 1000 + (500 * SPIKE_HEIGHT * 2); + private static final long SPIKE_REMAIN = 1000; + private long _start; + private List _spikes; + + public GolemSpike(GolemCreature creature) + { + super(creature); + _start = System.currentTimeMillis(); + _spikes = new ArrayList<>(); + } + + @Override + public int getCooldown() + { + return 15; + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public boolean hasFinished() + { + return UtilTime.elapsed(_start, ATTACK_DURATION) && _spikes.isEmpty(); + } + + @Override + public void setFinished() + { + _start = System.currentTimeMillis() - ATTACK_DURATION; + for (GroundSpike spike : _spikes) + { + spike.finish(); + } + _spikes.clear(); + } + + @Override + public void tick() + { + if (_spikes.isEmpty()) + { + for (Player player : UtilPlayer.getInRadius(getLocation(), 20).keySet()) + { + if (UtilEnt.isGrounded(player)) + { + player.playSound(player.getLocation(), Sound.STEP_STONE, 0.2f, 0.2f); + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getBoss().getEntity(), null, DamageCause.CUSTOM, 5 * getBoss().getDifficulty(), false, false, false, getBoss().getEntity().getName(), "Stone Spike"); + player.teleport(player.getLocation().add(0, SPIKE_HEIGHT, 0)); + UtilAction.velocity(player, player.getLocation().toVector().normalize().add(new Vector(0, 0.02, 0)).normalize()); + _spikes.add(new GroundSpike(player.getLocation().getBlock(), player.getLocation().getBlock().getRelative(0, -1, 0).getType(), new Random().nextInt(SPIKE_HEIGHT) + 2, SPIKE_REMAIN)); + } + } + } + else + { + List toRemove = new ArrayList<>(); + for (GroundSpike spike : _spikes) + { + spike.tick(); + if (spike.isFinished()) + { + toRemove.add(spike); + } + } + for (GroundSpike remove : toRemove) + { + _spikes.remove(remove); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemWallExplode.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemWallExplode.java new file mode 100644 index 000000000..aaebec6d4 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GolemWallExplode.java @@ -0,0 +1,419 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Effect; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilShapes; +import mineplex.core.common.util.UtilTime; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.ironwizard.GolemCreature; +import net.minecraft.server.v1_8_R3.AxisAlignedBB; +import net.minecraft.server.v1_8_R3.MathHelper; +import net.minecraft.server.v1_8_R3.MovingObjectPosition; +import net.minecraft.server.v1_8_R3.Vec3D; + +public class GolemWallExplode extends BossAbility +{ + private Map> _blockWalls = new HashMap<>(); + private List _dontTarget = new ArrayList<>(); + private List _fallingBlocks = new ArrayList<>(); + private int _maxTimes = UtilMath.r(2) + 1; + private int _tick; + private int _timesDone; + private Map _wallTimers = new HashMap<>(); + + public GolemWallExplode(GolemCreature creature) + { + super(creature); + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public int getCooldown() + { + return 20; + } + + private float getMod(int div) + { + return UtilMath.random.nextFloat() / div; + } + + @Override + public Player getTarget() + { + for (Player player : UtilPlayer.getNearby(getLocation(), 15, true)) + { + if (_dontTarget.contains(player.getName())) + { + continue; + } + + if (player.getLocation().distance(getLocation()) <= 4) + { + continue; + } + + return player; + } + + return null; + } + + @Override + public boolean hasFinished() + { + return _wallTimers.isEmpty() && _fallingBlocks.isEmpty() && _timesDone >= _maxTimes; + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + Iterator fallingIterator = _fallingBlocks.iterator(); + + while (fallingIterator.hasNext()) + { + FallingBlock cur = fallingIterator.next(); + + if (cur.isDead() || !cur.isValid() || cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + fallingIterator.remove(); + + Block block = cur.getLocation().getBlock(); + block.setTypeIdAndData(0, (byte) 0, true); + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + + // Expire + if (cur.getTicksLived() > 400 + || !cur.getWorld().isChunkLoaded(cur.getLocation().getBlockX() >> 4, cur.getLocation().getBlockZ() >> 4)) + { + cur.remove(); + continue; + } + + cur.remove(); + continue; + } + + double distanceToEntity = 0.0D; + LivingEntity victim = null; + + net.minecraft.server.v1_8_R3.Entity nmsEntity = ((CraftEntity) cur).getHandle(); + Vec3D vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + Vec3D vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, + nmsEntity.locZ + nmsEntity.motZ); + + MovingObjectPosition finalObjectPosition = nmsEntity.world.rayTrace(vec3d, vec3d1, false, true, false); + vec3d = new Vec3D(nmsEntity.locX, nmsEntity.locY, nmsEntity.locZ); + vec3d1 = new Vec3D(nmsEntity.locX + nmsEntity.motX, nmsEntity.locY + nmsEntity.motY, nmsEntity.locZ + nmsEntity.motZ); + + if (finalObjectPosition != null) + { + vec3d1 = new Vec3D(finalObjectPosition.pos.a, finalObjectPosition.pos.b, finalObjectPosition.pos.c); + } + + for (Object entity : ((CraftWorld) cur.getWorld()).getHandle().getEntities(((CraftEntity) cur).getHandle(), + ((CraftEntity) cur).getHandle().getBoundingBox().a(((CraftEntity) cur).getHandle().motX, + ((CraftEntity) cur).getHandle().motY, ((CraftEntity) cur).getHandle().motZ).grow(2, 2, 2))) + { + Entity bukkitEntity = ((net.minecraft.server.v1_8_R3.Entity) entity).getBukkitEntity(); + + if (bukkitEntity instanceof LivingEntity) + { + LivingEntity ent = (LivingEntity) bukkitEntity; + + // Avoid Self + if (ent.equals(getEntity())) + continue; + + // Creative or Spec + if (ent instanceof Player) + if (((Player) ent).getGameMode() == GameMode.CREATIVE || UtilPlayer.isSpectator(ent)) + continue; + + // float f1 = (float)(nmsEntity.boundingBox.a() * 0.6f); + AxisAlignedBB axisalignedbb1 = ((CraftEntity) ent).getHandle().getBoundingBox().grow(1F, 1F, 1F); + MovingObjectPosition entityCollisionPosition = axisalignedbb1.a(vec3d, vec3d1); + + if (entityCollisionPosition != null) + { + double d1 = vec3d.distanceSquared(entityCollisionPosition.pos); + if ((d1 < distanceToEntity) || (distanceToEntity == 0.0D)) + { + victim = ent; + distanceToEntity = d1; + } + } + } + } + + if (victim != null) + { + cur.getWorld().playEffect(victim.getEyeLocation().subtract(0, 0.5, 0), Effect.STEP_SOUND, cur.getBlockId()); + + if (canDamage(victim)) + { + getBoss().getEvent().getDamageManager().NewDamageEvent((LivingEntity) victim, getEntity(), null, + DamageCause.CONTACT, 10 * getBoss().getDifficulty(), true, true, false, "Iron Wizard Wall Explosion", + "Iron Wizard Wall Explosion"); + } + + cur.remove(); + fallingIterator.remove(); + + Vector vec = cur.getVelocity(); + + UtilAction.velocity(victim, vec, 1.5, true, 0, 0.2, 1, true); + } + else if (finalObjectPosition != null) + { + Block block = cur.getWorld().getBlockAt(((int) finalObjectPosition.pos.a), ((int) finalObjectPosition.pos.b), ((int) finalObjectPosition.pos.c)); + + if (!UtilBlock.airFoliage(block) && !block.isLiquid()) + { + nmsEntity.motX = ((float) (finalObjectPosition.pos.a - nmsEntity.locX)); + nmsEntity.motY = ((float) (finalObjectPosition.pos.b - nmsEntity.locY)); + nmsEntity.motZ = ((float) (finalObjectPosition.pos.c - nmsEntity.locZ)); + float f2 = MathHelper.sqrt( + nmsEntity.motX * nmsEntity.motX + nmsEntity.motY * nmsEntity.motY + nmsEntity.motZ * nmsEntity.motZ); + nmsEntity.locX -= nmsEntity.motX / f2 * 0.0500000007450581D; + nmsEntity.locY -= nmsEntity.motY / f2 * 0.0500000007450581D; + nmsEntity.locZ -= nmsEntity.motZ / f2 * 0.0500000007450581D; + + cur.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, cur.getBlockId()); + cur.remove(); + fallingIterator.remove(); + } + } + else + { + UtilParticle.PlayParticle(ParticleType.BLOCK_DUST.getParticle(Material.STONE, 0), + cur.getLocation().add(0, 0.5, 0), 0.3F, 0.3F, 0.3F, 0, 2, UtilParticle.ViewDist.NORMAL, + UtilServer.getPlayers()); + } + } + } + + @Override + public void setFinished() + { + for (FallingBlock block : _fallingBlocks) + { + block.remove(); + } + + for (List list : _blockWalls.values()) + { + for (Block b : list) + { + b.setType(Material.AIR); + } + } + } + + @SuppressWarnings("deprecation") + @Override + public void tick() + { + if (_tick++ % 30 == 0 && _timesDone < _maxTimes) + { + _dontTarget.clear(); + + _timesDone++; + + for (int i = 0; i < 10; i++) + { + Player target = getTarget(); + + if (target == null) + { + if (_dontTarget.isEmpty()) + { + _timesDone = _maxTimes; + } + } + else + { + _dontTarget.add(target.getName()); + + UtilEnt.CreatureLook(getEntity(), target); + + BlockFace face = UtilShapes.getFacing(getLocation().getYaw()); + + if (_wallTimers.containsKey(face)) + { + continue; + } + + ArrayList blocks = new ArrayList(); + + Location loc = getLocation().getBlock().getLocation().add(0.5, 0, 0.5); + + int mul = (face.getModX() != 0 && face.getModZ() != 0) ? 2 : 3; + + loc.add(face.getModX() * mul, 0, face.getModZ() * mul); + + Block b = loc.getBlock(); + + BlockFace sideFace = UtilShapes.getSideBlockFaces(face, true)[0]; + boolean invalid = false; + + for (int mult = -3; mult <= 3; mult++) + { + Block block = b; + + if (Math.abs(mult) < 3) + { + block = block.getRelative(face); + } + + block = block.getRelative(sideFace, mult); + + if (Math.abs(mult) == 3 && face.getModX() != 0 && face.getModZ() != 0) + { + block = block.getRelative(UtilShapes.getSideBlockFaces(face, false)[mult < 0 ? 0 : 1]); + } + + if (!UtilAlg.HasSight(getLocation(), block.getLocation())) + { + invalid = true; + break; + } + + Block under = block.getRelative(0, -1, 0); + + if (!UtilBlock.solid(under)) + { + continue; + } + + for (int y = 0; y <= 1; y++) + { + block = block.getRelative(0, y, 0); + + if (block.getType() != Material.AIR) + { + invalid = true; + break; + } + + blocks.add(block); + } + + if (invalid) + { + break; + } + } + + if (invalid) + { + continue; + } + + for (Block block : blocks) + { + block.setType(block.getWorld().getBlockAt(block.getX(), b.getY() - 1, block.getZ()).getType()); + block.getWorld().playEffect(block.getLocation(), Effect.STEP_SOUND, block.getTypeId()); + } + + _blockWalls.put(face, blocks); + _wallTimers.put(face, System.currentTimeMillis()); + break; + } + } + } + + Iterator>> itel = _blockWalls.entrySet().iterator(); + boolean doExplode = false; + + while (itel.hasNext()) + { + Entry> entry = itel.next(); + BlockFace face = entry.getKey(); + + if (UtilTime.elapsed(_wallTimers.get(face), 1000)) + { + doExplode = true; + itel.remove(); + _wallTimers.remove(face); + + for (Block b : entry.getValue()) + { + FallingBlock block = getEntity().getWorld().spawnFallingBlock(b.getLocation().add(0.5, 0, 0.5), b.getType(), + (byte) 0); + + block.setDropItem(false); + + int index = entry.getValue().indexOf(b); + + BlockFace f = index == 8 || index == 9 ? BlockFace.SELF + : UtilShapes.getSideBlockFaces(face, true)[index > 6 ? 0 : 1]; + + block.setVelocity(new Vector((face.getModX() * 0.6) + (f.getModX() * (0.05 + getMod(10))), 0.2 + getMod(15), + (face.getModZ() * 0.6) + (f.getModZ() * (0.05 + getMod(10))))); + + _fallingBlocks.add(block); + + b.getWorld().playEffect(b.getLocation(), Effect.STEP_SOUND, b.getTypeId()); + b.setType(Material.AIR); + } + } + } + + if (doExplode) + { + onUpdate(new UpdateEvent(UpdateType.TICK)); + } + } + + @Override + public boolean inProgress() + { + return false; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GroundSpike.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GroundSpike.java new file mode 100644 index 000000000..40d2989e3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/GroundSpike.java @@ -0,0 +1,122 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import java.util.LinkedList; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; + +public class GroundSpike +{ + private Block _initial; + private Material _type; + private int _max, _height; + private long _lastTick, _remain; + private LinkedList _blocks; + private boolean _shrinking, _finished; + + public GroundSpike(Block first, Material type, int maxHeight, long remainDuration) + { + _initial = first; + _type = type; + _height = 0; + _max = maxHeight; + _remain = remainDuration; + _lastTick = System.currentTimeMillis(); + _blocks = new LinkedList<>(); + _shrinking = false; + _finished = false; + } + + @SuppressWarnings("deprecation") + private void raise() + { + if ((_height + 1) < _max) + { + _lastTick = System.currentTimeMillis(); + Block b = _initial.getRelative(0, _height, 0); + for (Player player : UtilServer.getPlayers()) + { + player.sendBlockChange(b.getLocation(), _type, (byte)0); + } + _blocks.add(b); + _height++; + } + else + { + if (UtilTime.elapsed(_lastTick, _remain)) + { + _shrinking = true; + lower(); + } + } + } + + @SuppressWarnings("deprecation") + private void lower() + { + _height = Math.min(_blocks.size() - 1, _height); + if ((_height - 1) >= 0) + { + _lastTick = System.currentTimeMillis(); + for (Player player : UtilServer.getPlayers()) + { + player.sendBlockChange(_blocks.get(_height).getLocation(), Material.AIR, (byte)0); + } + _blocks.remove(_height); + _height--; + } + else + { + finish(); + } + } + + public boolean isFinished() + { + if (!_blocks.isEmpty()) + { + return false; + } + + return _finished; + } + + @SuppressWarnings("deprecation") + public void finish() + { + _finished = true; + for (Block block : _blocks) + { + for (Player player : UtilServer.getPlayers()) + { + player.sendBlockChange(block.getLocation(), Material.AIR, (byte)0); + } + } + _blocks.clear(); + } + + public void tick() + { + if (isFinished()) + { + return; + } + if (!UtilTime.elapsed(_lastTick, 500)) + { + return; + } + + if (_shrinking) + { + lower(); + } + else + { + raise(); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/IronHook.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/IronHook.java new file mode 100644 index 000000000..73ddfce16 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/ironwizard/abilities/IronHook.java @@ -0,0 +1,54 @@ +package mineplex.game.clans.clans.worldevent.boss.ironwizard.abilities; + +import org.bukkit.block.Block; +import org.bukkit.entity.IronGolem; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.projectile.IThrown; +import mineplex.core.projectile.ProjectileUser; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; + +public class IronHook implements IThrown +{ + private WorldEvent _host; + + public IronHook(WorldEvent event) + { + _host = event; + } + + @Override + public void Collide(LivingEntity target, Block block, ProjectileUser data) + { + data.getThrown().remove(); + + if (!(data.getThrower() instanceof IronGolem)) + return; + + IronGolem wizard = (IronGolem)data.getThrower(); + + if (target == null) + return; + + UtilAction.velocity(target, UtilAlg.getTrajectory(target.getLocation(), wizard.getLocation()), 5, false, 0, 0.7, 1.2, true); + + _host.getCondition().Factory().Falling("Iron Hook", target, wizard, 10, false, true); + + _host.getDamageManager().NewDamageEvent(target, wizard, null, DamageCause.CUSTOM, 5, false, true, false, wizard.getName(), "Iron Hook"); + } + + @Override + public void Idle(ProjectileUser data) + { + data.getThrown().remove(); + } + + @Override + public void Expire(ProjectileUser data) + { + data.getThrown().remove(); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonBoss.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonBoss.java new file mode 100644 index 000000000..dd004675e --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonBoss.java @@ -0,0 +1,65 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking; + +import org.bukkit.Bukkit; +import org.bukkit.Location; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilServer; +import mineplex.game.clans.clans.worldevent.WorldEventManager; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.boss.BossWorldEvent; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.MinionType; + +public class SkeletonBoss extends BossWorldEvent +{ + protected boolean canMove = false; + + public SkeletonBoss(WorldEventManager manager) + { + super("Skeleton King", manager.getBossArenaLocationFinder().getSkeletonKingCenter(), 50, manager.getBossArenaLocationFinder().getSkeletonKingPads().getLeft(), manager.getBossArenaLocationFinder().getSkeletonKingPads().getRight(), manager.getDisguiseManager(), manager.getClans().getProjectile(), manager.getClans().getDamageManager(), manager.getBlockRestore(), manager.getClans().getCondition()); + } + + @Override + protected void customStart() + { + Bukkit.broadcastMessage(F.main(getName(), "The evils of the world have manifested in the form of the " + getName() + "! Become the champion of Light and destroy him!")); + spawnSkeletonKing(getCenterLocation()); + Bukkit.getScheduler().runTaskLater(UtilServer.getPlugin(), () -> + { + canMove = true; + }, 20 * 3); + } + + public EventCreature spawnMinion(MinionType type, Location location) + { + EventCreature minionCreature = type.getNewInstance(this, location); + if (minionCreature != null) + { + registerCreature(minionCreature); + } + return minionCreature; + } + + private SkeletonCreature spawnSkeletonKing(Location location) + { + SkeletonCreature kingCreature = new SkeletonCreature(this, location); + registerCreature(kingCreature); + setBossCreature(kingCreature); + return kingCreature; + } + + @Override + public String getDeathMessage() + { + return F.main(getName(), "The demonic " + getName() + " has been slain!"); + } + + @Override + protected void customTick() {} + + @Override + public void customCleanup(boolean onDisable) {} + + @Override + protected void customStop() {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonCreature.java new file mode 100644 index 000000000..be6ae17e4 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/SkeletonCreature.java @@ -0,0 +1,482 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.entity.Skeleton.SkeletonType; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities.SkeletonArcherShield; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities.SkeletonPassive; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities.SkeletonPulse; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities.SkeletonSmite; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities.SkeletonStrike; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities.SkeletonWraithSummon; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.UndeadArcherCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.UndeadWarriorCreature; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class SkeletonCreature extends EventCreature +{ + private List> _currentAbilities = new ArrayList<>(); + private SkeletonPassive _passive; + private int _lastAbility; + private Map, Long> _cooldowns = new HashMap<>(); + private LinkedList _wraithTriggers = new LinkedList<>(); + private List _movePoints = new ArrayList<>(); + private Location _movingTo; + private boolean _moving; + private long _lastMoved; + private long _lastUsedPassive; + public List Archers = new ArrayList<>(); + public List Warriors = new ArrayList<>(); + + public SkeletonCreature(SkeletonBoss boss, Location location) + { + super(boss, location, "Skeleton King", true, 2500, 30, true, Skeleton.class); + + spawnEntity(); + _passive = new SkeletonPassive(this); + _wraithTriggers.add(1500D); + _wraithTriggers.add(1000D); + _wraithTriggers.add(500D); + _wraithTriggers.add(100D); + getEntity().getWorld().setThunderDuration(10000000); + getEntity().getWorld().setThundering(true); + } + + @Override + protected void spawnCustom() + { + UtilEnt.vegetate(getEntity()); + getEntity().setSkeletonType(SkeletonType.WITHER); + getEntity().getEquipment().setItemInHand(new ItemStack(Material.RECORD_6)); //Meridian Scepter + getEntity().getEquipment().setItemInHandDropChance(0.f); + } + + @Override + public void dieCustom() + { + HandlerList.unregisterAll(_passive); + _passive = null; + endAbility(); + getEntity().getWorld().setThunderDuration(0); + getEntity().getWorld().setThundering(false); + } + + private void endAbility() + { + for (BossAbility ability : _currentAbilities) + { + ability.setFinished(); + HandlerList.unregisterAll(ability); + } + + _currentAbilities.clear(); + } + + @EventHandler + public void onTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_passive != null && ((SkeletonBoss)getEvent()).canMove) + { + if (UtilTime.elapsed(_lastUsedPassive, _passive.getCooldown() * 20) || _passive.isProgressing()) + { + _lastUsedPassive = System.currentTimeMillis(); + _passive.tick(); + } + } + + Iterator> itel = _currentAbilities.iterator(); + boolean canDoNew = _currentAbilities.size() < 3; + + while (itel.hasNext()) + { + BossAbility ability = itel.next(); + + if (ability.hasFinished()) + { + itel.remove(); + ability.setFinished(); + _lastAbility = 20;// _currentAbility.getCooldown(); + + HandlerList.unregisterAll(ability); + if (DEBUG_MODE) + { + System.out.print("Unregistered necromancer ability " + ability.getClass().getSimpleName()); + } + + _cooldowns.put(ability.getClass(), System.currentTimeMillis() + (ability.getCooldown() * 1000)); + } + else if (ability.inProgress()) + { + canDoNew = false; + _lastAbility = 20;// _currentAbility.getCooldown(); + } + } + + if (_lastAbility-- <= 0 && canDoNew && UtilBlock.solid(getEntity().getLocation().getBlock().getRelative(BlockFace.DOWN))) + { + Map>, Integer> weight = new HashMap<>(); + Map dist = new HashMap<>(); + + for (Player player : UtilPlayer.getNearby(getEntity().getLocation(), 50, true)) + { + if (player.hasLineOfSight(getEntity())) + { + dist.put(player, player.getLocation().distance(getEntity().getLocation())); + } + } + + if (!dist.isEmpty()) + { + {// Pulse & Strike + List players = getPlayers(dist, UtilMath.r(10) == 0 ? 25 : 20); + List near = getPlayers(dist, 5); + + if (!players.isEmpty()) + { + if (!near.isEmpty() && near.size() >= 4 && new Random().nextDouble() <= .45) + { + weight.put(SkeletonPulse.class, 999); + } + else + { + weight.put(SkeletonStrike.class, 6); + } + } + } + {// Smite + List players = getPlayers(dist, 15); + + if (!players.isEmpty()) + { + weight.put(SkeletonSmite.class, 6); + } + } + {//Archer Shield + List players = getPlayers(dist, 20); + double score = 0; + for (Player player : players) + { + score += (18 - dist.get(player)) / 2; + } + if (players.size() >= 4) + { + score += 17; + } + if (score > 0) + { + weight.put(SkeletonArcherShield.class, (int) Math.ceil(score)); + } + } + Double wraithUse = null; + for (Double test : _wraithTriggers) + { + if (wraithUse == null) + { + if (getHealth() <= test) + { + wraithUse = test; + break; + } + } + } + if (wraithUse != null) + {// Wraith Summon + _wraithTriggers.remove(wraithUse); + weight.clear(); + weight.put(SkeletonWraithSummon.class, 999); + } + } + + for (BossAbility ability : _currentAbilities) + { + weight.remove(ability.getClass()); + } + + for (Class c : _cooldowns.keySet()) + { + if (_cooldowns.get(c) > System.currentTimeMillis()) + { + weight.remove(c); + } + } + + if (_moving) + { + Iterator>> trying = weight.keySet().iterator(); + while (trying.hasNext()) + { + Class> abilityClass = trying.next(); + + try + { + BossAbility ability = abilityClass.newInstance(); + if (!ability.canMove()) + { + trying.remove(); + } + } + catch (Exception e) {} + } + } + + BossAbility ability = null; + + if (!weight.isEmpty()) + { + int i = 0; + + for (Integer entry : weight.values()) + { + i += entry; + } + + loop: for (int a = 0; a < 10; a++) + { + int luckyNumber = UtilMath.r(i); + + for (Entry>, Integer> entry : weight.entrySet()) + { + luckyNumber -= entry.getValue(); + + if (luckyNumber <= 0) + { + try + { + ability = entry.getKey().getConstructor(SkeletonCreature.class).newInstance(this); + + if (ability.getTarget() == null || ability.hasFinished()) + { + ability = null; + } + else + { + break loop; + } + } + catch (Exception ex) + { + ex.printStackTrace(); + } + + break; + } + } + } + } + + if (ability != null && ability.getTarget() != null) + { + + Bukkit.getPluginManager().registerEvents(ability, UtilServer.getPlugin()); + + if (DEBUG_MODE) + { + System.out.print("Necromancer is using " + ability.getClass().getSimpleName()); + } + + _currentAbilities.add(ability); + } + + _lastAbility = 10; + } + + for (BossAbility ability : _currentAbilities) + { + try + { + ability.tick(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + boolean canMove = true; + for (BossAbility ability : _currentAbilities) + { + if (!ability.canMove()) + { + canMove = false; + } + } + if (!((SkeletonBoss)getEvent()).canMove) + { + return; + } + + if (_moving) + { + if (_movingTo == null) + { + _movingTo = selectWalkTarget(); + } + if (UtilMath.offset(getEntity().getLocation(), _movingTo) <= 1.3) + { + _lastMoved = System.currentTimeMillis(); + _movingTo = null; + _moving = false; + return; + } + UtilEnt.LookAt(getEntity(), _movingTo); + Vector walk = UtilAlg.getTrajectory(getEntity().getLocation(), _movingTo); + walk.multiply(walk.length()); + walk.multiply(.2); + getEntity().setVelocity(walk); + } + else + { + if (!UtilTime.elapsed(_lastMoved, 7000) || !canMove) + { + return; + } + _movingTo = selectWalkTarget(); + _moving = true; + } + } + + private Location selectWalkTarget() + { + if (_movePoints.isEmpty()) + { + Location base = getSpawnLocation().clone(); + base.setY(getEntity().getLocation().getY()); + generateWalkPoints(base); + } + Location selected = _movePoints.get(new Random().nextInt(_movePoints.size())); + _movePoints.remove(selected); + + return selected; + } + + private void generateWalkPoints(Location base) + { + _movePoints.add(base.clone().add(5 + UtilMath.random(1, 3), 0, 5 + UtilMath.random(1, 3))); + _movePoints.add(base.clone().add(-5 + UtilMath.random(1, 3), 0, 5 + UtilMath.random(1, 3))); + _movePoints.add(base.clone().add(5 + UtilMath.random(1, 3), 0, -5 + UtilMath.random(1, 3))); + _movePoints.add(base.clone().add(-5 + UtilMath.random(1, 3), 0, -5 + UtilMath.random(1, 3))); + } + + private List getPlayers(Map map, double maxDist) + { + return getPlayers(map, 0, maxDist); + } + + private List getPlayers(final Map map, double minDist, double maxDist) + { + List list = new ArrayList<>(); + + for (Player p : map.keySet()) + { + if (map.get(p) >= minDist && map.get(p) <= maxDist) + { + list.add(p); + } + } + + Collections.sort(list, (o1, o2) -> + { + return Double.compare(map.get(o2), map.get(o1)); + }); + + return list; + } + + @EventHandler + public void onSkeletonDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + event.SetKnockback(false); + } + } + + @EventHandler + public void noFallDamage(CustomDamageEvent event) + { + if (getEntity() == null) + { + return; + } + + if (event.GetDamageeEntity().getEntityId() != getEntity().getEntityId()) + { + return; + } + + DamageCause cause = event.GetCause(); + + if (cause == DamageCause.FALL) + { + event.SetCancelled("Boss Invulnerability"); + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void protect(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damagee)) + { + if (!(damager instanceof Player)) + { + event.SetCancelled("Allied Attacker"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonArcherShield.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonArcherShield.java new file mode 100644 index 000000000..c4eadb5d4 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonArcherShield.java @@ -0,0 +1,187 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftSkeleton; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.UndeadArcherCreature; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class SkeletonArcherShield extends BossAbility +{ + private static long ATTACK_DURATION = 10000; + private static long ARROW_DELAY = 100; + private static long ARROW_WARMUP = 2000; + private static double PULL_RANGE = 12; + private long _start; + private long _lastShoot; + private boolean _teleported; + + public SkeletonArcherShield(SkeletonCreature creature) + { + super(creature); + _start = System.currentTimeMillis(); + } + + @Override + public int getCooldown() + { + return 20; + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean inProgress() + { + return false; + } + + @Override + public boolean hasFinished() + { + return UtilTime.elapsed(_start, ATTACK_DURATION); + } + + @Override + public void setFinished() + { + _start = System.currentTimeMillis() - ATTACK_DURATION; + for (UndeadArcherCreature creature : getBoss().Archers) + { + creature.getEntity().remove(); + } + } + + private void run(boolean initial) + { + for (int i = 0; i < getBoss().Archers.size(); i++) + { + Skeleton archer = getBoss().Archers.get(i).getEntity(); + UtilEnt.vegetate(archer); + ((CraftSkeleton)archer).setVegetated(false); + + double lead = i * ((2d * Math.PI)/getBoss().Archers.size()); + + double sizeMod = 2; + + //Orbit + double speed = 10d; + double oX = -Math.sin(getEntity().getTicksLived()/speed + lead) * 2 * sizeMod; + double oY = 0; + double oZ = Math.cos(getEntity().getTicksLived()/speed + lead) * 2 * sizeMod; + + if (initial) + { + archer.teleport(getEntity().getLocation().add(oX, oY, oZ)); + UtilEnt.vegetate(archer); + } + else + { + Location to = getEntity().getLocation().add(oX, oY, oZ); + UtilEnt.LookAt(archer, to); + UtilAction.velocity(archer, UtilAlg.getTrajectory(archer.getLocation(), to), 0.4, false, 0, 0.1, 1, true); + } + } + } + + private void shoot() + { + if (UtilTime.elapsed(_start, ARROW_WARMUP) && UtilTime.elapsed(_lastShoot, ARROW_DELAY)) + { + _lastShoot = System.currentTimeMillis(); + for (UndeadArcherCreature archer : getBoss().Archers) + { + Location spawn = archer.getEntity().getEyeLocation().add(UtilAlg.getTrajectory(getEntity().getEyeLocation(), archer.getEntity().getEyeLocation()).normalize()); + Vector vector = UtilAlg.getTrajectory(getEntity().getEyeLocation(), spawn); + Arrow arrow = archer.getEntity().getWorld().spawnArrow(spawn, vector, 0.6f, 12f); + arrow.setMetadata("SHIELD_SHOT", new FixedMetadataValue(UtilServer.getPlugin(), true)); + arrow.setMetadata("BARBED_ARROW", new FixedMetadataValue(UtilServer.getPlugin(), 10)); + arrow.setShooter(archer.getEntity()); + } + } + } + + @Override + public void tick() + { + if (!_teleported) + { + run(true); + _teleported = true; + for (Player near : UtilPlayer.getInRadius(getEntity().getLocation(), PULL_RANGE).keySet()) + { + Vector velocity = UtilAlg.getTrajectory(near, getEntity()); + UtilAction.velocity(near, velocity, 2, false, 0, 0, 1, true); + near.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 5 * 20, -2)); + for (int i = 0; i < 6; i++) + { + Vector random = new Vector(Math.random() * 4 - 2, Math.random() * 4 - 2, Math.random() * 4 - 2); + + Location origin = getEntity().getLocation().add(0, 1.3, 0); + origin.add(velocity.clone().multiply(10)); + origin.add(random); + + Vector vel = UtilAlg.getTrajectory(origin, getEntity().getLocation().add(0, 1.3, 0)); + vel.multiply(7); + + UtilParticle.PlayParticleToAll(ParticleType.MAGIC_CRIT, origin, (float)vel.getX(), (float)vel.getY(), (float)vel.getZ(), 1, 0, ViewDist.LONG); + } + } + } + else + { + run(false); + shoot(); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().equals(getBoss().getEntity())) + { + if (!hasFinished()) + { + event.SetCancelled("Wraiths Alive"); + } + } + } + + @EventHandler + public void onArrowHit(ProjectileHitEvent event) + { + if (event.getEntity().hasMetadata("SHIELD_SHOT")) + { + Bukkit.getScheduler().runTaskLater(UtilServer.getPlugin(), () -> + { + event.getEntity().remove(); + }, 20L); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonHellishFlood.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonHellishFlood.java new file mode 100644 index 000000000..794e75ada --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonHellishFlood.java @@ -0,0 +1,119 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import org.bukkit.Location; +import org.bukkit.entity.Skeleton; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonBoss; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.MinionType; + +public class SkeletonHellishFlood extends BossAbility +{ + private static final int WAVE_COUNT = 3; + private static final int WAVE_SIZE = 5; + private static final MinionType[] POSSIBLE_MINIONS = new MinionType[] {MinionType.WARRIOR, MinionType.ARCHER}; + private static final long WAVE_DELAY = 1000; + + private Map _waves = new HashMap<>(); + private long _lastSpawned; + private int _current; + private int _ticks; + + public SkeletonHellishFlood(SkeletonCreature creature) + { + super(creature); + + if (WAVE_COUNT > 0) + { + for (int i = 1; i <= WAVE_COUNT; i++) + { + createWave(i); + } + } + _lastSpawned = System.currentTimeMillis(); + _current = 1; + } + + private void createWave(int number) + { + int length = POSSIBLE_MINIONS.length; + if (length <= 0 || WAVE_SIZE <= 0) + { + return; + } + MinionType[] wave = new MinionType[WAVE_SIZE]; + for (int i = 0; i < WAVE_SIZE; i++) + { + wave[i] = POSSIBLE_MINIONS[new Random().nextInt(length)]; + } + _waves.put("Wave " + number, wave); + } + + @Override + public int getCooldown() + { + return 30; + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public boolean hasFinished() + { + return _waves.isEmpty() && _ticks > ((WAVE_DELAY / 1000) * 20 * (WAVE_COUNT - 1)); + } + + @Override + public void setFinished() + { + _waves.clear(); + _ticks = 60; + } + + @Override + public void tick() + { + _ticks++; + if (UtilTime.elapsed(_lastSpawned, WAVE_DELAY)) + { + if (_current <= WAVE_COUNT) + { + for (MinionType type : _waves.get("Wave " + _current)) + { + Location toSpawn = getLocation().clone(); + toSpawn.add(UtilMath.random(3, 6), 0, UtilMath.random(3, 6)); + + ((SkeletonBoss)getBoss().getEvent()).spawnMinion(type, toSpawn); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, toSpawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, toSpawn, null, 0, 2, ViewDist.MAX); + } + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + _waves.remove("Wave " + _current); + _current++; + _lastSpawned = System.currentTimeMillis(); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPassive.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPassive.java new file mode 100644 index 000000000..20c542b2c --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPassive.java @@ -0,0 +1,120 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.EventHandler; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.api.EventCreatureDeathEvent; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonBoss; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.MinionType; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.UndeadArcherCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.UndeadWarriorCreature; + +public class SkeletonPassive extends BossPassive +{ + private static final int MAX_ARCHERS = 10; + private static final int MAX_WARRIORS = 8; + private static final long SPAWN_RATE = 5000; + private List _queuedArchers = new ArrayList<>(); + private List _queuedWarriors = new ArrayList<>(); + private long _lastASpawned; + private long _lastWSpawned; + + public SkeletonPassive(SkeletonCreature creature) + { + super(creature); + } + + @Override + public int getCooldown() + { + return 20; + } + + @Override + public boolean isProgressing() + { + return !_queuedArchers.isEmpty() || !_queuedWarriors.isEmpty(); + } + + @Override + public void tick() + { + if (getBoss().Archers.size() < MAX_ARCHERS && _queuedArchers.isEmpty()) + { + for (int i = 0; i < (MAX_ARCHERS - getBoss().Archers.size()); i++) + { + Location spawn = getLocation().clone(); + spawn.add(UtilMath.random(3, 6), 0, UtilMath.random(3, 6)); + _queuedArchers.add(spawn); + } + } + if (getBoss().Warriors.size() < MAX_WARRIORS && _queuedWarriors.isEmpty()) + { + for (int i = 0; i < (MAX_WARRIORS - getBoss().Warriors.size()); i++) + { + Location spawn = getLocation().clone(); + spawn.add(UtilMath.random(3, 6), 0, UtilMath.random(3, 6)); + _queuedWarriors.add(spawn); + } + } + + for (Location animate : _queuedArchers) + { + UtilParticle.PlayParticleToAll(ParticleType.BLOCK_DUST.getParticle(Material.DIRT, 0), + animate.clone().add(0, 0.2, 0), null, 0, 4, ViewDist.NORMAL); + } + for (Location animate : _queuedWarriors) + { + UtilParticle.PlayParticleToAll(ParticleType.BLOCK_DUST.getParticle(Material.DIRT, 0), + animate.clone().add(0, 0.2, 0), null, 0, 4, ViewDist.NORMAL); + } + + if (!_queuedArchers.isEmpty() && UtilTime.elapsed(_lastASpawned, SPAWN_RATE)) + { + _lastASpawned = System.currentTimeMillis(); + Location spawn = _queuedArchers.remove(0); + getBoss().Archers.add((UndeadArcherCreature) ((SkeletonBoss)getBoss().getEvent()).spawnMinion(MinionType.ARCHER, spawn)); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, spawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, spawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + } + if (!_queuedWarriors.isEmpty() && UtilTime.elapsed(_lastWSpawned, SPAWN_RATE)) + { + _lastWSpawned = System.currentTimeMillis(); + Location spawn = _queuedWarriors.remove(0); + getBoss().Warriors.add((UndeadWarriorCreature) ((SkeletonBoss)getBoss().getEvent()).spawnMinion(MinionType.WARRIOR, spawn)); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, spawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, spawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + } + } + + @EventHandler + public void onArcherDeath(EventCreatureDeathEvent event) + { + if (event.getCreature() instanceof UndeadArcherCreature) + { + getBoss().Archers.remove(event.getCreature()); + } + if (event.getCreature() instanceof UndeadWarriorCreature) + { + getBoss().Warriors.remove(event.getCreature()); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPulse.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPulse.java new file mode 100644 index 000000000..db28e1493 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonPulse.java @@ -0,0 +1,108 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.recharge.Recharge; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; + +public class SkeletonPulse extends BossAbility +{ + private static final long TOTAL_ATTACK_DURATION = 8000; + private static final long TOTAL_ATTACK_PROGRESS = 3000; + private long _start, _lastIncrement; + private int _radius; + private Location _center; + + public SkeletonPulse(SkeletonCreature creature) + { + super(creature); + _start = System.currentTimeMillis(); + _radius = 2; + _lastIncrement = System.currentTimeMillis(); + _center = creature.getEntity().getLocation(); + } + + private int getRadius() + { + return Math.min(8, _radius); + } + + @Override + public int getCooldown() + { + return 7; + } + + @Override + public boolean canMove() + { + return UtilTime.elapsed(_start, TOTAL_ATTACK_PROGRESS); + } + + @Override + public boolean inProgress() + { + return UtilTime.elapsed(_start, TOTAL_ATTACK_PROGRESS); + } + + @Override + public boolean hasFinished() + { + return UtilTime.elapsed(_start, TOTAL_ATTACK_DURATION); + } + + @Override + public void setFinished() + { + _start = System.currentTimeMillis() - TOTAL_ATTACK_DURATION; + } + + @Override + public void tick() + { + if (UtilTime.elapsed(_lastIncrement, 500)) + { + _lastIncrement = System.currentTimeMillis(); + _radius++; + } + + for (double token = 0; token <= (2 * Math.PI); token += .2) + { + double x = getRadius() * Math.cos(token); + double z = getRadius() * Math.sin(token); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, _center.clone().add(x, 1.5, z), null, 0, 1, ViewDist.MAX); + } + + for (Player player : UtilPlayer.getInRadius(getEntity().getLocation(), getRadius()).keySet()) + { + if (player.isDead() || !player.isValid() || !player.isOnline()) + { + continue; + } + if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + if (!Recharge.Instance.use(player, "Pulse Knockback", 400, false, false, false)) + { + continue; + } + + player.playSound(player.getLocation(), Sound.AMBIENCE_THUNDER, 1f, 1f); + UtilAction.velocity(player, UtilAlg.getTrajectory2d(getEntity(), player), 2, false, 0.6, 0, 1.4, true); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonSmite.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonSmite.java new file mode 100644 index 000000000..fc1a23de3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonSmite.java @@ -0,0 +1,104 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import java.math.BigDecimal; + +import org.bukkit.GameMode; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; + +public class SkeletonSmite extends BossAbility +{ + private static final long TOTAL_ATTACK_DURATION = 8000; + private long _start; + private int _ticks; + private boolean _shot; + + public SkeletonSmite(SkeletonCreature creature) + { + super(creature); + _start = System.currentTimeMillis(); + _ticks = 0; + _shot = false; + } + + @Override + public int getCooldown() + { + return 15; + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public boolean hasFinished() + { + return UtilTime.elapsed(_start, TOTAL_ATTACK_DURATION) && _shot; + } + + @Override + public void setFinished() + { + _start = System.currentTimeMillis() - TOTAL_ATTACK_DURATION; + _shot = true; + } + + @Override + public void tick() + { + if (_shot) + return; + + if (_ticks < (6 * 20)) + { + _ticks++; + double maxHeight = Math.min(_ticks / 20, 6); + int radius = Math.max(6 - (new BigDecimal(_ticks).divide(new BigDecimal(20)).intValue()), 0); + + for (double y = 0; y < maxHeight; y += 0.5) + { + double cos = radius * Math.cos(y); + double sin = radius * Math.sin(y); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation().add(cos, y, sin), null, 0, 1, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation().add(sin, y, cos), null, 0, 1, ViewDist.MAX); + } + } + else + { + _shot = true; + for (Player player : UtilPlayer.getInRadius(getEntity().getLocation(), 15).keySet()) + { + if (player.isDead() || !player.isValid() || !player.isOnline()) + { + continue; + } + if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + + player.getWorld().strikeLightningEffect(player.getLocation()); + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getEntity(), null, DamageCause.LIGHTNING, 15 * getBoss().getDifficulty(), false, true, false, getEntity().getName(), "Lightning Strike"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonStrike.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonStrike.java new file mode 100644 index 000000000..b8588d0b5 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonStrike.java @@ -0,0 +1,167 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; + +public class SkeletonStrike extends BossAbility +{ + private static final double MAX_RANGE = 25; + private static final Integer MAX_TARGETS = 1; + private boolean _shot; + + public SkeletonStrike(SkeletonCreature creature) + { + super(creature); + _shot = false; + } + + private int getPosition(Player toAdd, LinkedList ordered) + { + int position = ordered.size(); + int index = 0; + for (Player player : ordered) + { + if (player.getHealth() < toAdd.getHealth()) + { + position = index; + return position; + } + index++; + } + + return position; + } + + private List getTargets() + { + Skeleton necromancer = getBoss().getEntity(); + LinkedList selections = new LinkedList<>(); + List targeted = new ArrayList<>(); + + Map near = UtilPlayer.getInRadius(necromancer.getLocation(), MAX_RANGE); + + for (Player nearby : near.keySet()) + { + if (nearby.getGameMode() == GameMode.CREATIVE || nearby.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + + if (selections.isEmpty()) + { + selections.addFirst(nearby); + } + else + { + selections.add(getPosition(nearby, selections), nearby); + } + } + + for (int i = 0; i < MAX_TARGETS; i++) + { + if (i < selections.size()) + { + targeted.add(selections.get(i)); + } + } + + return targeted; + } + + private void shootAt(Player target) + { + double curRange = 0; + boolean canHit = false; + + while (curRange <= MAX_RANGE) + { + Location newTarget = getEntity().getEyeLocation().add(UtilAlg.getTrajectory(getEntity(), target).multiply(curRange)); + + if (!UtilBlock.airFoliage(newTarget.getBlock())) + { + canHit = false; + break; + } + if (UtilMath.offset(newTarget, target.getLocation()) <= 0.9) + { + canHit = true; + break; + } + + curRange += 0.2; + + UtilParticle.PlayParticle(ParticleType.WITCH_MAGIC, newTarget, 0, 0, 0, 0, 1, + ViewDist.MAX, UtilServer.getPlayers()); + + canHit = true; + } + + if (canHit) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(target, getEntity(), null, DamageCause.CUSTOM, 12 * getBoss().getDifficulty(), true, true, false, getEntity().getName(), "Mystical Energy"); + } + } + + @Override + public int getCooldown() + { + return 15; + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public boolean inProgress() + { + return false; + } + + @Override + public boolean hasFinished() + { + return _shot; + } + + @Override + public void setFinished() + { + _shot = true; + } + + @Override + public void tick() + { + if (_shot) + return; + + _shot = true; + + for (Player target : getTargets()) + { + shootAt(target); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonWraithSummon.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonWraithSummon.java new file mode 100644 index 000000000..a8a8a33b3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/abilities/SkeletonWraithSummon.java @@ -0,0 +1,231 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.abilities; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.game.clans.clans.worldevent.api.EventCreatureDeathEvent; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonBoss; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.SkeletonCreature; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.MinionType; +import mineplex.game.clans.clans.worldevent.boss.skeletonking.minion.WraithCreature; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class SkeletonWraithSummon extends BossAbility +{ + private static final int WRAITH_AMOUNT = 4; + private static final double DISTANCE_FROM_KING = 4; + private static final double FINAL_SKELETON_HEALTH = 100; + private static final double FINAL_WRAITH_MULTIPLIER = 2; + private final int WRAITH_AMOUNT_THIS_USE; + + private Map _wraiths = new HashMap<>(); + private Location[] _spawns; + private int _ticks; + + public SkeletonWraithSummon(SkeletonCreature creature) + { + super(creature); + + _spawns = new Location[] + { + getEntity().getLocation().add(DISTANCE_FROM_KING, 0, DISTANCE_FROM_KING), + getEntity().getLocation().add(DISTANCE_FROM_KING * -1, 0, DISTANCE_FROM_KING), + getEntity().getLocation().add(DISTANCE_FROM_KING, 0, DISTANCE_FROM_KING * -1), + getEntity().getLocation().add(DISTANCE_FROM_KING * -1, 0, DISTANCE_FROM_KING * -1), + getEntity().getLocation().add(DISTANCE_FROM_KING / 2, 0, DISTANCE_FROM_KING / 2), + getEntity().getLocation().add((DISTANCE_FROM_KING / 2) * -1, 0, DISTANCE_FROM_KING / 2), + getEntity().getLocation().add(DISTANCE_FROM_KING / 2, 0, (DISTANCE_FROM_KING / 2) * -1), + getEntity().getLocation().add((DISTANCE_FROM_KING / 2) * -1, 0, (DISTANCE_FROM_KING / 2) * -1) + }; + + if (creature.getHealth() <= FINAL_SKELETON_HEALTH) + { + WRAITH_AMOUNT_THIS_USE = (int)(WRAITH_AMOUNT * FINAL_WRAITH_MULTIPLIER); + } + else + { + WRAITH_AMOUNT_THIS_USE = WRAITH_AMOUNT; + } + } + + private String getNumberString(Integer number) + { + String num = number.toString(); + char last = num.toCharArray()[num.length() - 1]; + + String formatted = number.toString(); + String ending = ""; + + if (last == '1' && !num.equals("1" + last)) + { + ending = "st"; + } + if (last == '2' && !num.equals("1" + last)) + { + ending = "nd"; + } + if (last == '3' && !num.equals("1" + last)) + { + ending = "rd"; + } + if (ending.equals("")) + { + ending = "th"; + } + + return formatted + ending; + } + + private void spawnWraith(Location loc, int number) + { + WraithCreature wraith = (WraithCreature)((SkeletonBoss)getBoss().getEvent()).spawnMinion(MinionType.WRAITH, loc); + _wraiths.put(wraith, getNumberString(number)); + } + + @Override + public int getCooldown() + { + return 0; + } + + @Override + public boolean canMove() + { + return false; + } + + @Override + public boolean inProgress() + { + return true; + } + + @Override + public boolean hasFinished() + { + return _wraiths.isEmpty() && _ticks > 40; + } + + @Override + public void setFinished() + { + for (WraithCreature wraith : _wraiths.keySet()) + { + wraith.remove(); + } + _wraiths.clear(); + _ticks = 41; + } + + @Override + public void tick() + { + if (_ticks == 0) + { + if (WRAITH_AMOUNT > 0) + { + for (int i = 0; i < WRAITH_AMOUNT_THIS_USE; i++) + { + int spawnIndex = i; + if (spawnIndex >= _spawns.length) + { + spawnIndex = spawnIndex % _spawns.length; + } + spawnWraith(_spawns[spawnIndex], i + 1); + } + + for (Player player : UtilPlayer.getInRadius(getEntity().getLocation(), 80).keySet()) + { + if (player.isDead() || !player.isValid() || !player.isOnline()) + { + continue; + } + if (player.getGameMode() == GameMode.CREATIVE || player.getGameMode() == GameMode.SPECTATOR) + { + continue; + } + + player.sendMessage(F.main(getBoss().getEvent().getName(), "You must slay all " + WRAITH_AMOUNT_THIS_USE + " wraiths before continuing to fight the " + getBoss().getEvent().getName() + "!")); + } + } + } + _ticks++; + if (!hasFinished()) + { + int ticks = 10; + int hticks = 40; + boolean up = getEntity().getTicksLived() % (hticks * 2) < hticks; + int tick = getEntity().getTicksLived() % ticks; + double htick = getEntity().getTicksLived() % hticks; + int splits = 4; + + Location loc = getEntity().getLocation().add(0, 2, 0); + + for (double d = tick * (Math.PI * 2 / splits) / ticks; d < Math.PI * 2; d += Math.PI * 2 / splits) + { + Vector v = new Vector(Math.sin(d), 0, Math.cos(d)); + v.normalize().multiply(Math.max(0.2, Math.sin((htick / hticks) * Math.PI) * 1.0)); + v.setY((htick / hticks) * -2); + if (up) v.setY(-2 + 2 * (htick / hticks)); + + Location lloc = loc.clone().add(v); + + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, lloc, null, 0f, 2, ViewDist.MAX); + } + } + } + + @EventHandler + public void onWraithDie(EventCreatureDeathEvent event) + { + if (event.getCreature() instanceof WraithCreature) + { + String number = _wraiths.remove(event.getCreature()); + if (number != null) + { + double remainPercent = new BigDecimal(_wraiths.size()).divide(new BigDecimal(WRAITH_AMOUNT_THIS_USE)).doubleValue(); + ChatColor remainColor = ChatColor.GREEN; + if (remainPercent < .66) + { + remainColor = ChatColor.YELLOW; + } + if (remainPercent < .33) + { + remainColor = ChatColor.RED; + } + Bukkit.broadcastMessage(F.main(getBoss().getEvent().getName(), "A wraith has been slain!" + " (" + remainColor + _wraiths.size() + "/" + WRAITH_AMOUNT_THIS_USE + C.cGray + ") wraiths remaining!")); + System.out.println(F.main(getBoss().getEvent().getName(), "The " + number + " wraith has been slain!")); + } + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().equals(getBoss().getEntity())) + { + if (!hasFinished()) + { + event.SetCancelled("Wraiths Alive"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/MinionType.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/MinionType.java new file mode 100644 index 000000000..8d2f779ca --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/MinionType.java @@ -0,0 +1,34 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.minion; + +import org.bukkit.Location; + +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; + +public enum MinionType +{ + WARRIOR(UndeadWarriorCreature.class), + ARCHER(UndeadArcherCreature.class), + WRAITH(WraithCreature.class); + + private Class> _code; + + private MinionType(Class> code) + { + _code = code; + } + + public EventCreature getNewInstance(WorldEvent event, Location spawn) + { + try + { + return _code.getConstructor(WorldEvent.class, Location.class).newInstance(event, spawn); + } + catch (Exception e) + { + e.printStackTrace(); + } + + return null; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadArcherCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadArcherCreature.java new file mode 100644 index 000000000..625b96c0d --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadArcherCreature.java @@ -0,0 +1,234 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.minion; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.entity.EntityTargetLivingEntityEvent; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilServer; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class UndeadArcherCreature extends EventCreature +{ + private static final int BARBED_LEVEL = 1; + private static final int LIFETIME = -1; + + public UndeadArcherCreature(WorldEvent event, Location spawnLocation) + { + super(event, spawnLocation, "Undead Archer", true, 25, 30, true, Skeleton.class); + + spawnEntity(); + } + + @Override + protected void spawnCustom() + { + Skeleton entity = getEntity(); + EntityEquipment eq = entity.getEquipment(); + eq.setItemInHand(new ItemStack(Material.BOW)); + eq.setHelmet(new ItemStack(Material.CHAINMAIL_HELMET)); + eq.setChestplate(new ItemStack(Material.CHAINMAIL_CHESTPLATE)); + eq.setLeggings(new ItemStack(Material.CHAINMAIL_LEGGINGS)); + eq.setBoots(new ItemStack(Material.CHAINMAIL_BOOTS)); + eq.setItemInHandDropChance(0.f); + eq.setHelmetDropChance(0.f); + eq.setChestplateDropChance(0.f); + eq.setLeggingsDropChance(0.f); + eq.setBootsDropChance(0.f); + entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 999999, 0)); + } + + @Override + public void dieCustom() + { + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + return; + } + + if (Math.random() > 0.97) + { + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_HELMET)); + } + + if (Math.random() > 0.97) + { + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_CHESTPLATE)); + } + + if (Math.random() > 0.97) + { + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_LEGGINGS)); + } + + if (Math.random() > 0.97) + { + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.CHAINMAIL_BOOTS)); + } + + if (Math.random() > 0.90) + { + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.BOW)); + } + + getEntity().getWorld().dropItem(getEntity().getLocation(), new org.bukkit.inventory.ItemStack(Material.ARROW, UtilMath.r(12) + 1)); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void bowShoot(EntityShootBowEvent event) + { + if (BARBED_LEVEL == 0) + { + return; + } + + if (!(event.getProjectile() instanceof Arrow)) + { + return; + } + + if (event.getEntity().getEntityId() != getEntity().getEntityId()) + { + return; + } + + event.getProjectile().setMetadata("BARBED_ARROW", new FixedMetadataValue(UtilServer.getPlugin(), 2)); + } + + @EventHandler(priority = EventPriority.HIGH) + public void damage(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + if (event.GetCause() != DamageCause.PROJECTILE) + { + return; + } + + Projectile projectile = event.GetProjectile(); + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(true); + + if (projectile == null) + { + return; + } + + if (!projectile.hasMetadata("BARBED_ARROW")) + { + return; + } + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (!getEntity().equals(damager)) + { + return; + } + + // Level + if (BARBED_LEVEL == 0) + { + return; + } + + Player damageePlayer = event.GetDamageePlayer(); + + if (damageePlayer != null) + { + damageePlayer.setSprinting(false); + } + + // Damage + event.AddMod(damager.getName(), "Barbed Arrows", projectile.getMetadata("BARBED_ARROW").get(0).asDouble(), false); + + // Condition + getEvent().getCondition().Factory().Slow("Barbed Arrows", damagee, damager, (projectile.getVelocity().length() / 3) * (2 + BARBED_LEVEL), 0, false, true, true, true); + } + + @EventHandler + public void clean(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + { + return; + } + + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + remove(); + return; + } + } + + @EventHandler + public void onTarget(EntityTargetLivingEntityEvent event) + { + if (getEntity().equals(event.getEntity())) + { + if (!(event.getTarget() instanceof Player)) + { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void protect(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damagee)) + { + if (!(damager instanceof Player)) + { + event.SetCancelled("Allied Attacker"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadWarriorCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadWarriorCreature.java new file mode 100644 index 000000000..607a2c234 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/UndeadWarriorCreature.java @@ -0,0 +1,186 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.minion; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityTargetLivingEntityEvent; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilMath; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class UndeadWarriorCreature extends EventCreature +{ + private static final int LIFETIME = -1; + + public UndeadWarriorCreature(WorldEvent event, Location spawnLocation) + { + super(event, spawnLocation, "Undead Warrior", true, 30, 30, true, Zombie.class); + spawnEntity(); + } + + @Override + protected void spawnCustom() + { + Zombie entity = getEntity(); + EntityEquipment eq = entity.getEquipment(); + eq.setHelmet(new ItemStack(Material.IRON_HELMET)); + eq.setChestplate(new ItemStack(Material.IRON_CHESTPLATE)); + eq.setLeggings(new ItemStack(Material.IRON_LEGGINGS)); + eq.setBoots(new ItemStack(Material.IRON_BOOTS)); + eq.setItemInHand(new ItemStack(Material.STONE_SWORD)); + eq.setHelmetDropChance(0.f); + eq.setChestplateDropChance(0.f); + eq.setLeggingsDropChance(0.f); + eq.setBootsDropChance(0.f); + eq.setItemInHandDropChance(0.f); + entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 999999, 0)); + } + + @Override + public void dieCustom() + { + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + return; + } + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_HELMET)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_CHESTPLATE)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_LEGGINGS)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.IRON_BOOTS)); + } + + @EventHandler + public void leap(UpdateEvent event) + { + if (getEntity() == null) + return; + + if (event.getType() != UpdateType.FAST) + return; + + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + remove(); + return; + } + + if (Math.random() < 0.9) + return; + + Zombie zombie = getEntity(); + + if (zombie.getTarget() == null) + return; + + double dist = UtilMath.offset(zombie.getTarget(), zombie); + + if (dist <= 3 || dist > 16) + return; + + + double power = 0.8 + (1.2 * ((dist-3)/13d)); + + //Leap + UtilAction.velocity(zombie, UtilAlg.getTrajectory(zombie, zombie.getTarget()), + power, false, 0, 0.2, 1, true); + + //Effect + zombie.getWorld().playSound(zombie.getLocation(), Sound.ZOMBIE_HURT, 1f, 2f); + } + + @EventHandler + public void onTarget(EntityTargetLivingEntityEvent event) + { + if (getEntity().equals(event.getEntity())) + { + if (!(event.getTarget() instanceof Player)) + { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void attack(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(false); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damager)) + { + if (damagee instanceof Player) + { + ((Player)damagee).setFoodLevel(((Player)damagee).getFoodLevel() - 1); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void protect(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damagee)) + { + if (!(damager instanceof Player)) + { + event.SetCancelled("Allied Attacker"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/WraithCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/WraithCreature.java new file mode 100644 index 000000000..9a9cbcde3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/boss/skeletonking/minion/WraithCreature.java @@ -0,0 +1,190 @@ +package mineplex.game.clans.clans.worldevent.boss.skeletonking.minion; + +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityTargetLivingEntityEvent; +import org.bukkit.inventory.EntityEquipment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class WraithCreature extends EventCreature +{ + private static final int LIFETIME = -1; + + public WraithCreature(WorldEvent event, Location spawnLocation) + { + super(event, spawnLocation, "Wraith", true, 200, 30, true, Zombie.class); + spawnEntity(); + } + + @Override + protected void spawnCustom() + { + Zombie entity = getEntity(); + EntityEquipment eq = entity.getEquipment(); + eq.setHelmet(new ItemStack(Material.SKULL_ITEM, 1, (short)1)); + eq.setChestplate(new ItemBuilder(Material.LEATHER_CHESTPLATE).setColor(Color.BLACK).build()); + eq.setLeggings(new ItemBuilder(Material.LEATHER_LEGGINGS).setColor(Color.BLACK).build()); + eq.setBoots(new ItemBuilder(Material.LEATHER_BOOTS).setColor(Color.BLACK).build()); + eq.setItemInHand(new ItemStack(Material.IRON_SWORD)); + eq.setHelmetDropChance(0.f); + eq.setChestplateDropChance(0.f); + eq.setLeggingsDropChance(0.f); + eq.setBootsDropChance(0.f); + eq.setItemInHandDropChance(0.f); + entity.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 999999, 0)); + entity.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 999999, 0)); + entity.addPotionEffect(new PotionEffect(PotionEffectType.WATER_BREATHING, 999999, 0)); + entity.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 999999, 1)); + } + + @Override + public void dieCustom() + { + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + return; + } + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_HELMET)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_CHESTPLATE)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_LEGGINGS)); + + if (Math.random() > 0.97) + getEntity().getWorld().dropItem(getEntity().getLocation(), new ItemStack(Material.DIAMOND_BOOTS)); + } + + @EventHandler(priority = EventPriority.HIGH) + public void damage(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(false); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damager)) + { + event.AddMult(damager.getName(), "Mystical Darkness", 2, false); + } + } + + @EventHandler + public void blink(UpdateEvent event) + { + if (getEntity() == null) + return; + + if (event.getType() != UpdateType.FAST) + return; + + if (LIFETIME >= 0 && getEntity().getTicksLived() >= (20 * LIFETIME)) + { + remove(); + return; + } + + if (Math.random() < 0.6) + return; + + Zombie zombie = getEntity(); + + if (zombie.getTarget() == null) + return; + + double dist = UtilMath.offset(zombie.getTarget(), zombie); + + if (dist <= 10 || dist > 25) + return; + + Location teleport = zombie.getTarget().getLocation().add(Math.random() + 1, 0, Math.random() + 1); + if (UtilMath.offset(getSpawnLocation(), teleport) > 30) + { + return; + } + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, zombie.getLocation(), 0, 0, 0, 0, 5, ViewDist.MAX); + zombie.getWorld().playSound(zombie.getLocation(), Sound.ENDERMAN_TELEPORT, 1f, 2f); + zombie.teleport(teleport); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, zombie.getLocation(), 0, 0, 0, 0, 5, ViewDist.MAX); + zombie.getWorld().playSound(zombie.getLocation(), Sound.ENDERMAN_TELEPORT, 1f, 2f); + } + + @EventHandler + public void onTarget(EntityTargetLivingEntityEvent event) + { + if (getEntity().equals(event.getEntity())) + { + if (!(event.getTarget() instanceof Player)) + { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void protect(CustomDamageEvent event) + { + if (event.IsCancelled()) + { + return; + } + + LivingEntity damagee = event.GetDamageeEntity(); + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + + if (damagee == null) + { + return; + } + + if (damager == null) + { + return; + } + + if (getEntity().equals(damagee)) + { + if (!(damager instanceof Player)) + { + event.SetCancelled("Allied Attacker"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/ClearCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/ClearCommand.java index 4439d2502..58c63968a 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/ClearCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/ClearCommand.java @@ -8,12 +8,6 @@ import mineplex.core.common.util.F; import mineplex.core.common.util.UtilPlayer; import mineplex.game.clans.clans.worldevent.WorldEventManager; -/** - * ClearCommand - * - * @author Shaun Bennett - * @since 6/9/2015 - */ public class ClearCommand extends CommandBase { public ClearCommand(WorldEventManager plugin) @@ -27,4 +21,4 @@ public class ClearCommand extends CommandBase Plugin.clearEvents(); UtilPlayer.message(caller, F.main(Plugin.getName(), "All world events cleared!")); } -} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/RandomCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/RandomCommand.java index ef9c08af2..1c74e7e5b 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/RandomCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/RandomCommand.java @@ -8,7 +8,6 @@ import mineplex.core.common.util.F; import mineplex.core.common.util.UtilPlayer; import mineplex.game.clans.clans.worldevent.WorldEventManager; import mineplex.game.clans.clans.worldevent.WorldEventType; -import mineplex.minecraft.game.core.boss.WorldEvent; /** * Command for spawning a random world event in the world. @@ -33,4 +32,4 @@ public class RandomCommand extends CommandBase UtilPlayer.message(caller, F.main(Plugin.getName(), "Could not start World Event")); } } -} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/StartCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/StartCommand.java index e95f7fa48..1db7667de 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/StartCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/StartCommand.java @@ -9,7 +9,7 @@ import mineplex.core.common.util.F; import mineplex.core.common.util.UtilPlayer; import mineplex.game.clans.clans.worldevent.WorldEventManager; import mineplex.game.clans.clans.worldevent.WorldEventType; -import mineplex.minecraft.game.core.boss.WorldEvent; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; public class StartCommand extends CommandBase { @@ -56,4 +56,4 @@ public class StartCommand extends CommandBase } } } -} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/WorldEventCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/WorldEventCommand.java index e52b389b3..62e42c6e8 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/WorldEventCommand.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/command/WorldEventCommand.java @@ -22,9 +22,8 @@ public class WorldEventCommand extends MultiCommandBase @Override protected void Help(Player caller, String[] args) { - UtilPlayer.message(caller, F.help("/" + _aliasUsed + " start ", "Start a World Event where you're standing", Rank.ADMIN)); + UtilPlayer.message(caller, F.help("/" + _aliasUsed + " start ", "Start a World Event", Rank.ADMIN)); UtilPlayer.message(caller, F.help("/" + _aliasUsed + " clear", "Clears all World Events", Rank.ADMIN)); UtilPlayer.message(caller, F.help("/" + _aliasUsed + " random", "Starts a random World Event", Rank.ADMIN)); } -} - +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidAltar.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidAltar.java new file mode 100644 index 000000000..0bb876d79 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidAltar.java @@ -0,0 +1,199 @@ +package mineplex.game.clans.clans.worldevent.raid; + +import java.util.List; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.clans.ClansManager; + +public class RaidAltar +{ + private Block _altarBlock; + private RaidType _type; + private List _requiredItems; + + public RaidAltar(Block altarBlock, RaidType type, List requiredItems) + { + _altarBlock = altarBlock; + _type = type; + _requiredItems = requiredItems; + } + + @SuppressWarnings("deprecation") + private boolean has(Player player, Material type, String itemName, List lore, Byte data, Integer amount) + { + int count = 0; + for (ItemStack item : player.getInventory().getContents()) + { + boolean rejected = false; + if (item == null || item.getType() == Material.AIR) + { + continue; + } + if (type != null && item.getType() != type) + { + rejected = true; + } + if (itemName != null && (!item.hasItemMeta() || !item.getItemMeta().hasDisplayName() || !item.getItemMeta().getDisplayName().equals(itemName))) + { + rejected = true; + } + if (lore != null) + { + if (!item.hasItemMeta() || !item.getItemMeta().hasLore()) + { + rejected = true; + } + else + { + List itemLore = item.getItemMeta().getLore(); + if (itemLore.size() != lore.size()) + { + rejected = true; + } + else + { + for (int i = 0; i < lore.size(); i++) + { + if (!itemLore.get(i).equals(lore.get(i))) + { + rejected = true; + } + } + } + } + } + if (data != null) + { + if (item.getData().getData() != data.byteValue()) + { + rejected = true; + } + } + + if (!rejected) + { + count += item.getAmount(); + } + } + + if (amount != null) + { + return count >= amount.intValue(); + } + else + { + return count > 0; + } + } + + @SuppressWarnings("deprecation") + private void remove(Player player, Material type, String itemName, List lore, Byte data, int amount) + { + int removed = 0; + for (int i = 0; i < player.getInventory().getContents().length; i++) + { + ItemStack item = player.getInventory().getContents()[i]; + if (removed >= amount) + { + return; + } + boolean rejected = false; + if (item == null || item.getType() == Material.AIR) + { + continue; + } + if (type != null && item.getType() != type) + { + rejected = true; + } + if (itemName != null && (!item.hasItemMeta() || !item.getItemMeta().hasDisplayName() || !item.getItemMeta().getDisplayName().equals(itemName))) + { + rejected = true; + } + if (lore != null) + { + if (!item.hasItemMeta() || !item.getItemMeta().hasLore()) + { + rejected = true; + } + else + { + List itemLore = item.getItemMeta().getLore(); + if (itemLore.size() != lore.size()) + { + rejected = true; + } + else + { + for (int index = 0; index < lore.size(); index++) + { + if (!itemLore.get(index).equals(lore.get(index))) + { + rejected = true; + } + } + } + } + } + if (data != null) + { + if (item.getData().getData() != data.byteValue()) + { + rejected = true; + } + } + + if (!rejected) + { + if (item.getAmount() > (amount - removed)) + { + removed += (amount - removed); + item.setAmount(item.getAmount() - (amount - removed)); + } + else + { + removed += item.getAmount(); + player.getInventory().setItem(i, null); + } + } + } + + player.updateInventory(); + } + + @SuppressWarnings("deprecation") + public boolean handleInteract(Player player, Block block) + { + if (_altarBlock.equals(block)) + { + for (ItemStack required : _requiredItems) + { + String displayName = ((required.hasItemMeta() && required.getItemMeta().hasDisplayName()) ? required.getItemMeta().getDisplayName() : null); + List lore = ((required.hasItemMeta() && required.getItemMeta().hasLore()) ? required.getItemMeta().getLore() : null); + if (!has(player, required.getType(), displayName, lore, required.getData().getData(), required.getAmount())) + { + UtilPlayer.message(player, F.main(_type.getRaidName() + " Raid", "You do not have the required summoning items for this raid!")); + return true; + } + } + if (ClansManager.getInstance().getWorldEvent().getRaidManager().startRaid(player, _type)) + { + for (ItemStack required : _requiredItems) + { + String displayName = ((required.hasItemMeta() && required.getItemMeta().hasDisplayName()) ? required.getItemMeta().getDisplayName() : null); + List lore = ((required.hasItemMeta() && required.getItemMeta().hasLore()) ? required.getItemMeta().getLore() : null); + remove(player, required.getType(), displayName, lore, required.getData().getData(), required.getAmount()); + } + } + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidChallenge.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidChallenge.java new file mode 100644 index 000000000..6f30d8744 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidChallenge.java @@ -0,0 +1,62 @@ +package mineplex.game.clans.clans.worldevent.raid; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; + +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTextMiddle; + +public abstract class RaidChallenge implements Listener +{ + private T _raid; + private String _name; + private boolean _completed; + + public RaidChallenge(T raid, String name) + { + _raid = raid; + _name = name; + _completed = false; + } + + public abstract void customStart(); + public abstract void customComplete(); + + public T getRaid() + { + return _raid; + } + + public String getName() + { + return _name; + } + + public boolean isComplete() + { + return _completed; + } + + public void start() + { + customStart(); + UtilServer.RegisterEvents(this); + UtilTextMiddle.display("", getName(), getRaid().getPlayers().toArray(new Player[getRaid().getPlayers().size()])); + } + + public void complete() + { + complete(true); + } + + public void complete(boolean allowCustom) + { + if (allowCustom) + { + customComplete(); + } + HandlerList.unregisterAll(this); + _completed = true; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidCreature.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidCreature.java new file mode 100644 index 000000000..7d18b0fdc --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidCreature.java @@ -0,0 +1,16 @@ +package mineplex.game.clans.clans.worldevent.raid; + +import org.bukkit.Location; +import org.bukkit.entity.LivingEntity; + +import mineplex.game.clans.clans.worldevent.api.EventCreature; + +public abstract class RaidCreature extends EventCreature +{ + public RaidCreature(RaidWorldEvent event, Location spawnLocation, String name, boolean useName, double health, double walkRange, boolean healthRegen, Class entityClass) + { + super(event, spawnLocation, name, useName, health, walkRange, healthRegen, entityClass); + } + + public abstract void handleDeath(Location location); +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidManager.java new file mode 100644 index 000000000..06e29d9de --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidManager.java @@ -0,0 +1,196 @@ +package mineplex.game.clans.clans.worldevent.raid; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitTask; + +import mineplex.core.MiniPlugin; +import mineplex.core.blockrestore.BlockRestore; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.disguise.DisguiseManager; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.projectile.ProjectileManager; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.core.utils.UtilScheduler; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.worldevent.api.EventState; +import mineplex.game.clans.clans.worldevent.raid.command.StartRaidCommand; +import mineplex.minecraft.game.core.condition.ConditionManager; +import mineplex.minecraft.game.core.damage.DamageManager; + +public class RaidManager extends MiniPlugin +{ + private static final int MAX_PARTICIPANTS = 10; + + private Set _raids = new HashSet<>(); + private List _altars = new ArrayList<>(); + + public RaidManager(JavaPlugin plugin) + { + super("Raid Manager", plugin); + + addCommand(new StartRaidCommand(this)); + + { + List items = new ArrayList<>(); + items.add(new ItemStack(Material.BONE, 20)); + items.add(new ItemBuilder(Material.IRON_INGOT).setAmount(2).setTitle(C.cDRedB + "Old Silver Token").setLore(C.cRed + "This token pulses with an evil aura.").setGlow(true).build()); + _altars.add(new RaidAltar(new Location(Bukkit.getWorld("world"), 361, 57, -990).getBlock(), RaidType.CHARLES_WITHERTON, items)); + } + } + + @Override + public void disable() + { + _raids.forEach(raid -> raid.stop(true)); + _raids.clear(); + } + + public DisguiseManager getDisguiseManager() + { + return ClansManager.getInstance().getDisguiseManager(); + } + + public ProjectileManager getProjectileManager() + { + return ClansManager.getInstance().getProjectile(); + } + + public DamageManager getDamageManager() + { + return ClansManager.getInstance().getDamageManager(); + } + + public BlockRestore getBlockRestore() + { + return ClansManager.getInstance().getBlockRestore(); + } + + public ConditionManager getConditionManager() + { + return ClansManager.getInstance().getCondition(); + } + + public int getActiveRaids() + { + return _raids.size(); + } + + public boolean isInRaid(Location loc) + { + for (RaidWorldEvent event : _raids) + { + if (event.WorldData.World.equals(loc.getWorld())) + { + return true; + } + } + + return false; + } + + public boolean startRaid(Player player, RaidType type) + { + if (_raids.size() >= 5) + { + UtilPlayer.message(player, F.main(type.getRaidName() + " Raid", "There are currently too many ongoing raids to start a new one!")); + return false; + } + Set inside = UtilPlayer.getInRadius(player.getLocation(), 4).keySet(); + if (inside.size() > MAX_PARTICIPANTS) + { + UtilPlayer.message(player, F.main(type.getRaidName() + " Raid", "You cannot start a raid with more than " + MAX_PARTICIPANTS + " participants!")); + return false; + } + inside.forEach(in -> UtilPlayer.message(in, F.main(type.getRaidName() + " Raid", "Summoning ancient power..."))); + createNewRaid(type, raid -> inside.forEach(in -> + { + raid.addPlayer(in); + in.getWorld().strikeLightningEffect(in.getLocation()); + })); + return true; + } + + public void createNewRaid(RaidType type, Consumer raidConsumer) + { + final WorldData data = new WorldData(type.getRaidName()); + BukkitTask task = UtilScheduler.runEvery(UpdateType.TICK, () -> + { + if (data.Loaded) + { + try + { + RaidWorldEvent event = type.getClazz().getConstructor(WorldData.class, RaidManager.class).newInstance(data, this); + raidConsumer.accept(event); + event.start(); + _raids.add(event); + } + catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) + { + UtilServer.runSyncLater(data::uninitialize, 120); + e.printStackTrace(); + } + while (data.LoadChecker == null) {} + data.LoadChecker.cancel(); + } + }); + data.LoadChecker = task; + } + + @EventHandler + public void update(UpdateEvent event) + { + if (event.getType() == UpdateType.TICK) + { + UtilServer.getPlayersCollection() + .stream() + .filter(player -> isInRaid(player.getLocation())) + .forEach(player -> + { + ClansManager.getInstance().getItemMapManager().removeMap(player); + }); + return; + } + if (event.getType() != UpdateType.SEC) + { + return; + } + + _raids.removeIf(e -> e.getState() == EventState.STOPPED); + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) + { + if (!event.hasBlock()) + { + return; + } + + for (RaidAltar altar : _altars) + { + if (altar.handleInteract(event.getPlayer(), event.getClickedBlock())) + { + event.setCancelled(true); + return; + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidType.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidType.java new file mode 100644 index 000000000..ab655304c --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidType.java @@ -0,0 +1,27 @@ +package mineplex.game.clans.clans.worldevent.raid; + +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; + +public enum RaidType +{ + CHARLES_WITHERTON("Charles Witherton", WitherRaid.class); + + private String _raidName; + private Class _clazz; + + private RaidType(String raidName, Class clazz) + { + _raidName = raidName; + _clazz = clazz; + } + + public String getRaidName() + { + return _raidName; + } + + public Class getClazz() + { + return _clazz; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidWorldEvent.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidWorldEvent.java new file mode 100644 index 000000000..f3331ad5c --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/RaidWorldEvent.java @@ -0,0 +1,321 @@ +package mineplex.game.clans.clans.worldevent.raid; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.world.ChunkUnloadEvent; + +import mineplex.core.common.util.F; +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.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.event.ClansCommandExecutedEvent; +import mineplex.game.clans.clans.worldevent.api.EventCreatureDeathEvent; +import mineplex.game.clans.clans.worldevent.api.EventState; +import mineplex.game.clans.clans.worldevent.api.WorldEvent; +import mineplex.game.clans.spawn.Spawn; + +public abstract class RaidWorldEvent extends WorldEvent +{ + private static int nextId = 0; + + protected RaidManager Manager; + protected WorldData WorldData; + + protected final int Id; + + private List _players = new ArrayList<>(); + + protected long _forceEnd = -1; + + private boolean _cleanup = false; + + public RaidWorldEvent(String name, WorldData data, RaidManager manager) + { + super(name, new Location(data.World, data.MinX + ((data.MaxX - data.MinX) / 2), data.MinY + ((data.MaxY - data.MinY) / 2), data.MinZ + ((data.MaxZ - data.MinZ) / 2)), UtilMath.getMax((data.MaxX - data.MinX) / 2, (data.MaxY - data.MinY) / 2, (data.MaxZ - data.MinZ) / 2), false, manager.getDisguiseManager(), manager.getProjectileManager(), manager.getDamageManager(), manager.getBlockRestore(), manager.getConditionManager()); + + Id = nextId++; + Manager = manager; + WorldData = data; + + loadNecessaryChunks(); + customLoad(); + } + + protected abstract void customLoad(); + + protected abstract void afterTeleportIn(); + + private void loadNecessaryChunks() + { + int minX = WorldData.MinX >> 4; + int minZ = WorldData.MinZ >> 4; + int maxX = WorldData.MaxX >> 4; + int maxZ = WorldData.MaxZ >> 4; + + for (int x = minX; x <= maxX; x++) + { + for (int z = minZ; z <= maxZ; z++) + { + WorldData.World.getChunkAt(x, z); + } + } + } + + public mineplex.game.clans.clans.worldevent.raid.WorldData getWorldData() + { + return WorldData; + } + + public List getPlayers() + { + List players = new ArrayList<>(); + players.addAll(_players); + return players; + } + + public int getId() + { + return Id; + } + + @Override + public void customStart() + { + _forceEnd = System.currentTimeMillis() + UtilTime.convert(90, TimeUnit.MINUTES, TimeUnit.MILLISECONDS); + int spawnIndex = 0; + List spawns = WorldData.SpawnLocs.get("Red"); + for (Player player : _players) + { + if (spawnIndex >= spawns.size()) + { + spawnIndex = 0; + } + player.teleport(spawns.get(spawnIndex)); + spawnIndex++; + } + afterTeleportIn(); + } + + @Override + public void customCleanup(boolean onDisable) + { + _cleanup = true; + _players.forEach(player -> player.teleport(Spawn.getNorthSpawn())); + _players.clear(); + getCreatures().forEach(creature -> + { + HandlerList.unregisterAll(creature); + creature.getEntity().remove(); + }); + getCreatures().clear(); + if (onDisable) + { + WorldData.uninitialize(); + } + else + { + UtilServer.runSyncLater(WorldData::uninitialize, 20 * 10); + } + } + + public void addPlayer(Player player) + { + _players.add(player); + } + + public void setForceEnd(long end) + { + _forceEnd = end; + } + + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + { + return; + } + if (getState() != EventState.LIVE) + { + return; + } + if (_players.isEmpty()) + { + stop(); + } + else + { + updateLastActive(); + } + if (_forceEnd != -1 && System.currentTimeMillis() >= _forceEnd) + { + stop(); + } + } + + @EventHandler + public void onCreatureDeath(EventCreatureDeathEvent event) + { + if (!event.getCreature().getEvent().getName().equals(getName())) + { + return; + } + RaidWorldEvent worldEvent = (RaidWorldEvent) event.getCreature().getEvent(); + if (worldEvent.Id != Id) + { + return; + } + if (event.getCreature() instanceof RaidCreature) + { + ((RaidCreature)event.getCreature()).handleDeath(event.getCreature().getLastKnownLocation()); + } + } + + @EventHandler + public void onChunkUnload(ChunkUnloadEvent event) + { + if (getState() == EventState.STOPPED || getState() == EventState.REMOVED || _cleanup) + { + return; + } + if (!event.getWorld().equals(WorldData.World)) + { + return; + } + event.setCancelled(true); + } + + @EventHandler + public void breakBlock(BlockBreakEvent event) + { + Block block = event.getBlock(); + Player player = event.getPlayer(); + + if (player.getGameMode() == GameMode.CREATIVE) + { + return; + } + + if (!block.getWorld().equals(WorldData.World)) + { + return; + } + + event.setCancelled(true); + UtilPlayer.message(player, F.main(getName(), "You cannot build here!")); + } + + @EventHandler + public void placeBlock(BlockPlaceEvent event) + { + Block block = event.getBlock(); + Player player = event.getPlayer(); + + if (player.getGameMode() == GameMode.CREATIVE) + { + return; + } + + if (!block.getWorld().equals(WorldData.World)) + { + return; + } + + event.setCancelled(true); + UtilPlayer.message(player, F.main(getName(), "You cannot build here!")); + } + + @EventHandler(priority = EventPriority.LOW) + public void onQuit(PlayerQuitEvent event) + { + if (_cleanup) + { + return; + } + if (_players.remove(event.getPlayer())) + { + event.getPlayer().teleport(Spawn.getNorthSpawn()); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onDie(PlayerDeathEvent event) + { + if (_cleanup) + { + return; + } + if (_players.remove(event.getEntity())) + { + event.getEntity().setHealth(event.getEntity().getMaxHealth()); + getCondition().Clean(event.getEntity()); + event.getEntity().getActivePotionEffects().forEach(pe -> event.getEntity().removePotionEffect(pe.getType())); + event.getEntity().setExp(0); + event.getEntity().setLevel(0); + event.getEntity().setFireTicks(-1); + event.getEntity().teleport(Spawn.getNorthSpawn()); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onTeleport(PlayerTeleportEvent event) + { + if (_cleanup) + { + return; + } + if (!event.getTo().getWorld().equals(WorldData.World)) + { + _players.remove(event.getPlayer()); + } + } + + @EventHandler + public void onTpHome(ClansCommandExecutedEvent event) + { + if (!_players.contains(event.getPlayer())) + { + return; + } + if (event.getCommand().equalsIgnoreCase("tphome") || event.getCommand().equalsIgnoreCase("stuck")) + { + event.setCancelled(true); + UtilPlayer.message(event.getPlayer(), F.main(getName(), "You cannot teleport while in a raid!")); + return; + } + if (event.getCommand().equalsIgnoreCase("claim") || event.getCommand().equalsIgnoreCase("unclaim") || event.getCommand().equalsIgnoreCase("unclaimall") || event.getCommand().equalsIgnoreCase("homeset")) + { + event.setCancelled(true); + UtilPlayer.message(event.getPlayer(), F.main(getName(), "You cannot manage your clan's territory while in a raid!")); + return; + } + } + + @Override + public boolean equals(Object object) + { + if (!(object instanceof RaidWorldEvent)) + { + return false; + } + + return ((RaidWorldEvent)object).getId() == getId(); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/WorldData.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/WorldData.java new file mode 100644 index 000000000..a647f268c --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/WorldData.java @@ -0,0 +1,498 @@ +package mineplex.game.clans.clans.worldevent.raid; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.bukkit.Difficulty; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.scheduler.BukkitTask; + +import mineplex.core.common.timing.TimingManager; +import mineplex.core.common.util.FileUtil; +import mineplex.core.common.util.MapUtil; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.WorldUtil; +import mineplex.core.common.util.ZipUtil; +import mineplex.core.common.util.worldgen.WorldGenCleanRoom; +import mineplex.game.clans.spawn.Spawn; + +public class WorldData +{ + public int Id = -1; + + public String RaidName; + + public boolean Loaded = false; + + protected BukkitTask LoadChecker = null; + + public String File = null; + public String Folder = null; + + public World World; + public int MinX = 0; + public int MinZ = 0; + public int MaxX = 0; + public int MaxZ = 0; + + public int MinY = -1; + public int MaxY = 256; + + public Map> SpawnLocs = new LinkedHashMap<>(); + private Map> DataLocs = new LinkedHashMap<>(); + private Map> CustomLocs = new LinkedHashMap<>(); + private final Map _dataEntries = new LinkedHashMap<>(); + + public WorldData(String raidName) + { + RaidName = raidName; + initialize(); + + Id = getNewId(); + } + + private List loadFiles() + { + TimingManager.start("RaidManager LoadFiles"); + + File folder = new File(".." + java.io.File.separatorChar + ".." + java.io.File.separatorChar + "update" + java.io.File.separatorChar + + "maps" + java.io.File.separatorChar + "Clans" + java.io.File.separatorChar + "Raids" + java.io.File.separatorChar + RaidName); + System.out.println(folder.getAbsolutePath() + " -=-=-=-=-="); + if (!folder.exists()) + { + folder.mkdirs(); + } + + List maps = new ArrayList<>(); + + System.out.println("Searching Maps in: " + folder); + + if (folder.listFiles() != null) + { + for (File file : folder.listFiles()) + { + if (!file.isFile()) + { + System.out.println(file.getName() + " is not a file!"); + continue; + } + + String name = file.getName(); + + if (name.length() < 5) + { + continue; + } + + name = name.substring(name.length() - 4, name.length()); + + if (!name.equals(".zip")) + { + System.out.println(file.getName() + " is not a zip."); + continue; + } + + maps.add(file.getName().substring(0, file.getName().length() - 4)); + } + } + + for (String map : maps) + { + System.out.println("Found Map: " + map); + } + + TimingManager.stop("RaidManager LoadFiles"); + + return maps; + } + + public void initialize() + { + getFile(); + + UtilServer.runAsync(() -> + { + WorldData.this.unzipWorld(); + UtilServer.runSync(() -> + { + TimingManager.start("WorldData loading world."); + + WorldCreator creator = new WorldCreator(getFolder()); + creator.generator(new WorldGenCleanRoom()); + World = WorldUtil.LoadWorld(creator); + + TimingManager.stop("WorldData loading world."); + + World.setDifficulty(Difficulty.HARD); + World.setGameRuleValue("showDeathMessages", "false"); + ((CraftWorld)World).getHandle().allowAnimals = false; + ((CraftWorld)World).getHandle().allowMonsters = false; + + TimingManager.start("WorldData loading WorldConfig."); + //Load World Data + WorldData.this.loadWorldConfig(); + TimingManager.stop("WorldData loading WorldConfig."); + }); + }); + } + + protected String getFile() + { + if (File == null) + { + int map; + try + { + map = UtilMath.r(loadFiles().size()); + } + catch (IllegalArgumentException e) + { + System.out.println("No maps found!"); + return null; + } + File = loadFiles().get(map); + } + + return File; + } + + public String getFolder() + { + if (Folder == null) + { + Folder = RaidName + Id + "_" + getFile(); + } + return Folder; + } + + protected void unzipWorld() + { + TimingManager.start("UnzipWorld creating folders"); + String folder = getFolder(); + new File(folder).mkdir(); + new File(folder + java.io.File.separator + "region").mkdir(); + new File(folder + java.io.File.separator + "data").mkdir(); + TimingManager.stop("UnzipWorld creating folders"); + + TimingManager.start("UnzipWorld UnzipToDirectory"); + ZipUtil.UnzipToDirectory("../../update/maps/Clans/Raids/" + RaidName + "/" + getFile() + ".zip", folder); + TimingManager.stop("UnzipWorld UnzipToDirectory"); + } + + public void loadWorldConfig() + { + //Load Track Data + String line = null; + + try + { + FileInputStream fstream = new FileInputStream(getFolder() + java.io.File.separator + "WorldConfig.dat"); + DataInputStream in = new DataInputStream(fstream); + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + + List currentTeam = null; + List currentData = null; + + int currentDirection = 0; + + while ((line = br.readLine()) != null) + { + String[] tokens = line.split(":"); + + if (tokens.length < 2) + continue; + + if (tokens[0].length() == 0) + continue; + + //Spawn Locations + if (tokens[0].equalsIgnoreCase("TEAM_NAME")) + { + SpawnLocs.put(tokens[1], new ArrayList<>()); + currentTeam = SpawnLocs.get(tokens[1]); + currentDirection = 0; + } + else if (tokens[0].equalsIgnoreCase("TEAM_DIRECTION")) + { + currentDirection = Integer.parseInt(tokens[1]); + } + else if (tokens[0].equalsIgnoreCase("TEAM_SPAWNS")) + { + for (int i=1; i < tokens.length; i++) + { + Location loc = strToLoc(tokens[i]); + if (loc == null) continue; + + loc.setYaw(currentDirection); + + currentTeam.add(loc); + } + } + + //Data Locations + else if (tokens[0].equalsIgnoreCase("DATA_NAME")) + { + DataLocs.put(tokens[1], new ArrayList<>()); + currentData = DataLocs.get(tokens[1]); + } + else if (tokens[0].equalsIgnoreCase("DATA_LOCS")) + { + for (int i=1; i < tokens.length; i++) + { + Location loc = strToLoc(tokens[i]); + if (loc == null) continue; + + currentData.add(loc); + } + } + + //Custom Locations + else if (tokens[0].equalsIgnoreCase("CUSTOM_NAME")) + { + CustomLocs.put(tokens[1], new ArrayList<>()); + currentData = CustomLocs.get(tokens[1]); + } + else if (tokens[0].equalsIgnoreCase("CUSTOM_LOCS")) + { + for (int i=1; i < tokens.length; i++) + { + Location loc = strToLoc(tokens[i]); + if (loc == null) continue; + + currentData.add(loc); + } + } + + //Map Bounds + else if (tokens[0].equalsIgnoreCase("MIN_X")) + { + try + { + MinX = Integer.parseInt(tokens[1]); + } + catch (Exception e) + { + System.out.println("World Data Read Error: Invalid MinX [" + tokens[1] + "]"); + } + + } + else if (tokens[0].equalsIgnoreCase("MAX_X")) + { + try + { + MaxX = Integer.parseInt(tokens[1]); + } + catch (Exception e) + { + System.out.println("World Data Read Error: Invalid MaxX [" + tokens[1] + "]"); + } + } + else if (tokens[0].equalsIgnoreCase("MIN_Z")) + { + try + { + MinZ = Integer.parseInt(tokens[1]); + } + catch (Exception e) + { + System.out.println("World Data Read Error: Invalid MinZ [" + tokens[1] + "]"); + } + } + else if (tokens[0].equalsIgnoreCase("MAX_Z")) + { + try + { + MaxZ = Integer.parseInt(tokens[1]); + } + catch (Exception e) + { + System.out.println("World Data Read Error: Invalid MaxZ [" + tokens[1] + "]"); + } + } + else if (tokens[0].equalsIgnoreCase("MIN_Y")) + { + try + { + MinY = Integer.parseInt(tokens[1]); + } + catch (Exception e) + { + System.out.println("World Data Read Error: Invalid MinY [" + tokens[1] + "]"); + } + } + else if (tokens[0].equalsIgnoreCase("MAX_Y")) + { + try + { + MaxY = Integer.parseInt(tokens[1]); + } + catch (Exception e) + { + System.out.println("World Data Read Error: Invalid MaxY [" + tokens[1] + "]"); + } + } + else + { + _dataEntries.put(tokens[0], tokens[1]); + } + } + + in.close(); + + Loaded = true; + } + catch (Exception e) + { + e.printStackTrace(); + System.err.println("Line: " + line); + } + } + + protected Location strToLoc(String loc) + { + String[] coords = loc.split(","); + + try + { + return new Location(World, Integer.valueOf(coords[0])+0.5, Integer.valueOf(coords[1]), Integer.valueOf(coords[2])+0.5); + } + catch (Exception e) + { + System.out.println("World Data Read Error: Invalid Location String [" + loc + "]"); + } + + return null; + } + + public void uninitialize() + { + if (World == null) + { + return; + } + + World.getPlayers().forEach(player -> player.teleport(Spawn.getNorthSpawn())); + + //Wipe World + MapUtil.UnloadWorld(UtilServer.getPlugin(), World); + MapUtil.ClearWorldReferences(World.getName()); + FileUtil.DeleteFolder(new File(World.getName())); + + World = null; + } + + public int getNewId() + { + File file = new File(RaidName + "RaidId.dat"); + + int id = 0; + + //Write If Blank + if (!file.exists()) + { + try ( + FileWriter fstream = new FileWriter(file); + BufferedWriter out = new BufferedWriter(fstream); + ) + { + out.write("0"); + } + catch (Exception e) + { + System.out.println("Error: Raid World GetId Write Exception"); + } + } + else + { + try ( + FileInputStream fstream = new FileInputStream(file); + DataInputStream in = new DataInputStream(fstream); + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + ) + { + String line = br.readLine(); + + id = Integer.parseInt(line); + } + catch (Exception e) + { + System.out.println("Error: Raid World GetId Read Exception"); + } + } + + try ( + FileWriter fstream = new FileWriter(file); + BufferedWriter out = new BufferedWriter(fstream); + ) + { + out.write("" + (id + 1)); + } + catch (Exception e) + { + System.out.println("Error: Game World GetId Re-Write Exception"); + } + + return id; + } + + public List getDataLocs(String data) + { + if (!DataLocs.containsKey(data)) + { + return new ArrayList<>(); + } + + return DataLocs.get(data); + } + + public List getCustomLocs(String id) + { + if (!CustomLocs.containsKey(id)) + { + return new ArrayList<>(); + } + + return CustomLocs.get(id); + } + + public Map> getAllCustomLocs() + { + return CustomLocs; + } + + public Map> getAllDataLocs() + { + return DataLocs; + } + + public Location getRandomXZ() + { + Location loc = new Location(World, 0, 250, 0); + + int xVar = MaxX - MinX; + int zVar = MaxZ - MinZ; + + loc.setX(MinX + UtilMath.r(xVar)); + loc.setZ(MinZ + UtilMath.r(zVar)); + + return loc; + } + + public String get(String key) + { + return _dataEntries.get(key); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/command/StartRaidCommand.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/command/StartRaidCommand.java new file mode 100644 index 000000000..5701d38a2 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/command/StartRaidCommand.java @@ -0,0 +1,42 @@ +package mineplex.game.clans.clans.worldevent.raid.command; + +import org.bukkit.entity.Player; + +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.clans.worldevent.raid.RaidManager; +import mineplex.game.clans.clans.worldevent.raid.RaidType; + +public class StartRaidCommand extends CommandBase +{ + public StartRaidCommand(RaidManager plugin) + { + super(plugin, Rank.ADMIN, "startraid"); + } + + @Override + public void Execute(Player caller, String[] args) + { + if (args.length < 1) + { + UtilPlayer.message(caller, F.main(Plugin.getName(), "Usage: /startraid ")); + return; + } + try + { + RaidType type = RaidType.valueOf(args[0]); + Plugin.startRaid(caller, type); + } + catch (Exception e) + { + UtilPlayer.message(caller, F.main(Plugin.getName(), "That is not an existing raid type. Raids:")); + for (RaidType type : RaidType.values()) + { + UtilPlayer.message(caller, C.cGray + " - " + C.cYellow + type.name()); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/WitherRaid.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/WitherRaid.java new file mode 100644 index 000000000..6eb3a4112 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/WitherRaid.java @@ -0,0 +1,114 @@ +package mineplex.game.clans.clans.worldevent.raid.wither; + +import java.lang.reflect.InvocationTargetException; +import java.util.LinkedList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.event.EventHandler; + +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.RaidManager; +import mineplex.game.clans.clans.worldevent.raid.RaidType; +import mineplex.game.clans.clans.worldevent.raid.RaidWorldEvent; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.five.ChallengeFive; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.four.ChallengeFour; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.one.ChallengeOne; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.seven.ChallengeSeven; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.six.ChallengeSix; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.three.ChallengeThree; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.two.ChallengeTwo; +import mineplex.minecraft.game.classcombat.Skill.event.SkillTriggerEvent; + +public class WitherRaid extends RaidWorldEvent +{ + private List>> _challenges; + private RaidChallenge _currentChallenge; + + public WitherRaid(mineplex.game.clans.clans.worldevent.raid.WorldData data, RaidManager manager) + { + super(RaidType.CHARLES_WITHERTON.getRaidName(), data, manager); + } + + private void nextChallenge() + { + _currentChallenge = null; + + if (_challenges.isEmpty()) + { + return; + } + + Class> clazz = _challenges.remove(0); + try + { + _currentChallenge = clazz.getConstructor(WitherRaid.class).newInstance(this); + _currentChallenge.start(); + } + catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) + { + e.printStackTrace(); + } + } + + private void teleportToAltar() + { + Location altar = WorldData.getCustomLocs("MAIN_ALTAR").get(0); + getPlayers().forEach(player -> player.teleport(altar)); + } + + @Override + protected void customLoad() + { + WorldData.World.setGameRuleValue("doDaylightCycle", "false"); + WorldData.World.setTime(14000); + _challenges = new LinkedList<>(); + _challenges.add(ChallengeOne.class); + _challenges.add(ChallengeTwo.class); + _challenges.add(ChallengeThree.class); + _challenges.add(ChallengeFour.class); + _challenges.add(ChallengeFive.class); + _challenges.add(ChallengeSix.class); + _challenges.add(ChallengeSeven.class); + } + + @Override + protected void afterTeleportIn() + { + nextChallenge(); + } + + @Override + protected void customTick() + { + if (_currentChallenge != null) + { + if (_currentChallenge.isComplete()) + { + if (_challenges.size() < 5) + { + teleportToAltar(); + } + nextChallenge(); + } + } + } + + @Override + protected void customStop() + { + if (_currentChallenge != null) + { + _currentChallenge.complete(false); + } + } + + @EventHandler + public void onBlockToss(SkillTriggerEvent event) + { + if (event.GetSkillName().equals("Block Toss") && getPlayers().contains(event.GetPlayer())) + { + event.SetCancelled(true); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/five/ChallengeFive.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/five/ChallengeFive.java new file mode 100644 index 000000000..b77f231be --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/five/ChallengeFive.java @@ -0,0 +1,181 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.challenge.five; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilAlg; +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.game.clans.clans.worldevent.api.EventCreature; +import mineplex.game.clans.clans.worldevent.api.EventCreatureDeathEvent; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.archer.DecayingArcher; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.corpse.ReanimatedCorpse; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.giant.Goliath; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.mage.UndeadKnight; +import mineplex.minecraft.game.classcombat.Skill.event.SkillTriggerEvent; + +public class ChallengeFive extends RaidChallenge +{ + private Location _altar; + private boolean _teleported = false; + private LinkedList _gates = new LinkedList<>(); + private Goliath _goliath; + + public ChallengeFive(WitherRaid raid) + { + super(raid, "Rapid Escape"); + + _altar = raid.getWorldData().getCustomLocs("MAIN_ALTAR").get(0); + } + + private void teleportIn() + { + getRaid().getPlayers().forEach(player -> + { + UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Run!")); + player.teleport(getRaid().getWorldData().getCustomLocs("C_FIVE_ENTER").get(0)); + }); + } + + @Override + public void customStart() + { + int i = 1; + while (getRaid().getWorldData().getAllCustomLocs().containsKey("C_FIVE_G" + i)) + { + List> creatures = new ArrayList<>(); + for (Location loc : getRaid().getWorldData().getCustomLocs("C_FIVE_G" + i + "G")) + { + int type = UtilMath.r(3) + 1; + if (type == 1) + { + UndeadKnight knight = new UndeadKnight(this, loc); + getRaid().registerCreature(knight); + creatures.add(knight); + } + if (type == 2) + { + ReanimatedCorpse corpse = new ReanimatedCorpse(this, loc); + getRaid().registerCreature(corpse); + creatures.add(corpse); + } + if (type == 3) + { + DecayingArcher archer = new DecayingArcher(this, loc); + getRaid().registerCreature(archer); + creatures.add(archer); + } + } + _gates.add(new IronGate(this, getRaid().getWorldData().getCustomLocs("C_FIVE_G" + i), creatures)); + i++; + } + _goliath = new Goliath(this, getRaid().getWorldData().getCustomLocs("C_FIVE_GIANT").get(0)); + getRaid().registerCreature(_goliath); + getRaid().getPlayers().forEach(player -> UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Use the third gate!"))); + } + + @SuppressWarnings("deprecation") + @Override + public void customComplete() + { + getRaid().getPlayers().forEach(player -> + { + UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "You made it!")); + player.teleport(_altar); + }); + getRaid().getWorldData().getCustomLocs("GATE_THREE").get(0).getBlock().getRelative(BlockFace.DOWN).setType(Material.OBSIDIAN); + Block gate = getRaid().getWorldData().getCustomLocs("GATE_FOUR").get(0).getBlock(); + gate.getRelative(BlockFace.DOWN).setType(Material.GLOWSTONE); + gate.setType(Material.SKULL); + gate.setData((byte)1); + _altar.getWorld().dropItem(_altar.clone().add(0, 2, 0), new ItemStack(Material.EMERALD, UtilMath.rRange(15, 17))); + } + + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() == UpdateType.SEC) + { + for (Player player : getRaid().getPlayers()) + { + if (UtilMath.offset(player.getLocation(), getRaid().getWorldData().getCustomLocs("C_FIVE_EXIT").get(0)) <= 3) + { + complete(); + return; + } + } + } + if (event.getType() == UpdateType.TICK) + { + if (!_gates.isEmpty() && _teleported) + { + IronGate gate = _gates.peek(); + if (UtilMath.offset2d(_goliath.getEntity().getLocation(), gate.getCenter()) > 5) + { + Location to = gate.getCenter().clone(); + to.setY(_goliath.getEntity().getLocation().getY()); + _goliath.getEntity().setVelocity(UtilAlg.getTrajectory(_goliath.getEntity().getLocation(), to).normalize().multiply(0.15)); + } + if (gate.update()) + { + _gates.poll(); + } + } + } + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) + { + if (!event.hasBlock()) + { + return; + } + + Block clicked = event.getClickedBlock(); + if (!_teleported) + { + if (clicked.equals(getRaid().getWorldData().getCustomLocs("GATE_THREE").get(0).getBlock()) || clicked.equals(getRaid().getWorldData().getCustomLocs("GATE_THREE").get(0).getBlock().getRelative(BlockFace.DOWN))) + { + _teleported = true; + teleportIn(); + } + } + } + + @EventHandler + public void onIcePrison(SkillTriggerEvent event) + { + if (getRaid().getPlayers().contains(event.GetPlayer()) && _teleported && (event.GetSkillName().equals("Ice Prison") || event.GetSkillName().equals("Fissure"))) + { + event.SetCancelled(true); + } + } + + @EventHandler + public void onDeath(EventCreatureDeathEvent event) + { + if (event.getCreature().getEvent() instanceof WitherRaid) + { + if (((WitherRaid)event.getCreature().getEvent()).getId() == getRaid().getId()) + { + _gates.forEach(gate -> gate.handleDeath(event.getCreature())); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/five/IronGate.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/five/IronGate.java new file mode 100644 index 000000000..b0a0964d5 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/five/IronGate.java @@ -0,0 +1,79 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.challenge.five; + +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; + +import mineplex.game.clans.clans.worldevent.api.EventCreature; + +public class IronGate +{ + private ChallengeFive _challenge; + private List _corners; + private List> _guardians; + + public IronGate(ChallengeFive challenge, List corners, List> guardians) + { + _challenge = challenge; + _corners = corners; + _guardians = guardians; + } + + private void open() + { + Location pos1 = _corners.get(0); + Location pos2 = _corners.get(1); + int minX = Math.min(pos1.getBlockX(), pos2.getBlockX()); + int maxX = Math.max(pos1.getBlockX(), pos2.getBlockX()); + int minY = Math.min(pos1.getBlockY(), pos2.getBlockY()); + int maxY = Math.max(pos1.getBlockY(), pos2.getBlockY()) + 3; + int minZ = Math.min(pos1.getBlockZ(), pos2.getBlockZ()); + int maxZ = Math.max(pos1.getBlockZ(), pos2.getBlockZ()); + + for (int x = minX; x <= maxX; x++) + { + for (int y = minY; y <= maxY; y++) + { + for (int z = minZ; z <= maxZ; z++) + { + Block block = _challenge.getRaid().getWorldData().World.getBlockAt(x, y, z); + if (block.getType() == Material.IRON_FENCE) + { + block.setType(Material.AIR); + } + } + } + } + } + + public Location getCenter() + { + Location pos1 = _corners.get(0); + Location pos2 = _corners.get(1); + int minX = Math.min(pos1.getBlockX(), pos2.getBlockX()); + int maxX = Math.max(pos1.getBlockX(), pos2.getBlockX()); + int minY = Math.min(pos1.getBlockY(), pos2.getBlockY()); + int maxY = Math.max(pos1.getBlockY(), pos2.getBlockY()) + 3; + int minZ = Math.min(pos1.getBlockZ(), pos2.getBlockZ()); + int maxZ = Math.max(pos1.getBlockZ(), pos2.getBlockZ()); + + return new Location(_challenge.getRaid().getWorldData().World, minX + ((maxX - minX) / 2), minY + ((maxY - minY) / 2), minZ + ((maxZ - minZ) / 2)); + } + + public boolean update() + { + if (_guardians.size() < 1) + { + open(); + return true; + } + return false; + } + + public void handleDeath(EventCreature creature) + { + _guardians.remove(creature); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/four/ChallengeFour.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/four/ChallengeFour.java new file mode 100644 index 000000000..bfb9cb879 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/four/ChallengeFour.java @@ -0,0 +1,131 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.challenge.four; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.F; +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.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.minecraft.game.classcombat.Skill.event.SkillTriggerEvent; + +public class ChallengeFour extends RaidChallenge +{ + private Location _altar; + private boolean _teleported = false; + private List _blocks = new ArrayList<>(); + private double[] _damageYRange = new double[2]; + + public ChallengeFour(WitherRaid raid) + { + super(raid, "Infested Pits"); + + _altar = raid.getWorldData().getCustomLocs("MAIN_ALTAR").get(0); + } + + private void teleportIn() + { + getRaid().getPlayers().forEach(player -> + { + UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Complete the parkour!")); + player.teleport(getRaid().getWorldData().getCustomLocs("C_FOUR_ENTER").get(0)); + }); + } + + @Override + public void customStart() + { + for (Location loc : getRaid().getWorldData().getCustomLocs("C_FOUR_FB")) + { + loc.getBlock().setType(Material.NETHER_BRICK); + _blocks.add(new FakeBlock(this, loc.getBlock())); + } + getRaid().getPlayers().forEach(player -> UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Use the second gate!"))); + Location pos1 = getRaid().getWorldData().getCustomLocs("C_FOUR_SF").get(0); + Location pos2 = getRaid().getWorldData().getCustomLocs("C_FOUR_SF").get(1); + _damageYRange[0] = Math.min(pos1.getY(), pos2.getY()); + _damageYRange[1] = Math.max(pos1.getY(), pos2.getY()); + } + + @SuppressWarnings("deprecation") + @Override + public void customComplete() + { + getRaid().getPlayers().forEach(player -> + { + UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Excellent jumping!")); + player.teleport(_altar); + }); + getRaid().getWorldData().getCustomLocs("GATE_TWO").get(0).getBlock().getRelative(BlockFace.DOWN).setType(Material.OBSIDIAN); + Block gate = getRaid().getWorldData().getCustomLocs("GATE_THREE").get(0).getBlock(); + gate.getRelative(BlockFace.DOWN).setType(Material.GLOWSTONE); + gate.setType(Material.SKULL); + gate.setData((byte)1); + _altar.getWorld().dropItem(_altar.clone().add(0, 2, 0), new ItemStack(Material.EMERALD, UtilMath.rRange(13, 17))); + } + + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() == UpdateType.SEC && _teleported) + { + for (Player player : getRaid().getPlayers()) + { + if (UtilMath.offset(player.getLocation(), getRaid().getWorldData().getCustomLocs("C_FOUR_EXIT").get(0)) <= 3) + { + complete(); + return; + } + if (player.getLocation().getY() <= _damageYRange[1] && player.getLocation().getY() >= _damageYRange[0]) + { + getRaid().getDamageManager().NewDamageEvent(player, null, null, DamageCause.LAVA, 1, false, true, true, "Burning Cavern", "Hot Ground"); + } + } + } + if (event.getType() == UpdateType.TICK) + { + _blocks.forEach(FakeBlock::update); + } + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) + { + if (!event.hasBlock()) + { + return; + } + + Block clicked = event.getClickedBlock(); + if (!_teleported) + { + if (clicked.equals(getRaid().getWorldData().getCustomLocs("GATE_TWO").get(0).getBlock()) || clicked.equals(getRaid().getWorldData().getCustomLocs("GATE_TWO").get(0).getBlock().getRelative(BlockFace.DOWN))) + { + _teleported = true; + teleportIn(); + } + } + } + + @EventHandler + public void onIcePrison(SkillTriggerEvent event) + { + if (getRaid().getPlayers().contains(event.GetPlayer()) && _teleported) + { + event.SetCancelled(true); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/four/FakeBlock.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/four/FakeBlock.java new file mode 100644 index 000000000..55793d72d --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/four/FakeBlock.java @@ -0,0 +1,38 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.challenge.four; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; + +public class FakeBlock +{ + private ChallengeFour _challenge; + private Block _block; + + public FakeBlock(ChallengeFour challenge, Block block) + { + _challenge = challenge; + _block = block; + _block.setType(Material.NETHER_BRICK); + } + + public void update() + { + boolean aired = false; + for (Player player : _challenge.getRaid().getPlayers()) + { + if (player.getLocation().getBlock().getRelative(BlockFace.DOWN).equals(_block)) + { + _block.setType(Material.AIR); + aired = true; + break; + } + } + + if (!aired) + { + _block.setType(Material.NETHER_BRICK); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/one/ChallengeOne.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/one/ChallengeOne.java new file mode 100644 index 000000000..57c1fa0af --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/one/ChallengeOne.java @@ -0,0 +1,104 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.challenge.one; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; + +import mineplex.core.common.util.F; +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.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; + +public class ChallengeOne extends RaidChallenge +{ + private Location _altar; + private Player _trigger; + + public ChallengeOne(WitherRaid raid) + { + super(raid, "Entering Hell"); + + _altar = raid.getWorldData().getCustomLocs("MAIN_ALTAR").get(0); + } + + private void sealDoor() + { + Location doorBase1 = getRaid().getWorldData().getCustomLocs("C_ONE_TRAP").get(0); + Location doorBase2 = getRaid().getWorldData().getCustomLocs("C_ONE_TRAP").get(1); + int minX = Math.min(doorBase1.getBlockX(), doorBase2.getBlockX()); + int maxX = Math.max(doorBase1.getBlockX(), doorBase2.getBlockX()); + int minY = Math.min(doorBase1.getBlockY(), doorBase2.getBlockY()); + int maxY = Math.max(doorBase1.getBlockY(), doorBase2.getBlockY()) + 1; + int minZ = Math.min(doorBase1.getBlockZ(), doorBase2.getBlockZ()); + int maxZ = Math.max(doorBase1.getBlockZ(), doorBase2.getBlockZ()); + + for (int x = minX; x <= maxX; x++) + { + for (int y = minY; y <= maxY; y++) + { + for (int z = minZ; z <= maxZ; z++) + { + Block block = getRaid().getWorldData().World.getBlockAt(x, y, z); + block.setType(Material.NETHER_BRICK); + } + } + } + } + + private void setupStoneBrickTraps() + { + for (Location loc : getRaid().getWorldData().getCustomLocs("C_ONE_SBT")) + { + Block b = loc.getBlock(); + b.setType(Material.SMOOTH_BRICK); + b.getRelative(BlockFace.UP).setType(Material.SMOOTH_BRICK); + } + } + + @Override + public void customStart() + { + setupStoneBrickTraps(); + getRaid().getPlayers().forEach(player -> UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Enter the Altar Room"))); + } + + @Override + public void customComplete() + { + getRaid().getPlayers().forEach(player -> + { + player.getWorld().strikeLightningEffect(player.getLocation()); + if (_trigger != null) + { + if (UtilMath.offset(player.getLocation(), _altar) >= 17) + { + player.teleport(_trigger); + } + } + }); + sealDoor(); + } + + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() == UpdateType.SEC) + { + for (Player player : getRaid().getPlayers()) + { + if (UtilMath.offset(player.getLocation(), _altar) <= 10) + { + _trigger = player; + complete(); + return; + } + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/seven/ChallengeSeven.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/seven/ChallengeSeven.java new file mode 100644 index 000000000..193a2fb37 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/seven/ChallengeSeven.java @@ -0,0 +1,175 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.challenge.seven; + +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilShapes; +import mineplex.core.common.util.UtilTime; +import mineplex.core.common.util.UtilTime.TimeUnit; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.worldevent.api.EventCreatureDeathEvent; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.mage.UndeadKnight; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.wither.CharlesWitherton; +import mineplex.game.clans.items.ItemType; +import mineplex.game.clans.items.RareItemFactory; +import mineplex.game.clans.items.attributes.weapon.ConqueringAttribute; +import mineplex.game.clans.items.attributes.weapon.FlamingAttribute; +import mineplex.game.clans.items.attributes.weapon.SharpAttribute; +import mineplex.game.clans.items.legendaries.DemonicScythe; + +public class ChallengeSeven extends RaidChallenge +{ + private Location _altar; + private boolean _teleported = false; + private boolean _bottomLayer = false; + private CharlesWitherton _charlie; + private long _lastKnightRespawn; + + public ChallengeSeven(WitherRaid raid) + { + super(raid, "The Final Battle"); + + _altar = raid.getWorldData().getCustomLocs("MAIN_ALTAR").get(0); + } + + private void teleportToBottom() + { + _charlie.getEntity().teleport(getRaid().getWorldData().getCustomLocs("C_SEVEN_RWC").get(0)); + for (Player player : getRaid().getPlayers()) + { + player.teleport(getRaid().getWorldData().getCustomLocs("C_SEVEN_RWC").get(0)); + } + } + + private void teleportIn() + { + getRaid().getPlayers().forEach(player -> + { + UtilPlayer.message(player, F.main(getRaid().getName(), "GUARDS! ATTACK!")); + player.teleport(getRaid().getWorldData().getCustomLocs("C_SEVEN_ENTER").get(0)); + }); + for (Location loc : getRaid().getWorldData().getCustomLocs("C_SEVEN_UK")) + { + getRaid().registerCreature(new UndeadKnight(this, loc)); + } + _lastKnightRespawn = System.currentTimeMillis(); + _charlie = new CharlesWitherton(this, getRaid().getWorldData().getCustomLocs("C_SEVEN_CHARLES").get(0)); + getRaid().registerCreature(_charlie); + for (Location loc : getRaid().getWorldData().getCustomLocs("C_SEVEN_UK")) + { + getRaid().registerCreature(new UndeadKnight(this, loc)); + } + } + + @Override + public void customStart() + { + getRaid().getPlayers().forEach(player -> UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Use the final gate!"))); + } + + @Override + public void customComplete() + { + getRaid().getPlayers().forEach(player -> + { + UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "The evil reign of Charles Witherton is over! You will be returned to spawn in 2 minutes!")); + player.teleport(_altar); + }); + List anim = UtilShapes.getPointsInCircle(_altar.clone().add(0, 2, 0), 5, 3); + int emeralds = UtilMath.rRange((int)Math.ceil(45 / anim.size()), (int)Math.ceil(80 / anim.size())); + for (Location drop : anim) + { + ClansManager.getInstance().getLootManager().dropRare(drop); + drop.getWorld().dropItem(drop, new ItemStack(Material.EMERALD, emeralds)); + } + RareItemFactory mainFactory = RareItemFactory.begin(ItemType.LEGENDARY).setLegendary(DemonicScythe.class); + if (Math.random() < 0.1) + { + mainFactory.setSuperPrefix(FlamingAttribute.class); + mainFactory.setPrefix(SharpAttribute.class); + mainFactory.setSuffix(ConqueringAttribute.class); + } + _altar.getWorld().dropItem(_altar.clone().add(0, 2, 0), mainFactory.fabricate()); + getRaid().getWorldData().getCustomLocs("GATE_FIVE").get(0).getBlock().getRelative(BlockFace.DOWN).setType(Material.OBSIDIAN); + getRaid().setForceEnd(System.currentTimeMillis() + UtilTime.convert(2, TimeUnit.MINUTES, TimeUnit.MILLISECONDS)); + } + + @EventHandler + public void onDeath(EventCreatureDeathEvent event) + { + if (event.getCreature() instanceof CharlesWitherton) + { + if (((WitherRaid)event.getCreature().getEvent()).getId() == getRaid().getId()) + { + complete(); + } + } + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) + { + if (!event.hasBlock()) + { + return; + } + + Block clicked = event.getClickedBlock(); + if (!_teleported) + { + if (clicked.equals(getRaid().getWorldData().getCustomLocs("GATE_FIVE").get(0).getBlock()) || clicked.equals(getRaid().getWorldData().getCustomLocs("GATE_FIVE").get(0).getBlock().getRelative(BlockFace.DOWN))) + { + _teleported = true; + teleportIn(); + } + } + } + + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() == UpdateType.SEC) + { + if (_teleported && !_bottomLayer && _charlie != null) + { + if (_charlie.getHealthPercent() <= 0.75) + { + _bottomLayer = true; + teleportToBottom(); + return; + } + + if (UtilTime.elapsed(_lastKnightRespawn, 30000)) + { + _lastKnightRespawn = System.currentTimeMillis(); + long knights = getRaid().getCreatures().stream().filter(UndeadKnight.class::isInstance).count(); + int total = getRaid().getWorldData().getCustomLocs("C_SEVEN_UK").size(); + if (knights < total) + { + long needed = total - knights; + for (int i = 0; i < needed; i++) + { + Location loc = getRaid().getWorldData().getCustomLocs("C_SEVEN_UK").get(i); + getRaid().registerCreature(new UndeadKnight(this, loc)); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/six/ChallengeSix.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/six/ChallengeSix.java new file mode 100644 index 000000000..46d3526b3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/six/ChallengeSix.java @@ -0,0 +1,94 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.challenge.six; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.clans.worldevent.api.EventCreatureDeathEvent; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.magma.Magmus; + +public class ChallengeSix extends RaidChallenge +{ + private Location _altar; + private boolean _teleported = false; + + public ChallengeSix(WitherRaid raid) + { + super(raid, "Fiery Gates"); + + _altar = raid.getWorldData().getCustomLocs("MAIN_ALTAR").get(0); + } + + private void teleportIn() + { + getRaid().getPlayers().forEach(player -> + { + UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Slay the gatekeeper or perish!")); + player.teleport(getRaid().getWorldData().getCustomLocs("C_SIX_ENTER").get(0)); + }); + getRaid().registerCreature(new Magmus(this, getRaid().getWorldData().getCustomLocs("C_SIX_MCS").get(0))); + } + + @Override + public void customStart() + { + getRaid().getPlayers().forEach(player -> UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Use the fourth gate!"))); + } + + @SuppressWarnings("deprecation") + @Override + public void customComplete() + { + getRaid().getPlayers().forEach(player -> + { + UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Your final battle awaits!")); + player.teleport(_altar); + }); + getRaid().getWorldData().getCustomLocs("GATE_FOUR").get(0).getBlock().getRelative(BlockFace.DOWN).setType(Material.OBSIDIAN); + Block gate = getRaid().getWorldData().getCustomLocs("GATE_FIVE").get(0).getBlock(); + gate.getRelative(BlockFace.DOWN).setType(Material.GLOWSTONE); + gate.setType(Material.SKULL); + gate.setData((byte)1); + _altar.getWorld().dropItem(_altar.clone().add(0, 2, 0), new ItemStack(Material.EMERALD, UtilMath.rRange(15, 20))); + } + + @EventHandler + public void onDeath(EventCreatureDeathEvent event) + { + if (event.getCreature() instanceof Magmus) + { + if (((WitherRaid)event.getCreature().getEvent()).getId() == getRaid().getId()) + { + complete(); + } + } + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) + { + if (!event.hasBlock()) + { + return; + } + + Block clicked = event.getClickedBlock(); + if (!_teleported) + { + if (clicked.equals(getRaid().getWorldData().getCustomLocs("GATE_FOUR").get(0).getBlock()) || clicked.equals(getRaid().getWorldData().getCustomLocs("GATE_FOUR").get(0).getBlock().getRelative(BlockFace.DOWN))) + { + _teleported = true; + teleportIn(); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/three/ChallengeThree.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/three/ChallengeThree.java new file mode 100644 index 000000000..260e59321 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/three/ChallengeThree.java @@ -0,0 +1,135 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.challenge.three; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.archer.DecayingArcher; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.corpse.ReanimatedCorpse; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.mage.UndeadMage; + +public class ChallengeThree extends RaidChallenge +{ + private Location _altar; + private boolean _teleported = false; + private List _torches = new ArrayList<>(); + protected int LitTorches; + private long _lastSpawn; + private int _spawnTotal; + + public ChallengeThree(WitherRaid raid) + { + super(raid, "Light The Fires"); + + _altar = raid.getWorldData().getCustomLocs("MAIN_ALTAR").get(0); + LitTorches = 0; + } + + private void teleportIn() + { + getRaid().getPlayers().forEach(player -> + { + UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Light the torches!")); + player.teleport(getRaid().getWorldData().getCustomLocs("C_THREE_ENTER").get(0)); + }); + getRaid().registerCreature(new UndeadMage(this, getRaid().getWorldData().getCustomLocs("C_THREE_UM").get(0), true, getRaid().getWorldData().getCustomLocs("C_THREE_UMS"), getRaid().getWorldData().getCustomLocs("C_THREE_UMT"))); + } + + @Override + public void customStart() + { + for (Location loc : getRaid().getWorldData().getCustomLocs("C_THREE_TORCH")) + { + loc.getBlock().setType(Material.NETHERRACK); + _torches.add(new ChallengeTorch(this, loc.getBlock())); + } + getRaid().getPlayers().forEach(player -> UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "Use the first gate!"))); + } + + @SuppressWarnings("deprecation") + @Override + public void customComplete() + { + getRaid().getPlayers().forEach(player -> + { + UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "The Torches are lit!")); + player.teleport(_altar); + }); + getRaid().getWorldData().getCustomLocs("GATE_ONE").get(0).getBlock().getRelative(BlockFace.DOWN).setType(Material.OBSIDIAN); + Block gate = getRaid().getWorldData().getCustomLocs("GATE_TWO").get(0).getBlock(); + gate.getRelative(BlockFace.DOWN).setType(Material.GLOWSTONE); + gate.setType(Material.SKULL); + gate.setData((byte)1); + _altar.getWorld().dropItem(_altar.clone().add(0, 2, 0), new ItemStack(Material.EMERALD, UtilMath.rRange(10, 15))); + } + + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() == UpdateType.SEC) + { + if (LitTorches >= 4) + { + complete(); + } + } + if (event.getType() == UpdateType.TICK) + { + _torches.forEach(ChallengeTorch::update); + if (UtilTime.elapsed(_lastSpawn, 7000) && _teleported) + { + _lastSpawn = System.currentTimeMillis(); + if (_spawnTotal > 100) + { + return; + } + getRaid().getWorldData().getCustomLocs("C_THREE_RC").forEach(loc -> + { + _spawnTotal++; + getRaid().registerCreature(new ReanimatedCorpse(this, loc)); + }); + getRaid().getWorldData().getCustomLocs("C_THREE_DA").forEach(loc -> + { + _spawnTotal++; + getRaid().registerCreature(new DecayingArcher(this, loc)); + }); + } + } + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) + { + if (!event.hasBlock()) + { + return; + } + + Block clicked = event.getClickedBlock(); + if (!_teleported) + { + if (clicked.equals(getRaid().getWorldData().getCustomLocs("GATE_ONE").get(0).getBlock()) || clicked.equals(getRaid().getWorldData().getCustomLocs("GATE_ONE").get(0).getBlock().getRelative(BlockFace.DOWN))) + { + _lastSpawn = System.currentTimeMillis(); + _teleported = true; + teleportIn(); + } + } + _torches.forEach(torch -> torch.handleInteract(clicked)); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/three/ChallengeTorch.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/three/ChallengeTorch.java new file mode 100644 index 000000000..90b6e0a4e --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/three/ChallengeTorch.java @@ -0,0 +1,42 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.challenge.three; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +public class ChallengeTorch +{ + private ChallengeThree _challenge; + private Block _block; + private long _extinguish; + + public ChallengeTorch(ChallengeThree challenge, Block block) + { + _challenge = challenge; + _block = block; + _extinguish = -1; + } + + public void handleInteract(Block block) + { + if (block.equals(_block) && _extinguish == -1) + { + _challenge.LitTorches++; + _extinguish = System.currentTimeMillis() + 3000; + _block.getRelative(BlockFace.UP).setType(Material.FIRE); + } + } + + public void update() + { + if (_extinguish != -1 && !_challenge.isComplete()) + { + if (_extinguish < System.currentTimeMillis()) + { + _extinguish = -1; + _challenge.LitTorches--; + _block.getRelative(BlockFace.UP).setType(Material.AIR); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/two/ChallengeTwo.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/two/ChallengeTwo.java new file mode 100644 index 000000000..a18665263 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/challenge/two/ChallengeTwo.java @@ -0,0 +1,72 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.challenge.two; + +import org.bukkit.DyeColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.event.EventHandler; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.clans.worldevent.api.EventCreatureDeathEvent; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.mage.UndeadKnight; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.mage.UndeadMage; + +public class ChallengeTwo extends RaidChallenge +{ + private Location _altar; + + public ChallengeTwo(WitherRaid raid) + { + super(raid, "Undead Encounter"); + + _altar = raid.getWorldData().getCustomLocs("MAIN_ALTAR").get(0); + } + + private void openStoneBrickTraps() + { + for (Location loc : getRaid().getWorldData().getCustomLocs("C_ONE_SBT")) + { + Block b = loc.getBlock(); + b.setType(Material.AIR); + b.getRelative(BlockFace.UP).setType(Material.AIR); + getRaid().registerCreature(new UndeadKnight(this, loc)); + } + } + + @SuppressWarnings("deprecation") + @Override + public void customStart() + { + openStoneBrickTraps(); + _altar.getBlock().getRelative(BlockFace.DOWN).setData(DyeColor.BLACK.getWoolData()); + getRaid().getPlayers().forEach(player -> UtilPlayer.message(player, F.main("Undead Mage", "MINIONS, ATTACK!"))); + getRaid().registerCreature(new UndeadMage(this, _altar, false, getRaid().getWorldData().getCustomLocs("C_ONE_SBT"), getRaid().getWorldData().getCustomLocs("C_TWO_MTP"))); + } + + @SuppressWarnings("deprecation") + @Override + public void customComplete() + { + getRaid().getPlayers().forEach(player -> UtilPlayer.message(player, F.main(getRaid().getName() + " Raid", "The Undead Mage has fallen!"))); + Block gate = getRaid().getWorldData().getCustomLocs("GATE_ONE").get(0).getBlock(); + gate.getRelative(BlockFace.DOWN).setType(Material.GLOWSTONE); + gate.setType(Material.SKULL); + gate.setData((byte)1); + } + + @EventHandler + public void onDeath(EventCreatureDeathEvent event) + { + if (event.getCreature() instanceof UndeadMage) + { + if (((WitherRaid)event.getCreature().getEvent()).getId() == getRaid().getId()) + { + complete(); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/archer/ArcherShooting.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/archer/ArcherShooting.java new file mode 100644 index 000000000..9bf61cb22 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/archer/ArcherShooting.java @@ -0,0 +1,95 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.archer; + +import org.bukkit.entity.Arrow; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossAbility; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class ArcherShooting extends BossAbility +{ + private long _lastShoot; + private long _lastRope; + + public ArcherShooting(DecayingArcher creature) + { + super(creature); + + _lastShoot = System.currentTimeMillis(); + _lastRope = System.currentTimeMillis(); + } + + @Override + public void tick() + { + if (getEntity().getTarget() != null && getEntity().getTarget() instanceof Player) + { + if (UtilTime.elapsed(_lastRope, 10000)) + { + _lastRope = System.currentTimeMillis(); + UtilEnt.LookAt(getEntity(), getEntity().getTarget().getEyeLocation()); + UtilEnt.addFlag(getEntity().launchProjectile(Arrow.class), "ROPED_ARROW"); + return; + } + if (UtilTime.elapsed(_lastShoot, 2000)) + { + _lastShoot = System.currentTimeMillis(); + UtilEnt.LookAt(getEntity(), getEntity().getTarget().getEyeLocation()); + getEntity().launchProjectile(Arrow.class); + } + } + } + + @EventHandler + public void onDamage(CustomDamageEvent event) + { + if (event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE) == null) + { + return; + } + LivingEntity ent = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + if (ent.getEntityId() == getEntity().getEntityId()) + { + if (event.GetCause() != DamageCause.PROJECTILE) + { + event.SetCancelled("Archer Only"); + return; + } + if (UtilEnt.hasFlag(event.GetProjectile(), "ROPED_ARROW")) + { + ent.setVelocity(UtilAlg.getTrajectory(ent, event.GetDamageeEntity()).normalize()); + event.AddMod("Roped Arrow", -event.GetDamage()); + return; + } + event.AddMod("Ranged Attack", 2 - event.GetDamage()); + } + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public boolean inProgress() + { + return false; + } + + @Override + public boolean hasFinished() + { + return false; + } + + @Override + public void setFinished() {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/archer/DecayingArcher.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/archer/DecayingArcher.java new file mode 100644 index 000000000..e7215b1a3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/archer/DecayingArcher.java @@ -0,0 +1,86 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.archer; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.RaidCreature; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class DecayingArcher extends RaidCreature +{ + private RaidChallenge _challenge; + private ArcherShooting _passive; + + public DecayingArcher(RaidChallenge challenge, Location location) + { + super(challenge.getRaid(), location, "Decaying Archer", true, 10, 100, true, Zombie.class); + + _challenge = challenge; + spawnEntity(); + _passive = new ArcherShooting(this); + } + + @Override + protected void spawnCustom() + { + getEntity().getEquipment().setItemInHand(new ItemStack(Material.BOW)); + getEntity().getEquipment().setItemInHandDropChance(0f); + } + + @Override + public void dieCustom() + { + endAbility(); + } + + private void endAbility() + { + HandlerList.unregisterAll(_passive); + _passive = null; + } + + @EventHandler + public void onTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_challenge.isComplete()) + { + remove(); + return; + } + + _passive.tick(); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void allyDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + if (damager != null && !(damager instanceof Player)) + { + event.SetCancelled("Allied Damage"); + } + } + } + + @Override + public void handleDeath(Location location) {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/corpse/CorpsePassive.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/corpse/CorpsePassive.java new file mode 100644 index 000000000..f08d0ed32 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/corpse/CorpsePassive.java @@ -0,0 +1,43 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.corpse; + +import org.bukkit.entity.Zombie; +import org.bukkit.event.EventHandler; + +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class CorpsePassive extends BossPassive +{ + public CorpsePassive(ReanimatedCorpse creature) + { + super(creature); + } + + @Override + public int getCooldown() + { + return 0; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() {} + + @EventHandler + public void onDamage(CustomDamageEvent event) + { + if (event.GetDamagerEntity(false) == null) + { + return; + } + if (event.GetDamagerEntity(false).getEntityId() == getEntity().getEntityId()) + { + event.AddMod("Corpse Attack", 1 - event.GetDamage()); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/corpse/ReanimatedCorpse.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/corpse/ReanimatedCorpse.java new file mode 100644 index 000000000..e09e61ea2 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/corpse/ReanimatedCorpse.java @@ -0,0 +1,88 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.corpse; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Zombie; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.RaidCreature; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class ReanimatedCorpse extends RaidCreature +{ + private static final Material[] SWORDS = {Material.WOOD_SWORD, Material.STONE_SWORD, Material.GOLD_SWORD, Material.IRON_SWORD, Material.DIAMOND_SWORD}; + private RaidChallenge _challenge; + private CorpsePassive _passive; + + public ReanimatedCorpse(RaidChallenge challenge, Location location) + { + super(challenge.getRaid(), location, "Reanimated Corpse", true, 15, 100, true, Zombie.class); + + _challenge = challenge; + spawnEntity(); + _passive = new CorpsePassive(this); + } + + @Override + protected void spawnCustom() + { + getEntity().getEquipment().setItemInHand(new ItemStack(UtilMath.randomElement(SWORDS))); + getEntity().getEquipment().setItemInHandDropChance(0f); + } + + @Override + public void dieCustom() + { + endAbility(); + } + + private void endAbility() + { + HandlerList.unregisterAll(_passive); + _passive = null; + } + + @EventHandler + public void onTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_challenge.isComplete()) + { + remove(); + return; + } + + _passive.tick(); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void allyDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + if (damager != null && !(damager instanceof Player)) + { + event.SetCancelled("Allied Damage"); + } + } + } + + @Override + public void handleDeath(Location location) {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/giant/Goliath.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/giant/Goliath.java new file mode 100644 index 000000000..1920ef4aa --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/giant/Goliath.java @@ -0,0 +1,80 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.giant; + +import org.bukkit.Location; +import org.bukkit.entity.Giant; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.RaidCreature; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class Goliath extends RaidCreature +{ + private RaidChallenge _challenge; + private GoliathPassive _passive; + + public Goliath(RaidChallenge challenge, Location location) + { + super(challenge.getRaid(), location, "Goliath", true, 5000, 500, true, Giant.class); + + _challenge = challenge; + spawnEntity(); + _passive = new GoliathPassive(this); + } + + @Override + protected void spawnCustom() {} + + @Override + public void dieCustom() + { + endAbility(); + } + + private void endAbility() + { + HandlerList.unregisterAll(_passive); + _passive = null; + } + + @EventHandler + public void onTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_challenge.isComplete()) + { + remove(); + return; + } + + _passive.tick(); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void allyDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + if (damager != null && !(damager instanceof Player)) + { + event.SetCancelled("Allied Damage"); + } + } + } + + @Override + public void handleDeath(Location location) {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/giant/GoliathPassive.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/giant/GoliathPassive.java new file mode 100644 index 000000000..1551a9fc9 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/giant/GoliathPassive.java @@ -0,0 +1,60 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.giant; + +import org.bukkit.entity.Giant; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class GoliathPassive extends BossPassive +{ + public GoliathPassive(Goliath creature) + { + super(creature); + } + + @Override + public int getCooldown() + { + return 0; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + for (Player player : ((WitherRaid)getBoss().getEvent()).getPlayers()) + { + if (UtilPlayer.isSpectator(player) || player.isDead() || !player.isValid()) + { + continue; + } + if (UtilMath.offset(getEntity(), player) <= 7) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getEntity(), null, DamageCause.ENTITY_ATTACK, 100, false, true, true, getEntity().getName(), "Smash"); + } + } + } + + @EventHandler + public void onDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity() != null) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + event.SetCancelled("Giant Invulnerability"); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/KnightPassive.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/KnightPassive.java new file mode 100644 index 000000000..825254c8b --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/KnightPassive.java @@ -0,0 +1,67 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.mage; + +import org.bukkit.entity.Skeleton; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityShootBowEvent; + +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class KnightPassive extends BossPassive +{ + private long _lastUsed; + + public KnightPassive(UndeadKnight creature) + { + super(creature); + + _lastUsed = System.currentTimeMillis(); + } + + @Override + public int getCooldown() + { + return 12; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() {} + + @EventHandler + public void onDamage(CustomDamageEvent event) + { + if (event.GetDamagerEntity(false) == null) + { + return; + } + if (event.GetDamagerEntity(false).getEntityId() == getEntity().getEntityId()) + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + _lastUsed = System.currentTimeMillis(); + event.AddMod("Hilt Smash", 4 - event.GetDamage()); + getBoss().getEvent().getCondition().Factory().Slow("Hilt Smash", event.GetDamageeEntity(), event.GetDamagerEntity(false), 2, 1, false, true, false, true); + } + else + { + event.AddMod("Knight Attack", 4 - event.GetDamage()); + } + } + } + + @EventHandler + public void onShoot(EntityShootBowEvent event) + { + if (event.getEntity().getEntityId() == getEntity().getEntityId()) + { + event.setCancelled(true); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageBlink.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageBlink.java new file mode 100644 index 000000000..2974f216d --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageBlink.java @@ -0,0 +1,67 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.mage; + +import java.util.List; +import java.util.stream.Collectors; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; + +public class MageBlink extends BossPassive +{ + private List _spots; + private long _lastUsed; + + public MageBlink(UndeadMage creature, List teleportSpots) + { + super(creature); + + _spots = teleportSpots; + _lastUsed = System.currentTimeMillis(); + } + + @Override + public int getCooldown() + { + return 7; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + _lastUsed = System.currentTimeMillis(); + List tp = null; + if (_spots != null) + { + tp = _spots.stream().filter(spot -> UtilMath.offset(getLocation(), spot) <= 10).collect(Collectors.toList()); + } + else + { + tp = getBoss().getPlayers(UtilPlayer.getInRadius(getLocation(), 10), 10).stream().map(Player::getLocation).collect(Collectors.toList()); + } + if (tp != null && !tp.isEmpty()) + { + Location to = UtilMath.randomElement(tp); + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getEntity().getLocation(), null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, to, null, 0, 2, ViewDist.MAX); + getEntity().teleport(to); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageBolt.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageBolt.java new file mode 100644 index 000000000..71f6d6944 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageBolt.java @@ -0,0 +1,86 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.mage; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; + +public class MageBolt extends BossPassive +{ + private static final double RANGE = 10; + private long _lastUsed; + + public MageBolt(UndeadMage creature) + { + super(creature); + _lastUsed = System.currentTimeMillis(); + } + + private void shootBolt(Player target) + { + double curRange = 0; + boolean canHit = true; + + while (curRange <= RANGE) + { + Location newTarget = getEntity().getEyeLocation().add(UtilAlg.getTrajectory(getEntity(), target).multiply(curRange)); + + if (!UtilBlock.airFoliage(newTarget.getBlock())) + { + canHit = false; + break; + } + if (UtilMath.offset(newTarget, target.getLocation()) <= 0.9) + { + break; + } + + curRange += 0.2; + + UtilParticle.PlayParticle(ParticleType.WITCH_MAGIC, newTarget, 0, 0, 0, 0, 1, + ViewDist.MAX, UtilServer.getPlayers()); + } + + if (canHit) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(target, getEntity(), null, DamageCause.CUSTOM, 5, true, true, false, getEntity().getName(), "Mystical Energy"); + } + } + + @Override + public int getCooldown() + { + return 3; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + Player target = UtilMath.randomElement(getBoss().getPlayers(UtilPlayer.getInRadius(getLocation(), RANGE), RANGE)); + if (target != null) + { + _lastUsed = System.currentTimeMillis(); + shootBolt(target); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageBoneExplode.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageBoneExplode.java new file mode 100644 index 000000000..87440c682 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageBoneExplode.java @@ -0,0 +1,76 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.mage; + +import java.util.Map; + +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.Managers; +import mineplex.core.blood.Blood; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class MageBoneExplode extends BossPassive +{ + private long _lastUsed; + + public MageBoneExplode(UndeadMage creature) + { + super(creature); + _lastUsed = System.currentTimeMillis(); + } + + private void explode() + { + Map nearby = UtilPlayer.getInRadius(getLocation(), 4); + for (Player near : nearby.keySet()) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(near, getEntity(), null, DamageCause.CUSTOM, 3, true, true, false, getEntity().getName(), "Bone Explosion"); + } + Managers.get(Blood.class).Effects(null, getLocation().add(0, 0.5, 0), 48, 0.8, Sound.SKELETON_HURT, 2f, 1.2f, Material.BONE, (byte) 0, 40, false); + } + + @Override + public int getCooldown() + { + return 8; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + _lastUsed = System.currentTimeMillis(); + explode(); + } + } + + @EventHandler + public void Knockback(CustomDamageEvent event) + { + if (event.GetReason() == null || !event.GetReason().contains("Bone Explosion")) + { + return; + } + + if (event.GetDamagerEntity(false) == null || event.GetDamagerEntity(false).getEntityId() != getEntity().getEntityId()) + { + return; + } + + event.AddKnockback("Bone Explosion", 5); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageSummon.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageSummon.java new file mode 100644 index 000000000..3ee21f400 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/MageSummon.java @@ -0,0 +1,80 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.mage; + +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.entity.Skeleton; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; + +public class MageSummon extends BossPassive +{ + private final int MAX_KNIGHTS; + private static final int KNIGHTS_PER_USE = 6; + private long _lastUsed; + private List _spawnLocations; + + public MageSummon(UndeadMage creature, List spawnLocations) + { + super(creature); + + _lastUsed = System.currentTimeMillis(); + MAX_KNIGHTS = spawnLocations == null ? 10 : spawnLocations.size(); + _spawnLocations = spawnLocations; + } + + private void spawnKnight() + { + Location spawn = null; + if (_spawnLocations != null) + { + spawn = UtilMath.randomElement(_spawnLocations); + } + else + { + spawn = getLocation(); + } + getBoss().getEvent().registerCreature(new UndeadKnight(getBoss().getChallenge(), spawn)); + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, spawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, spawn, null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, getLocation(), null, 0, 2, ViewDist.MAX); + UtilParticle.PlayParticleToAll(ParticleType.SMOKE, getLocation(), null, 0, 2, ViewDist.MAX); + } + + @Override + public int getCooldown() + { + return 30; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + if (!UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + return; + } + long amount = ((WitherRaid)getBoss().getEvent()).getCreatures().stream().filter(UndeadKnight.class::isInstance).count(); + if (amount < MAX_KNIGHTS) + { + _lastUsed = System.currentTimeMillis(); + long spawnAmount = Math.min(MAX_KNIGHTS - amount, KNIGHTS_PER_USE); + for (int i = 0; i < spawnAmount; i++) + { + spawnKnight(); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/UndeadKnight.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/UndeadKnight.java new file mode 100644 index 000000000..093d3afa5 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/UndeadKnight.java @@ -0,0 +1,92 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.mage; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.RaidCreature; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class UndeadKnight extends RaidCreature +{ + private RaidChallenge _challenge; + private KnightPassive _passive; + + public UndeadKnight(RaidChallenge challenge, Location location) + { + super(challenge.getRaid(), location, "Undead Knight", true, 25, 100, true, Skeleton.class); + + _challenge = challenge; + spawnEntity(); + _passive = new KnightPassive(this); + } + + @Override + protected void spawnCustom() + { + getEntity().getEquipment().setItemInHand(new ItemStack(Material.STONE_SWORD)); + getEntity().getEquipment().setItemInHandDropChance(0f); + getEntity().getEquipment().setHelmet(new ItemBuilder(Material.CHAINMAIL_HELMET).setUnbreakable(true).build()); + getEntity().getEquipment().setHelmetDropChance(0f); + getEntity().addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 100000000, 0)); + } + + @Override + public void dieCustom() + { + endAbility(); + } + + private void endAbility() + { + HandlerList.unregisterAll(_passive); + _passive = null; + } + + @EventHandler + public void onTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_challenge.isComplete()) + { + remove(); + return; + } + + _passive.tick(); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void allyDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + if (damager != null && !(damager instanceof Player)) + { + event.SetCancelled("Allied Damage"); + } + } + } + + @Override + public void handleDeath(Location location) {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/UndeadMage.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/UndeadMage.java new file mode 100644 index 000000000..7a767fcdd --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/mage/UndeadMage.java @@ -0,0 +1,199 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.mage; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Skeleton; +import org.bukkit.entity.Skeleton.SkeletonType; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.RaidCreature; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class UndeadMage extends RaidCreature +{ + private RaidChallenge _challenge; + private List> _abilities; + private boolean _invuln; + + public UndeadMage(RaidChallenge challenge, Location location, boolean invulnerable, List spawnLocations, List blinkLocations) + { + super(challenge.getRaid(), location, "Undead Mage", true, 500, 1500, true, Skeleton.class); + + _challenge = challenge; + _invuln = invulnerable; + spawnEntity(); + _abilities = new ArrayList<>(); + _abilities.add(new MageSummon(this, spawnLocations)); + _abilities.add(new MageBlink(this, blinkLocations)); + _abilities.add(new MageBolt(this)); + _abilities.add(new MageBoneExplode(this)); + } + + @Override + protected void spawnCustom() + { + //UtilEnt.vegetate(getEntity()); + getEntity().setSkeletonType(SkeletonType.WITHER); + getEntity().getEquipment().setItemInHand(new ItemStack(Material.RECORD_6)); //Meridian Scepter + getEntity().getEquipment().setItemInHandDropChance(0f); + getEntity().getEquipment().setHelmet(new ItemBuilder(Material.GOLD_HELMET).setUnbreakable(true).build()); + getEntity().getEquipment().setChestplate(new ItemBuilder(Material.GOLD_CHESTPLATE).setUnbreakable(true).build()); + getEntity().getEquipment().setLeggings(new ItemBuilder(Material.GOLD_LEGGINGS).setUnbreakable(true).build()); + getEntity().getEquipment().setBoots(new ItemBuilder(Material.GOLD_BOOTS).setUnbreakable(true).build()); + getEntity().getEquipment().setHelmetDropChance(0f); + getEntity().getEquipment().setChestplateDropChance(0f); + getEntity().getEquipment().setLeggingsDropChance(0f); + getEntity().getEquipment().setBootsDropChance(0f); + } + + public RaidChallenge getChallenge() + { + return _challenge; + } + + @Override + public void dieCustom() + { + endAbility(); + } + + private void endAbility() + { + for (BossPassive ability : _abilities) + { + HandlerList.unregisterAll(ability); + } + _abilities.clear(); + } + + @EventHandler + public void onTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_challenge.isComplete()) + { + remove(); + return; + } + + _abilities.forEach(BossPassive::tick); + } + + protected List getPlayers(Map map, double maxDist) + { + return getPlayers(map, 0, maxDist); + } + + protected List getPlayers(final Map map, double minDist, double maxDist) + { + List list = new ArrayList<>(); + + for (Player p : map.keySet()) + { + if (!_challenge.getRaid().getPlayers().contains(p)) + { + continue; + } + if (map.get(p) >= minDist && map.get(p) <= maxDist) + { + list.add(p); + } + } + + Collections.sort(list, (o1, o2) -> + { + return Double.compare(map.get(o2), map.get(o1)); + }); + + return list; + } + + @EventHandler + public void onSkeletonDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + event.SetKnockback(false); + if (_invuln) + { + event.SetCancelled("Challenge Invulnerability"); + } + } + } + + @EventHandler + public void noFallDamage(CustomDamageEvent event) + { + if (getEntity() == null) + { + return; + } + + if (event.GetDamageeEntity().getEntityId() != getEntity().getEntityId()) + { + return; + } + + DamageCause cause = event.GetCause(); + + if (cause == DamageCause.FALL) + { + event.SetCancelled("Boss Invulnerability"); + } + } + + @EventHandler + public void buffDamage(CustomDamageEvent event) + { + if (event.GetDamagerEntity(false) == null) + { + return; + } + if (event.GetDamagerEntity(false).getEntityId() == getEntity().getEntityId() && event.GetCause() == DamageCause.ENTITY_ATTACK) + { + event.AddMod("Mage Attack", 7 - event.GetDamage()); + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void ally(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + if (damager != null && !(damager instanceof Player)) + { + event.SetCancelled("Allied Damage"); + } + } + } + + @Override + public void handleDeath(Location location) + { + location.getWorld().dropItem(location.clone().add(0, 1, 0), new ItemStack(Material.EMERALD, UtilMath.rRange(10, 20))); + location.getWorld().dropItem(location.clone().add(0, 1, 0), new ItemStack(UtilMath.randomElement(new Material[] {Material.GOLD_HELMET, Material.GOLD_CHESTPLATE, Material.GOLD_LEGGINGS, Material.GOLD_BOOTS}))); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/BlazeMinion.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/BlazeMinion.java new file mode 100644 index 000000000..0d8f9a19a --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/BlazeMinion.java @@ -0,0 +1,66 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.magma; + +import org.bukkit.Location; +import org.bukkit.entity.Blaze; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.RaidCreature; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class BlazeMinion extends RaidCreature +{ + private RaidChallenge _challenge; + + public BlazeMinion(RaidChallenge challenge, Location spawnLocation) + { + super(challenge.getRaid(), spawnLocation, "Blaze Minion", true, 20, 500, true, Blaze.class); + + _challenge = challenge; + spawnEntity(); + } + + @Override + protected void spawnCustom() {} + + @Override + public void dieCustom() {} + + @EventHandler + public void onTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_challenge.isComplete()) + { + remove(); + return; + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void allyDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + if (damager != null && !(damager instanceof Player)) + { + event.SetCancelled("Allied Damage"); + } + } + } + + @Override + public void handleDeath(Location location) {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/Cataclysm.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/Cataclysm.java new file mode 100644 index 000000000..1a46b6b33 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/Cataclysm.java @@ -0,0 +1,63 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.magma; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTextMiddle; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.six.ChallengeSix; + +public abstract class Cataclysm implements Listener +{ + protected ChallengeSix Challenge; + protected Magmus Magmus; + + public Cataclysm(ChallengeSix challenge, Magmus magmus) + { + Challenge = challenge; + Magmus = magmus; + + challenge.getRaid().getPlayers().forEach(player -> + { + UtilPlayer.message(player, F.main(challenge.getRaid().getName() + " Raid", getAnnouncement())); + UtilTextMiddle.display("", getAnnouncement(), player); + }); + onStart(); + UtilServer.RegisterEvents(this); + } + + protected abstract String getAnnouncement(); + + protected abstract void onStart(); + + protected abstract void onEnd(); + + protected abstract void tick(); + + protected void end() + { + onEnd(); + HandlerList.unregisterAll(this); + } + + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() == UpdateType.TICK) + { + if (Challenge.isComplete()) + { + end(); + } + else + { + tick(); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/HeatingUp.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/HeatingUp.java new file mode 100644 index 000000000..c421b4b82 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/HeatingUp.java @@ -0,0 +1,79 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.magma; + +import org.bukkit.DyeColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.UtilMath; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.six.ChallengeSix; + +public class HeatingUp extends Cataclysm +{ + private Location _center; + private int _ticks; + + public HeatingUp(ChallengeSix challenge, Magmus magmus) + { + super(challenge, magmus); + } + + @Override + protected String getAnnouncement() + { + return "The room is heating up! Quickly, head to a safe location!"; + } + + @SuppressWarnings("deprecation") + @Override + protected void onStart() + { + ((MagmusMeteor)Magmus.Abilities.get(2)).Disabled = true; + _center = Challenge.getRaid().getWorldData().getCustomLocs("C_SIX_C1S").get(0); + for (int x = -1; x <= 1; x++) + { + for (int z = -1; z <= 1; z++) + { + _center.getBlock().getRelative(x, -1, z).setTypeIdAndData(Material.STAINED_GLASS.getId(), DyeColor.GREEN.getWoolData(), true); + } + } + } + + @Override + protected void onEnd() + { + for (int x = -1; x <= 1; x++) + { + for (int z = -1; z <= 1; z++) + { + _center.getBlock().getRelative(x, -1, z).setType(Material.STONE); + } + } + if (Magmus.Abilities.size() > 1 && Magmus.Abilities.get(2) instanceof MagmusMeteor) + { + ((MagmusMeteor)Magmus.Abilities.get(2)).Disabled = false; + } + } + + @Override + protected void tick() + { + _ticks++; + if (_ticks > (20 * 10)) + { + for (Player player : Challenge.getRaid().getPlayers()) + { + if (UtilMath.offset(player.getLocation(), _center) > 1) + { + player.setFireTicks(1); + Challenge.getRaid().getDamageManager().NewDamageEvent(player, Magmus.getEntity(), null, DamageCause.FIRE, 1, false, true, true, Magmus.getEntity().getName(), "Heat Room"); + } + } + } + if (_ticks > (20 * 30)) + { + end(); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/InfernalMinions.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/InfernalMinions.java new file mode 100644 index 000000000..4255bc09f --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/InfernalMinions.java @@ -0,0 +1,45 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.magma; + +import org.bukkit.Location; + +import mineplex.core.common.util.UtilMath; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.six.ChallengeSix; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.mage.UndeadKnight; + +public class InfernalMinions extends Cataclysm +{ + public InfernalMinions(ChallengeSix challenge, Magmus magmus) + { + super(challenge, magmus); + } + + @Override + protected String getAnnouncement() + { + return "Infernal minions have flocked to Magmus' aid!"; + } + + @Override + protected void onStart() + { + for (int i = 0; i < 20; i++) + { + Location loc = UtilMath.randomElement(Magmus.getChallenge().getRaid().getPlayers()).getLocation(); + if (UtilMath.r(2) == 1) + { + Challenge.getRaid().registerCreature(new UndeadKnight(Challenge, loc)); + } + else + { + Challenge.getRaid().registerCreature(new BlazeMinion(Challenge, loc)); + } + } + end(); + } + + @Override + protected void onEnd() {} + + @Override + protected void tick() {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/Magmus.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/Magmus.java new file mode 100644 index 000000000..490adbfb0 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/Magmus.java @@ -0,0 +1,119 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.magma; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.MagmaCube; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.UtilEnt; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.raid.RaidCreature; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.six.ChallengeSix; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class Magmus extends RaidCreature +{ + private ChallengeSix _challenge; + protected List> Abilities = new ArrayList<>(); + + protected boolean TeleportBackASAP = true; + + public Magmus(ChallengeSix challenge, Location location) + { + super(challenge.getRaid(), location, "Gatekeeper Magmus", true, 2000, 500, true, MagmaCube.class); + + _challenge = challenge; + spawnEntity(); + Abilities.add(new MagmusCataclysm(this)); + Abilities.add(new MagmusSmash(this)); + Abilities.add(new MagmusMeteor(this)); + Abilities.add(new MagmusEat(this)); + } + + protected ChallengeSix getChallenge() + { + return _challenge; + } + + @Override + protected void spawnCustom() + { + UtilEnt.vegetate(getEntity()); + getEntity().setSize(17); + } + + @Override + public void dieCustom() + { + endAbility(); + } + + private void endAbility() + { + Abilities.forEach(ability -> + { + HandlerList.unregisterAll(ability); + }); + Abilities.clear(); + } + + @EventHandler + public void onTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_challenge.isComplete()) + { + remove(); + return; + } + + if (TeleportBackASAP) + { + getEntity().teleport(getSpawnLocation()); + } + + Abilities.forEach(BossPassive::tick); + } + + @EventHandler + public void onMagmusDamage(CustomDamageEvent event) + { + if (event.GetDamagerEntity(false) == null) + { + return; + } + if (event.GetDamagerEntity(false).getEntityId() == getEntity().getEntityId() && (event.GetCause() != DamageCause.FIRE && event.GetCause() != DamageCause.CUSTOM && event.GetCause() != DamageCause.PROJECTILE)) + { + event.SetCancelled("Wrong Attack Type Magmus"); + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void allyDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + if (damager != null && !(damager instanceof Player)) + { + event.SetCancelled("Allied Damage"); + } + } + } + + @Override + public void handleDeath(Location location) {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusCataclysm.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusCataclysm.java new file mode 100644 index 000000000..1bec42e4c --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusCataclysm.java @@ -0,0 +1,59 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.magma; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.entity.MagmaCube; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.six.ChallengeSix; + +public class MagmusCataclysm extends BossPassive +{ + private long _lastUse; + private List> _cataclysms = new ArrayList<>(); + + public MagmusCataclysm(Magmus creature) + { + super(creature); + _lastUse = System.currentTimeMillis() - (getCooldown() * 1000); + _cataclysms.add(HeatingUp.class); + _cataclysms.add(InfernalMinions.class); + _cataclysms.add(UndeadAlly.class); + } + + @Override + public int getCooldown() + { + return 23; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + if (UtilTime.elapsed(_lastUse, getCooldown() * 1000)) + { + _lastUse = System.currentTimeMillis(); + if (!_cataclysms.isEmpty()) + { + try + { + UtilMath.randomElement(_cataclysms).getConstructor(ChallengeSix.class, Magmus.class).newInstance(getBoss().getChallenge(), getBoss()); + } + catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) + { + e.printStackTrace(); + } + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusEat.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusEat.java new file mode 100644 index 000000000..f174ced35 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusEat.java @@ -0,0 +1,90 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.magma; + +import org.bukkit.entity.MagmaCube; +import org.bukkit.entity.Player; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; + +public class MagmusEat extends BossPassive +{ + private long _lastUse; + private Player _eating; + private int _ticks; + + public MagmusEat(Magmus creature) + { + super(creature); + _lastUse = System.currentTimeMillis(); + } + + private void spit() + { + double offset = UtilMath.offset(_eating, getEntity()); + //Velocity + UtilAction.velocity(_eating, + UtilAlg.getTrajectory2d(getLocation().toVector(), _eating.getLocation().toVector()), + 2 + 2 * offset, true, 0, 1.2 + 1.0 * offset, 3, true); + + getBoss().getEvent().getCondition().Factory().Falling("Spit Out", _eating, getEntity(), 10, false, true); + + _lastUse = System.currentTimeMillis(); + _eating = null; + _ticks = -1; + } + + private void eat() + { + if (_ticks < 20 * 10) + { + _eating.setFireTicks(40); + _eating.teleport(getEntity()); + } + else + { + spit(); + } + _ticks++; + } + + private void initialEat(Player target) + { + _eating = target; + _ticks = 0; + getBoss().getEvent().getCondition().Factory().Silence("Eat", _eating, getEntity(), 10, true, true); + } + + @Override + public int getCooldown() + { + return 15; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + if (_eating != null) + { + eat(); + return; + } + if (UtilTime.elapsed(_lastUse, getCooldown() * 1000)) + { + Player target = UtilPlayer.getClosest(getLocation(), 7); + if (target != null) + { + initialEat(target); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusMeteor.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusMeteor.java new file mode 100644 index 000000000..c0da5fa5b --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusMeteor.java @@ -0,0 +1,123 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.magma; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Sound; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftLargeFireball; +import org.bukkit.entity.LargeFireball; +import org.bukkit.entity.MagmaCube; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.ProjectileHitEvent; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import net.minecraft.server.v1_8_R3.EntityLargeFireball; + +public class MagmusMeteor extends BossPassive +{ + private long _lastUse; + private List _shot = new ArrayList<>(); + + protected boolean Disabled = false; + + public MagmusMeteor(Magmus creature) + { + super(creature); + _lastUse = System.currentTimeMillis(); + } + + private void newBall() + { + if (Disabled) + { + return; + } + Player target = UtilMath.randomElement(getBoss().getChallenge().getRaid().getPlayers()); + LargeFireball ball = target.getWorld().spawn(target.getLocation().add(2 * Math.random(), 10 + Math.random() * 16, 2 * Math.random()), LargeFireball.class); + + EntityLargeFireball eFireball = ((CraftLargeFireball) ball).getHandle(); + eFireball.dirX = (Math.random()-0.5)*0.02; + eFireball.dirY = -0.2 - 0.05 * Math.random(); + eFireball.dirZ = (Math.random()-0.5)*0.02; + + ball.setShooter(getEntity()); + ball.setYield(0f); + ball.setBounce(false); + ball.setIsIncendiary(false); + _shot.add(ball); + } + + @Override + public int getCooldown() + { + return 30; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + if (Disabled) + { + return; + } + if (UtilTime.elapsed(_lastUse, getCooldown() * 1000)) + { + _lastUse = System.currentTimeMillis(); + for (int i = 0; i < 20; i++) + { + newBall(); + } + } + } + + @EventHandler + public void onExplode(EntityExplodeEvent event) + { + if (event.getEntity() instanceof LargeFireball) + { + LargeFireball ball = (LargeFireball) event.getEntity(); + if (ball.getShooter() instanceof MagmaCube && ((MagmaCube)ball.getShooter()).getEntityId() == getEntity().getEntityId()) + { + event.blockList().clear(); + return; + } + } + } + + @EventHandler + public void onBallHit(ProjectileHitEvent event) + { + if (event.getEntity() instanceof LargeFireball) + { + LargeFireball ball = (LargeFireball) event.getEntity(); + if (_shot.contains(ball)) + { + _shot.remove(ball); + UtilParticle.PlayParticle(ParticleType.EXPLODE, ball.getLocation(), null, 0, 2, ViewDist.MAX, UtilServer.getPlayers()); + ball.getWorld().playSound(ball.getLocation(), Sound.EXPLODE, 10, 0); + Player hit = UtilPlayer.getClosest(ball.getLocation(), 3); + if (hit != null) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(hit, getEntity(), ball, DamageCause.PROJECTILE, 4, true, true, false, getEntity().getName(), "Meteor Shower"); + } + ball.remove(); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusSmash.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusSmash.java new file mode 100644 index 000000000..50eab5b2b --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/MagmusSmash.java @@ -0,0 +1,71 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.magma; + +import java.util.Map; + +import org.bukkit.entity.MagmaCube; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; + +public class MagmusSmash extends BossPassive +{ + private long _lastUse; + + public MagmusSmash(Magmus creature) + { + super(creature); + _lastUse = System.currentTimeMillis(); + } + + private void slam() + { + //Action + Map targets = UtilPlayer.getInRadius(getLocation(), 5.5d + 0.5 * 5); + getBoss().TeleportBackASAP = false; + getEntity().setVelocity(new Vector(0, 5, 0)); + UtilServer.runSyncLater(() -> getBoss().TeleportBackASAP = true, 3 * 20); + for (Player player : targets.keySet()) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getEntity(), null, + DamageCause.CUSTOM, 6 * targets.get(player) + 0.5, false, true, false, + getEntity().getName(), "Smash"); + + //Velocity + UtilAction.velocity(player, + UtilAlg.getTrajectory2d(getLocation().toVector(), player.getLocation().toVector()), + 2 + 2 * targets.get(player), true, 0, 1.2 + 1.0 * targets.get(player), 3, true); + + //Condition + getBoss().getEvent().getCondition().Factory().Falling("Smash", player, getEntity(), 10, false, true); + } + } + + @Override + public int getCooldown() + { + return 10; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + if (UtilTime.elapsed(_lastUse, getCooldown() * 1000)) + { + _lastUse = System.currentTimeMillis(); + slam(); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/UndeadAlly.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/UndeadAlly.java new file mode 100644 index 000000000..06730bf2b --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/magma/UndeadAlly.java @@ -0,0 +1,31 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.magma; + +import mineplex.game.clans.clans.worldevent.raid.wither.challenge.six.ChallengeSix; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.mage.UndeadMage; + +public class UndeadAlly extends Cataclysm +{ + public UndeadAlly(ChallengeSix challenge, Magmus magmus) + { + super(challenge, magmus); + } + + @Override + protected String getAnnouncement() + { + return "Magmus has summoned an undead ally!"; + } + + @Override + protected void onStart() + { + Challenge.getRaid().registerCreature(new UndeadMage(Challenge, Challenge.getRaid().getWorldData().getCustomLocs("C_SIX_C3S").get(0), false, null, null)); + end(); + } + + @Override + protected void onEnd() {} + + @Override + protected void tick() {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/BlackHole.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/BlackHole.java new file mode 100644 index 000000000..2465a56ab --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/BlackHole.java @@ -0,0 +1,129 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.entity.Wither; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilAction; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; + +public class BlackHole extends BossPassive +{ + private static final double RANGE = 15; + private long _lastUsed; + private int _chargeTicks; + + public BlackHole(CharlesWitherton creature) + { + super(creature); + _lastUsed = -1; + _chargeTicks = -1; + } + + private void pull() + { + for (Player entity : UtilPlayer.getInRadius(getLocation(), RANGE).keySet()) + { + UtilAction.velocity(entity, UtilAlg.getTrajectory(entity, getEntity()), 0.3, false, 0, 0, 1, true); + } + for (int i = 0; i < 6; i++) + { + Vector random = new Vector(Math.random() * 4 - 2, Math.random() * 4 - 2, Math.random() * 4 - 2); + + Location origin = getLocation().add(0, 1.3, 0); + origin.add(getLocation().getDirection().multiply(10)); + origin.add(random); + + Vector vel = UtilAlg.getTrajectory(origin, getLocation().add(0, 1.3, 0)); + vel.multiply(7); + + UtilParticle.PlayParticle(ParticleType.MAGIC_CRIT, + origin, + (float)vel.getX(), + (float)vel.getY(), + (float)vel.getZ(), + 1, 0, ViewDist.LONG, UtilServer.getPlayers()); + } + } + + private void throwUp() + { + Map near = UtilPlayer.getInRadius(getLocation(), RANGE); + for (Entry thr : near.entrySet()) + { + Vector vel = new Vector(0, Math.min(7.5, Math.max(5 / thr.getValue(), 4)), 0); + thr.getKey().setVelocity(vel); + } + } + + @Override + public int getCooldown() + { + return 60; + } + + @Override + public boolean isProgressing() + { + return _chargeTicks != -1; + } + + @Override + public void tick() + { + if (_chargeTicks != -1) + { + _chargeTicks++; + if (_chargeTicks >= (20 * 5)) + { + _lastUsed = System.currentTimeMillis(); + _chargeTicks = -1; + throwUp(); + } + else + { + pull(); + } + return; + } + if (getBoss().getHealthPercent() <= 0.25) + { + if (_lastUsed == -1) + { + _lastUsed = System.currentTimeMillis(); + } + else + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + _chargeTicks = 0; + ((WitherRaid)getBoss().getEvent()).getPlayers().forEach(player -> UtilPlayer.message(player, F.main(getBoss().getEvent().getName() + " Raid", "He's charging up Decay! Run away!"))); + } + } + } + } + + @EventHandler + public void onKick(PlayerKickEvent event) + { + if (_chargeTicks != -1 && getBoss().getChallenge().getRaid().getPlayers().contains(event.getPlayer())) + { + event.setCancelled(true); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/CharlesSkulls.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/CharlesSkulls.java new file mode 100644 index 000000000..88e88a8cd --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/CharlesSkulls.java @@ -0,0 +1,191 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import org.bukkit.Sound; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Wither; +import org.bukkit.entity.WitherSkull; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.ProjectileHitEvent; +import org.bukkit.util.Vector; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossAbility; + +public class CharlesSkulls extends BossAbility +{ + private long _lastUnguided; + private long _lastGuided; + private long _lastBombard; + private Map _guidedSkulls; + + public CharlesSkulls(CharlesWitherton creature) + { + super(creature); + + _guidedSkulls = new HashMap<>(); + _lastUnguided = System.currentTimeMillis(); + _lastGuided = System.currentTimeMillis(); + _lastBombard = -1; + } + + @Override + public void tick() + { + if (getBoss().getHealthPercent() <= 0.75) + { + if (_lastBombard == -1) + { + _lastBombard = System.currentTimeMillis(); + } + else + { + if (UtilTime.elapsed(_lastBombard, 25000)) + { + Player target = UtilPlayer.getClosest(getLocation()); + if (target != null) + { + _lastBombard = System.currentTimeMillis(); + UtilEnt.LookAt(getEntity(), target.getEyeLocation()); + for (int i = 0; i < 15; i++) + { + UtilEnt.addFlag(getEntity().launchProjectile(WitherSkull.class), "BOMBARD"); + } + return; + } + } + } + } + if (UtilTime.elapsed(_lastUnguided, 10000)) + { + Player target = UtilPlayer.getClosest(getLocation()); + if (target != null) + { + _lastUnguided = System.currentTimeMillis(); + UtilEnt.LookAt(getEntity(), target.getEyeLocation()); + getEntity().launchProjectile(WitherSkull.class); + return; + } + } + if (UtilTime.elapsed(_lastGuided, 5000)) + { + Player target = UtilPlayer.getClosest(getLocation()); + if (target != null) + { + _lastGuided = System.currentTimeMillis(); + UtilEnt.LookAt(getEntity(), target.getEyeLocation()); + WitherSkull skull = getEntity().launchProjectile(WitherSkull.class); + UtilEnt.addFlag(skull, "GUIDED"); + _guidedSkulls.put(skull, target); + } + } + + Iterator> iterator = _guidedSkulls.entrySet().iterator(); + while (iterator.hasNext()) + { + Entry entry = iterator.next(); + if (!entry.getKey().isValid() || entry.getKey().isDead()) + { + iterator.remove(); + continue; + } + Vector velocity = UtilAlg.getTrajectory(entry.getKey(), entry.getValue()); + entry.getKey().setDirection(velocity); + entry.getKey().setVelocity(velocity.multiply(0.6)); + } + } + + @EventHandler + public void onExplode(EntityExplodeEvent event) + { + if (event.getEntity().getEntityId() == getEntity().getEntityId()) + { + event.blockList().clear(); + return; + } + if (event.getEntity() instanceof WitherSkull) + { + WitherSkull skull = (WitherSkull) event.getEntity(); + if (skull.getShooter() instanceof Wither && ((Wither)skull.getShooter()).getEntityId() == getEntity().getEntityId()) + { + event.blockList().clear(); + return; + } + } + } + + @EventHandler + public void onSkullHit(ProjectileHitEvent event) + { + if (event.getEntity() instanceof WitherSkull) + { + WitherSkull skull = (WitherSkull) event.getEntity(); + if (skull.getShooter() instanceof Wither && ((Wither)skull.getShooter()).getEntityId() == getEntity().getEntityId()) + { + UtilParticle.PlayParticle(ParticleType.EXPLODE, skull.getLocation(), null, 0, 2, ViewDist.MAX, UtilServer.getPlayers()); + skull.getWorld().playSound(skull.getLocation(), Sound.EXPLODE, 10, 0); + if (UtilEnt.hasFlag(skull, "GUIDED")) + { + Player hit = UtilPlayer.getClosest(skull.getLocation(), 0.5); + if (hit != null) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(hit, getEntity(), skull, DamageCause.PROJECTILE, 2, true, true, false, getEntity().getName(), "Guided Skull"); + } + } + else if (UtilEnt.hasFlag(skull, "BOMBARD")) + { + Player hit = UtilPlayer.getClosest(skull.getLocation(), 0.5); + if (hit != null) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(hit, getEntity(), skull, DamageCause.PROJECTILE, 2, true, true, false, getEntity().getName(), "Bombardment"); + } + } + else + { + Player hit = UtilPlayer.getClosest(skull.getLocation(), 0.5); + if (hit != null) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(hit, getEntity(), skull, DamageCause.PROJECTILE, 4, true, true, false, getEntity().getName(), "Wither Skull"); + getBoss().getEvent().getCondition().Factory().Wither("Wither Skull", hit, getEntity(), 3, 0, false, true, false); + } + } + skull.remove(); + } + } + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public boolean inProgress() + { + return false; + } + + @Override + public boolean hasFinished() + { + return false; + } + + @Override + public void setFinished() {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/CharlesWitherton.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/CharlesWitherton.java new file mode 100644 index 000000000..1043b4187 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/CharlesWitherton.java @@ -0,0 +1,185 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftWither; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Wither; +import org.bukkit.entity.WitherSkull; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.ProjectileLaunchEvent; + +import com.google.common.base.Predicate; + +import mineplex.core.common.util.UtilEnt; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.RaidCreature; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.wither.ai.PathfinderGoalCustomFloat; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import net.minecraft.server.v1_8_R3.Entity; +import net.minecraft.server.v1_8_R3.EntityHuman; +import net.minecraft.server.v1_8_R3.EntityInsentient; +import net.minecraft.server.v1_8_R3.EntityWither; +import net.minecraft.server.v1_8_R3.PathfinderGoalHurtByTarget; +import net.minecraft.server.v1_8_R3.PathfinderGoalLookAtPlayer; +import net.minecraft.server.v1_8_R3.PathfinderGoalNearestAttackableTarget; +import net.minecraft.server.v1_8_R3.PathfinderGoalRandomLookaround; +import net.minecraft.server.v1_8_R3.PathfinderGoalRandomStroll; + +public class CharlesWitherton extends RaidCreature +{ + private RaidChallenge _challenge; + private CharlesSkulls _passive; + private List> _abilities = new ArrayList<>(); + + public boolean Flying = false; + + public CharlesWitherton(RaidChallenge challenge, Location location) + { + super(challenge.getRaid(), location, "Charles Witherton", true, 5000, 15000, true, Wither.class); + + _challenge = challenge; + spawnEntity(); + _passive = new CharlesSkulls(this); + _abilities.add(new LifeSap(this)); + _abilities.add(new Flight(this)); + _abilities.add(new Decay(this)); + _abilities.add(new WitherWave(this)); + _abilities.add(new SummonUndead(this)); + _abilities.add(new SummonCorpse(this)); + _abilities.add(new BlackHole(this)); + _abilities.add(new SummonMinions(this)); + } + + protected RaidChallenge getChallenge() + { + return _challenge; + } + + protected List getCustomLocs(String id) + { + return _challenge.getRaid().getWorldData().getCustomLocs(id); + } + + @Override + protected void spawnCustom() + { + UtilEnt.vegetate(getEntity()); + CraftWither cw = (CraftWither)getEntity(); + EntityWither wither = cw.getHandle(); + wither.setVegetated(false); + wither.goalSelector.a(0, new PathfinderGoalCustomFloat(this, wither)); + wither.goalSelector.a(5, new PathfinderGoalRandomStroll(wither, 1.0D)); + wither.goalSelector.a(6, new PathfinderGoalLookAtPlayer(wither, EntityHuman.class, 8.0F)); + wither.goalSelector.a(7, new PathfinderGoalRandomLookaround(wither)); + wither.targetSelector.a(1, new PathfinderGoalHurtByTarget(wither, false, new Class[0])); + wither.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(wither, EntityInsentient.class, 0, false, false, new Predicate() + { + public boolean a(Entity entity) + { + return entity instanceof EntityHuman; + } + + public boolean apply(Entity entity) + { + return this.a(entity); + } + })); + } + + @Override + public void dieCustom() + { + endAbility(); + } + + private void endAbility() + { + for (BossPassive ability : _abilities) + { + HandlerList.unregisterAll(ability); + } + _abilities.clear(); + _passive.setFinished(); + HandlerList.unregisterAll(_passive); + _passive = null; + } + + @EventHandler + public void onTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_challenge.isComplete()) + { + remove(); + return; + } + + _passive.tick(); + _abilities.forEach(BossPassive::tick); + + if (Flying) + { + getEntity().setHealth(500); + } + else + { + getEntity().setHealth(100); + } + } + + @EventHandler + public void handleBlockChange(EntityChangeBlockEvent event) + { + if (event.getEntity().getEntityId() == getEntity().getEntityId()) + { + event.setCancelled(true); + } + } + + @EventHandler + public void onLaunch(ProjectileLaunchEvent event) + { + if (event.getEntity() instanceof WitherSkull && event.getEntity().getShooter() instanceof Wither) + { + if (((Wither)event.getEntity().getShooter()).getEntityId() == getEntity().getEntityId()) + { + if (((WitherSkull)event.getEntity()).isCharged()) + { + event.setCancelled(true); + } + } + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void allyDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + if (damager != null && !(damager instanceof Player)) + { + event.SetCancelled("Allied Damage"); + } + } + } + + @Override + public void handleDeath(Location location) {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/Decay.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/Decay.java new file mode 100644 index 000000000..b7271831b --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/Decay.java @@ -0,0 +1,79 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.entity.Wither; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilShapes; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; + +public class Decay extends BossPassive +{ + private static final double RANGE = 28; + private long _lastUsed; + private int _chargeTicks; + + public Decay(CharlesWitherton creature) + { + super(creature); + _lastUsed = -1; + _chargeTicks = -1; + } + + @Override + public int getCooldown() + { + return 300; + } + + @Override + public boolean isProgressing() + { + return _chargeTicks != -1; + } + + @Override + public void tick() + { + if (_chargeTicks != -1) + { + _chargeTicks++; + if (_chargeTicks >= (20 * 5)) + { + _lastUsed = System.currentTimeMillis(); + _chargeTicks = -1; + for (Player player : UtilPlayer.getInRadius(getLocation(), RANGE).keySet()) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(player, getEntity(), null, DamageCause.WITHER, 1000, false, true, true, getEntity().getName(), "Decay"); + } + } + else + { + getEntity().teleport(getBoss().getCustomLocs("C_SEVEN_RWC").get(0)); + for (Location loc : UtilShapes.getSphereBlocks(getEntity().getEyeLocation(), 2, 2, true)) + { + UtilParticle.playColoredParticleToAll(Color.RED, ParticleType.RED_DUST, loc, 2, ViewDist.MAX); + UtilParticle.playColoredParticleToAll(Color.BLACK, ParticleType.RED_DUST, loc, 2, ViewDist.MAX); + } + } + return; + } + if (getBoss().getHealthPercent() <= 0.5) + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + _chargeTicks = 0; + ((WitherRaid)getBoss().getEvent()).getPlayers().forEach(player -> UtilPlayer.message(player, F.main(getBoss().getEvent().getName() + " Raid", "He's charging up Decay! Run away!"))); + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/Flight.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/Flight.java new file mode 100644 index 000000000..bb1cafc24 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/Flight.java @@ -0,0 +1,62 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import org.bukkit.entity.Wither; + +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; + +public class Flight extends BossPassive +{ + private long _lastUsed; + private int _flyingTicks; + + public Flight(CharlesWitherton creature) + { + super(creature); + _lastUsed = -1; + _flyingTicks = -1; + } + + @Override + public int getCooldown() + { + return 200; + } + + @Override + public boolean isProgressing() + { + return _flyingTicks != -1; + } + + @Override + public void tick() + { + if (_flyingTicks != -1) + { + _flyingTicks++; + if (_flyingTicks >= (20 * 20)) + { + _lastUsed = System.currentTimeMillis(); + _flyingTicks = -1; + getBoss().Flying = false; + } + return; + } + if (getBoss().getHealthPercent() <= 0.75) + { + if (_lastUsed == -1) + { + _lastUsed = System.currentTimeMillis(); + } + else + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + getBoss().Flying = true; + _flyingTicks = 0; + } + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/LifeSap.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/LifeSap.java new file mode 100644 index 000000000..5afeb2e8d --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/LifeSap.java @@ -0,0 +1,116 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.entity.Wither; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; + +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilShapes; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; + +public class LifeSap extends BossPassive +{ + private static final double RANGE = 20; + private long _lastUsed; + private int _chargeTicks; + + public LifeSap(CharlesWitherton creature) + { + super(creature); + _lastUsed = -1; + _chargeTicks = -1; + } + + private void shootBeam(Player target) + { + double curRange = 0; + boolean canHit = true; + + while (curRange <= RANGE) + { + Location newTarget = getEntity().getEyeLocation().add(UtilAlg.getTrajectory(getEntity(), target).multiply(curRange)); + + if (!UtilBlock.airFoliage(newTarget.getBlock())) + { + canHit = false; + break; + } + if (UtilMath.offset(newTarget, target.getLocation()) <= 0.9) + { + break; + } + + curRange += 0.2; + + UtilParticle.playColoredParticleToAll(Color.RED, ParticleType.RED_DUST, newTarget, 5, ViewDist.MAX); + } + + if (canHit) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(target, getEntity(), null, DamageCause.CUSTOM, 2.5, true, true, false, getEntity().getName(), "Mystical Energy"); + getBoss().setHealth(getBoss().getHealth() + 200); + } + } + + @Override + public int getCooldown() + { + return 60; + } + + @Override + public boolean isProgressing() + { + return _chargeTicks != -1; + } + + @Override + public void tick() + { + if (_chargeTicks != -1) + { + _chargeTicks++; + if (_chargeTicks >= (20 * 4)) + { + _lastUsed = System.currentTimeMillis(); + _chargeTicks = -1; + Player target = UtilPlayer.getClosest(getLocation(), RANGE); + if (target != null) + { + shootBeam(target); + } + } + else + { + for (Location loc : UtilShapes.getCircle(getEntity().getEyeLocation(), true, 1.5)) + { + UtilParticle.playColoredParticleToAll(Color.RED, ParticleType.RED_DUST, loc, 2, ViewDist.MAX); + } + } + return; + } + if (getBoss().getHealthPercent() <= 0.75) + { + if (_lastUsed == -1) + { + _lastUsed = System.currentTimeMillis(); + } + else + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + _chargeTicks = 0; + } + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/MiniCharles.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/MiniCharles.java new file mode 100644 index 000000000..1a3a911e0 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/MiniCharles.java @@ -0,0 +1,164 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftWither; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Wither; +import org.bukkit.entity.WitherSkull; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.ProjectileLaunchEvent; + +import com.google.common.base.Predicate; + +import mineplex.core.common.util.UtilEnt; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.worldevent.raid.RaidChallenge; +import mineplex.game.clans.clans.worldevent.raid.RaidCreature; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.wither.ai.PathfinderGoalCustomFloat; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import net.minecraft.server.v1_8_R3.Entity; +import net.minecraft.server.v1_8_R3.EntityHuman; +import net.minecraft.server.v1_8_R3.EntityInsentient; +import net.minecraft.server.v1_8_R3.EntityWither; +import net.minecraft.server.v1_8_R3.PathfinderGoalHurtByTarget; +import net.minecraft.server.v1_8_R3.PathfinderGoalLookAtPlayer; +import net.minecraft.server.v1_8_R3.PathfinderGoalNearestAttackableTarget; +import net.minecraft.server.v1_8_R3.PathfinderGoalRandomLookaround; +import net.minecraft.server.v1_8_R3.PathfinderGoalRandomStroll; + +public class MiniCharles extends RaidCreature +{ + private CharlesWitherton _charles; + private RaidChallenge _challenge; + private MiniCharlesSkulls _passive; + private int _liveTicks; + + protected boolean Flying = false; + + public MiniCharles(CharlesWitherton charles, Location location) + { + super(charles.getChallenge().getRaid(), location, "Charles' Minion", true, 50, 15000, true, Wither.class); + + _charles = charles; + _challenge = charles.getChallenge(); + spawnEntity(); + _passive = new MiniCharlesSkulls(this); + } + + @Override + protected void spawnCustom() + { + UtilEnt.vegetate(getEntity()); + EntityWither wither = ((CraftWither)getEntity()).getHandle(); + wither.setVegetated(false); + wither.goalSelector.a(0, new PathfinderGoalCustomFloat(_charles, wither)); + wither.goalSelector.a(5, new PathfinderGoalRandomStroll(wither, 1.0D)); + wither.goalSelector.a(6, new PathfinderGoalLookAtPlayer(wither, EntityHuman.class, 8.0F)); + wither.goalSelector.a(7, new PathfinderGoalRandomLookaround(wither)); + wither.targetSelector.a(1, new PathfinderGoalHurtByTarget(wither, false, new Class[0])); + wither.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(wither, EntityInsentient.class, 0, false, false, new Predicate() + { + public boolean a(Entity entity) + { + return entity instanceof EntityHuman; + } + + public boolean apply(Entity entity) + { + return this.a(entity); + } + })); + } + + @Override + public void dieCustom() + { + endAbility(); + } + + private void endAbility() + { + _passive.setFinished(); + HandlerList.unregisterAll(_passive); + _passive = null; + } + + @EventHandler + public void onTick(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + if (_challenge.isComplete()) + { + remove(); + return; + } + + _passive.tick(); + + _liveTicks++; + if (_liveTicks > (20 * 15)) + { + remove(); + } + + if (Flying) + { + getEntity().setHealth(500); + } + else + { + getEntity().setHealth(100); + } + } + + @EventHandler + public void handleBlockChange(EntityChangeBlockEvent event) + { + if (event.getEntity().getEntityId() == getEntity().getEntityId()) + { + event.setCancelled(true); + } + } + + @EventHandler + public void onLaunch(ProjectileLaunchEvent event) + { + if (event.getEntity() instanceof WitherSkull && event.getEntity().getShooter() instanceof Wither) + { + if (((Wither)event.getEntity().getShooter()).getEntityId() == getEntity().getEntityId()) + { + if (((WitherSkull)event.getEntity()).isCharged()) + { + event.setCancelled(true); + } + } + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void allyDamage(CustomDamageEvent event) + { + if (event.GetDamageeEntity().getEntityId() == getEntity().getEntityId()) + { + LivingEntity damager = event.GetDamagerEntity(event.GetCause() == DamageCause.PROJECTILE); + if (damager != null && !(damager instanceof Player)) + { + event.SetCancelled("Allied Damage"); + } + } + } + + @Override + public void handleDeath(Location location) {} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/MiniCharlesSkulls.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/MiniCharlesSkulls.java new file mode 100644 index 000000000..135decf8a --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/MiniCharlesSkulls.java @@ -0,0 +1,117 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.entity.Wither; +import org.bukkit.entity.WitherSkull; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.ProjectileHitEvent; + +import mineplex.core.common.util.UtilEnt; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossAbility; + +public class MiniCharlesSkulls extends BossAbility +{ + private long _lastUnguided; + private List _shot = new ArrayList<>(); + + public MiniCharlesSkulls(MiniCharles creature) + { + super(creature); + + _lastUnguided = System.currentTimeMillis(); + } + + @Override + public void tick() + { + if (UtilTime.elapsed(_lastUnguided, 10000)) + { + Player target = UtilPlayer.getClosest(getLocation()); + if (target != null) + { + _lastUnguided = System.currentTimeMillis(); + UtilEnt.LookAt(getEntity(), target.getEyeLocation()); + _shot.add(getEntity().launchProjectile(WitherSkull.class)); + return; + } + } + } + + @EventHandler + public void onExplode(EntityExplodeEvent event) + { + if (event.getEntity().getEntityId() == getEntity().getEntityId()) + { + event.blockList().clear(); + return; + } + if (event.getEntity() instanceof WitherSkull) + { + WitherSkull skull = (WitherSkull) event.getEntity(); + if (skull.getShooter() instanceof Wither && ((Wither)skull.getShooter()).getEntityId() == getEntity().getEntityId()) + { + event.blockList().clear(); + return; + } + } + } + + @EventHandler + public void onSkullHit(ProjectileHitEvent event) + { + if (event.getEntity() instanceof WitherSkull) + { + WitherSkull skull = (WitherSkull) event.getEntity(); + if (skull.getShooter() instanceof Wither && ((Wither)skull.getShooter()).getEntityId() == getEntity().getEntityId()) + { + _shot.remove(skull); + UtilParticle.PlayParticle(ParticleType.EXPLODE, skull.getLocation(), null, 0, 2, ViewDist.MAX, UtilServer.getPlayers()); + skull.getWorld().playSound(skull.getLocation(), Sound.EXPLODE, 10, 0); + Player hit = UtilPlayer.getClosest(skull.getLocation(), 0.5); + if (hit != null) + { + getBoss().getEvent().getDamageManager().NewDamageEvent(hit, getEntity(), skull, DamageCause.PROJECTILE, 4, true, true, false, getEntity().getName(), "Wither Skull"); + getBoss().getEvent().getCondition().Factory().Wither("Wither Skull", hit, getEntity(), 3, 0, false, true, false); + } + skull.remove(); + } + } + } + + @Override + public boolean canMove() + { + return true; + } + + @Override + public boolean inProgress() + { + return false; + } + + @Override + public boolean hasFinished() + { + return false; + } + + @Override + public void setFinished() + { + _shot.forEach(WitherSkull::remove); + _shot.clear(); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/SummonCorpse.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/SummonCorpse.java new file mode 100644 index 000000000..492b8b714 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/SummonCorpse.java @@ -0,0 +1,53 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import org.bukkit.entity.Wither; + +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.corpse.ReanimatedCorpse; + +public class SummonCorpse extends BossPassive +{ + private long _lastUsed; + + public SummonCorpse(CharlesWitherton creature) + { + super(creature); + _lastUsed = -1; + } + + @Override + public int getCooldown() + { + return 30; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + if (getBoss().getHealthPercent() <= 0.50) + { + if (_lastUsed == -1) + { + _lastUsed = System.currentTimeMillis(); + } + else + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + _lastUsed = System.currentTimeMillis(); + for (int i = 0; i < 6; i++) + { + getBoss().getEvent().registerCreature(new ReanimatedCorpse(getBoss().getChallenge(), getLocation())); + } + } + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/SummonMinions.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/SummonMinions.java new file mode 100644 index 000000000..7ea48dcd1 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/SummonMinions.java @@ -0,0 +1,52 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import org.bukkit.entity.Wither; + +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; + +public class SummonMinions extends BossPassive +{ + private long _lastUsed; + + public SummonMinions(CharlesWitherton creature) + { + super(creature); + _lastUsed = -1; + } + + @Override + public int getCooldown() + { + return 60; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + if (getBoss().getHealthPercent() <= 0.25) + { + if (_lastUsed == -1) + { + _lastUsed = System.currentTimeMillis(); + } + else + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + _lastUsed = System.currentTimeMillis(); + for (int i = 0; i < 2; i++) + { + getBoss().getEvent().registerCreature(new MiniCharles(getBoss(), getLocation())); + } + } + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/SummonUndead.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/SummonUndead.java new file mode 100644 index 000000000..0862c84df --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/SummonUndead.java @@ -0,0 +1,53 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import org.bukkit.entity.Wither; + +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.raid.wither.creature.mage.UndeadKnight; + +public class SummonUndead extends BossPassive +{ + private long _lastUsed; + + public SummonUndead(CharlesWitherton creature) + { + super(creature); + _lastUsed = -1; + } + + @Override + public int getCooldown() + { + return 60; + } + + @Override + public boolean isProgressing() + { + return false; + } + + @Override + public void tick() + { + if (getBoss().getHealthPercent() <= 0.50) + { + if (_lastUsed == -1) + { + _lastUsed = System.currentTimeMillis(); + } + else + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + _lastUsed = System.currentTimeMillis(); + for (int i = 0; i < 6; i++) + { + getBoss().getEvent().registerCreature(new UndeadKnight(getBoss().getChallenge(), getLocation())); + } + } + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/WitherWave.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/WitherWave.java new file mode 100644 index 000000000..ae7fea54c --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/WitherWave.java @@ -0,0 +1,91 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither; + +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.entity.Wither; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilShapes; +import mineplex.core.common.util.UtilTime; +import mineplex.game.clans.clans.worldevent.api.BossPassive; +import mineplex.game.clans.clans.worldevent.raid.wither.WitherRaid; + +public class WitherWave extends BossPassive +{ + private static final double RANGE = 10; + private long _lastUsed; + private int _chargeTicks; + + public WitherWave(CharlesWitherton creature) + { + super(creature); + _lastUsed = -1; + _chargeTicks = -1; + } + + @Override + public int getCooldown() + { + return 60; + } + + @Override + public boolean isProgressing() + { + return _chargeTicks != -1; + } + + @Override + public void tick() + { + if (_chargeTicks != -1) + { + _chargeTicks++; + if (_chargeTicks >= (20 * 5)) + { + for (Location loc : UtilShapes.getSphereBlocks(getLocation(), RANGE / 2, RANGE / 2, false)) + { + UtilParticle.playColoredParticleToAll(Color.GRAY, ParticleType.RED_DUST, loc, 2, ViewDist.MAX); + } + for (Player player : UtilPlayer.getInRadius(getLocation(), RANGE).keySet()) + { + getBoss().getEvent().getCondition().Factory().Wither("Wither Wave", player, getEntity(), 5, 1, false, true, false); + } + if (_chargeTicks >= (20 * 10)) + { + _lastUsed = System.currentTimeMillis(); + _chargeTicks = -1; + } + } + else + { + getEntity().teleport(getLocation()); + for (Location loc : UtilShapes.getSphereBlocks(getEntity().getEyeLocation(), 2, 2, true)) + { + UtilParticle.playColoredParticleToAll(Color.GRAY, ParticleType.RED_DUST, loc, 2, ViewDist.MAX); + } + } + return; + } + if (getBoss().getHealthPercent() <= 0.5) + { + if (_lastUsed == -1) + { + _lastUsed = System.currentTimeMillis(); + } + else + { + if (UtilTime.elapsed(_lastUsed, getCooldown() * 1000)) + { + _chargeTicks = 0; + ((WitherRaid)getBoss().getEvent()).getPlayers().forEach(player -> UtilPlayer.message(player, F.main(getBoss().getEvent().getName() + " Raid", "He's charging up Decay! Run away!"))); + } + } + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/ai/PathfinderGoalCustomFloat.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/ai/PathfinderGoalCustomFloat.java new file mode 100644 index 000000000..227413fd3 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/worldevent/raid/wither/creature/wither/ai/PathfinderGoalCustomFloat.java @@ -0,0 +1,33 @@ +package mineplex.game.clans.clans.worldevent.raid.wither.creature.wither.ai; + +import mineplex.game.clans.clans.worldevent.raid.wither.creature.wither.CharlesWitherton; +import net.minecraft.server.v1_8_R3.EntityInsentient; +import net.minecraft.server.v1_8_R3.Navigation; +import net.minecraft.server.v1_8_R3.PathfinderGoal; + +public class PathfinderGoalCustomFloat extends PathfinderGoal +{ + private CharlesWitherton _boss; + private EntityInsentient a; + + public PathfinderGoalCustomFloat(CharlesWitherton boss, EntityInsentient ent) + { + _boss = boss; + this.a = ent; + this.a(4); + ((Navigation)ent.getNavigation()).d(true); + } + + public boolean a() + { + return _boss.Flying; + } + + public void e() + { + if (this.a.bc().nextFloat() < 0.8F) + { + this.a.getControllerJump().a(); + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/economy/GoldManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/economy/GoldManager.java index 43da489eb..db67d9a1e 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/economy/GoldManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/economy/GoldManager.java @@ -366,6 +366,10 @@ public class GoldManager extends MiniDbClientPlugin { rewardGold(resultCallback, player, -amount, true); } + if (amount == 0 && resultCallback != null) + { + resultCallback.run(true); + } } public void rewardGold(final Callback callback, final Player player, final int amount, final boolean updateTotal) diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/CustomCreatures.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/CustomCreatures.java index b97ecbc2c..8dfc6ee3a 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/CustomCreatures.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/CustomCreatures.java @@ -1,23 +1,18 @@ package mineplex.game.clans.gameplay; -import mineplex.core.common.util.F; -import mineplex.core.common.util.UtilPlayer; - -import org.bukkit.Material; import org.bukkit.entity.EntityType; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.inventory.CraftItemEvent; -import org.bukkit.inventory.Recipe; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; public class CustomCreatures implements Listener { private static final EntityType[] DISABLED_CREATURES = { EntityType.WITCH, EntityType.PIG_ZOMBIE, - EntityType.HORSE, EntityType.ENDERMAN }; + EntityType.ENDERMAN }; + + private static final EntityType[] DISABLED_NATURAL = { EntityType.HORSE }; @EventHandler public void onCreatureSpawn(CreatureSpawnEvent event) @@ -26,6 +21,10 @@ public class CustomCreatures implements Listener { event.setCancelled(true); } + if (isDisabledNatural(event.getEntityType()) && event.getSpawnReason() != SpawnReason.CUSTOM) + { + event.setCancelled(true); + } } private boolean isDisabledCreature(EntityType entityType) @@ -40,4 +39,17 @@ public class CustomCreatures implements Listener return false; } -} + + private boolean isDisabledNatural(EntityType entityType) + { + for (EntityType disabledCreature : DISABLED_NATURAL) + { + if (disabledCreature == entityType) + { + return true; + } + } + + return false; + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/DurabilityManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/DurabilityManager.java new file mode 100644 index 000000000..995598c15 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/DurabilityManager.java @@ -0,0 +1,303 @@ +package mineplex.game.clans.gameplay; + +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Effect; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilEvent; +import mineplex.core.common.util.UtilEvent.ActionType; +import mineplex.core.common.util.UtilGear; +import mineplex.core.common.util.UtilInv; +import mineplex.core.common.util.UtilItem; +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.itemstack.ItemStackFactory; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.items.GearManager; + +public class DurabilityManager implements Listener +{ + private final Map _itemDurabilities = new HashMap<>(); + + public DurabilityManager() + { + _itemDurabilities.put(Material.DIAMOND_HELMET, 900); + _itemDurabilities.put(Material.DIAMOND_CHESTPLATE, 900); + _itemDurabilities.put(Material.DIAMOND_LEGGINGS, 900); + _itemDurabilities.put(Material.DIAMOND_BOOTS, 900); + _itemDurabilities.put(Material.DIAMOND_SWORD, 900); + _itemDurabilities.put(Material.DIAMOND_AXE, 900); + _itemDurabilities.put(Material.IRON_HELMET, 900); + _itemDurabilities.put(Material.IRON_CHESTPLATE, 900); + _itemDurabilities.put(Material.IRON_LEGGINGS, 900); + _itemDurabilities.put(Material.IRON_BOOTS, 900); + _itemDurabilities.put(Material.IRON_SWORD, 900); + _itemDurabilities.put(Material.IRON_AXE, 900); + _itemDurabilities.put(Material.CHAINMAIL_HELMET, 900); + _itemDurabilities.put(Material.CHAINMAIL_CHESTPLATE, 900); + _itemDurabilities.put(Material.CHAINMAIL_LEGGINGS, 900); + _itemDurabilities.put(Material.CHAINMAIL_BOOTS, 900); + _itemDurabilities.put(Material.GOLD_HELMET, 900); + _itemDurabilities.put(Material.GOLD_CHESTPLATE, 900); + _itemDurabilities.put(Material.GOLD_LEGGINGS, 900); + _itemDurabilities.put(Material.GOLD_BOOTS, 900); + _itemDurabilities.put(Material.GOLD_SWORD, 900); + _itemDurabilities.put(Material.GOLD_AXE, 900); + _itemDurabilities.put(Material.LEATHER_HELMET, 900); + _itemDurabilities.put(Material.LEATHER_CHESTPLATE, 900); + _itemDurabilities.put(Material.LEATHER_LEGGINGS, 900); + _itemDurabilities.put(Material.LEATHER_BOOTS, 900); + _itemDurabilities.put(Material.BOW, 900); + } + + private boolean canRepair(ItemStack item) + { + int repairs = ItemStackFactory.Instance.GetLoreVar(item, "Repaired", 0); + boolean canRepair = true; + + if (repairs >= 2) + { + canRepair = false; + } + + return canRepair; + } + + private int getItemDamage(ItemStack item) + { + if (item == null) + { + return 0; + } + if (_itemDurabilities.containsKey(item.getType())) + { + int defaultDurability = _itemDurabilities.get(item.getType()); + return defaultDurability - ItemStackFactory.Instance.GetLoreVar(item, "Durability", 0); + } + else + { + return item.getDurability(); + } + } + + private int itemDuraToLoreDura(ItemStack item) + { + if (item == null || !_itemDurabilities.containsKey(item.getType()) || UtilItem.isUnbreakable(item)) + { + return -1; + } + int currentDura = ItemStackFactory.Instance.GetLoreVar(item, "Durability", -1); + if (item.getDurability() == 0 && currentDura != -1) + { + return -1; + } + if (currentDura == -1) + { + updateItemDamage(item, 0, true); + return -2; + } + int newDura = (currentDura - item.getDurability()); + if (newDura <= 0) + { + return 0; + } + else + { + updateItemDamage(item, newDura, false); + item.setDurability((short)0); + } + return newDura; + } + + private void updateItemDamage(ItemStack item, int itemDamage, boolean subtractFromDefault) + { + if (item == null) + { + return; + } + if (_itemDurabilities.containsKey(item.getType())) + { + int defaultDurability = _itemDurabilities.get(item.getType()); + ItemStackFactory.Instance.SetLoreVar(item, "Durability", Math.min(defaultDurability, subtractFromDefault ? (defaultDurability - itemDamage) : itemDamage) + ""); + } + else + { + item.setDurability((short)itemDamage); + } + } + + @EventHandler + public void onUpdate(UpdateEvent event) + { + if (event.getType() == UpdateType.SEC) + { + Bukkit.getOnlinePlayers().forEach(player -> + { + boolean change = false; + for (int i = 0; i < player.getInventory().getArmorContents().length; i++) + { + int d = itemDuraToLoreDura(player.getInventory().getArmorContents()[i]); + if (d == -2) + { + change = true; + } + else if (d == 0) + { + ItemStack[] armor = new ItemStack[4]; + for (int ar = 0; ar < armor.length; ar++) + { + if (ar != i) + { + armor[ar] = player.getInventory().getArmorContents()[ar]; + } + else + { + armor[ar] = null; + } + } + player.getInventory().setArmorContents(armor); + change = true; + } + else if (d != -1) + { + change = true; + } + } + for (int i = 0; i < player.getInventory().getContents().length; i++) + { + int d = itemDuraToLoreDura(player.getInventory().getContents()[i]); + if (d == -2) + { + change = true; + } + else if (d == 0) + { + player.getInventory().setItem(i, null); + change = true; + } + else if (d != -1) + { + change = true; + } + } + + if (change) + { + UtilInv.Update(player); + } + }); + } + } + + @SuppressWarnings("deprecation") + @EventHandler + public void onRepair(PlayerInteractEvent event) + { + Player player = event.getPlayer(); + + if (event.getClickedBlock() == null || event.getClickedBlock().getType() != Material.ANVIL || !UtilEvent.isAction(event, ActionType.R_BLOCK) || player.isSneaking() || player.getItemInHand().getType() == Material.AIR) + { + return; + } + + if (UtilMath.offset(player.getLocation(), event.getClickedBlock().getLocation()) > 2) + { + UtilPlayer.message(player, F.main("Repair", "You are too far from the " + F.item("Anvil") + ".")); + return; + } + + ItemStack item = player.getItemInHand(); + + if (getItemDamage(item) <= 0) + { + UtilPlayer.message(player, F.main("Repair", "Your " + F.item(item == null ? ChatColor.YELLOW + "Hand" : item.getItemMeta().getDisplayName()) + " does not need repairs.")); + return; + } + + if (!UtilGear.isRepairable(item)) + { + UtilPlayer.message(player, F.main("Repair", "You cannot repair " + F.item(item.getItemMeta().getDisplayName()) + ".")); + return; + } + + if (GearManager.isCustomItem(item)) + { + UtilPlayer.message(player, F.main("Repair", "You cannot repair " + F.item(item.getItemMeta().getDisplayName()) + ".")); + return; + } + + int repairs = ItemStackFactory.Instance.GetLoreVar(item, "Repaired", 0); + boolean canRepair = canRepair(item); + + if (!canRepair) + { + UtilPlayer.message(player, F.main("Repair", "This item cannot be repaired anymore.")); + return; + } + + String creator = ItemStackFactory.Instance.GetLoreVar(item, "Owner"); + + if (creator != null) + { + if (creator.length() > 2) creator = creator.substring(2, creator.length()); + + if (!creator.equals(player.getName())) + { + UtilPlayer.message(player, F.main("Repair", "You cannot repair " + F.item(item.getItemMeta().getDisplayName()) + " by " + F.name(creator) + ".")); + return; + } + } + + if (ClansManager.getInstance().getBlockRestore().contains(event.getClickedBlock())) + { + UtilPlayer.message(player, F.main("Repair", "You cannot repair using that anvil.")); + return; + } + + // Repair! + UtilPlayer.message(player, F.main("Repair", "You repaired " + F.item(item.getItemMeta().getDisplayName()) + ".")); + updateItemDamage(item, 0, true); + UtilInv.Update(player); + + // Break + if (Math.random() > 0.85) + { + byte data = event.getClickedBlock().getData(); + if (data >= 8) // Anvil has already been damaged twice + { + player.getWorld().playEffect(event.getClickedBlock().getLocation(), Effect.STEP_SOUND, 145); + event.getClickedBlock().setType(Material.AIR); + } + else + { + event.getClickedBlock().setData((byte)(data + 4)); + } + } + + // Record + ItemStackFactory.Instance.SetLoreVar(item, "Repaired", (repairs + 1) + ""); + if (!canRepair(item)) + { + ItemMeta meta = item.getItemMeta(); + meta.getLore().add(ChatColor.BLUE + "Unrepairable"); + item.setItemMeta(meta); + } + + // Effect + player.playSound(player.getLocation(), Sound.ANVIL_USE, 1f, 1f); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/Gameplay.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/Gameplay.java index 70b87da02..d54d83ebb 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/Gameplay.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/Gameplay.java @@ -1,44 +1,8 @@ package mineplex.game.clans.gameplay; import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; - -import mineplex.core.MiniPlugin; -import mineplex.core.blockrestore.BlockRestore; -import mineplex.core.common.util.F; -import mineplex.core.common.util.UtilBlock; -import mineplex.core.common.util.UtilEvent; -import mineplex.core.common.util.UtilEvent.ActionType; -import mineplex.core.common.util.UtilGear; -import mineplex.core.common.util.UtilInv; -import mineplex.core.common.util.UtilItem; -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.weight.Weight; -import mineplex.core.common.weight.WeightSet; -import mineplex.core.itemstack.ItemStackFactory; -import mineplex.core.recharge.Recharge; -import mineplex.core.updater.UpdateType; -import mineplex.core.updater.event.UpdateEvent; -import mineplex.game.clans.clans.ClanInfo; -import mineplex.game.clans.clans.ClansManager; -import mineplex.game.clans.clans.event.ClansWaterPlaceEvent; -import mineplex.game.clans.clans.event.IronDoorOpenEvent; -import mineplex.game.clans.core.repository.ClanTerritory; -import mineplex.game.clans.items.GearManager; -import mineplex.minecraft.game.classcombat.Class.ClientClass; -import mineplex.minecraft.game.classcombat.Class.IPvpClass.ClassType; -import mineplex.minecraft.game.classcombat.Skill.event.BlockTossEvent; -import mineplex.minecraft.game.classcombat.Skill.event.BlockTossLandEvent; -import mineplex.minecraft.game.core.damage.CustomDamageEvent; -import mineplex.minecraft.game.core.damage.DamageManager; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.DyeColor; import org.bukkit.Effect; import org.bukkit.Location; @@ -66,19 +30,41 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityShootBowEvent; import org.bukkit.event.entity.EntitySpawnEvent; import org.bukkit.event.entity.FoodLevelChangeEvent; -import org.bukkit.event.player.PlayerBucketEmptyEvent; -import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.event.player.PlayerFishEvent; import org.bukkit.event.player.PlayerFishEvent.State; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.weather.WeatherChangeEvent; import org.bukkit.event.world.StructureGrowEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.material.Dye; import org.bukkit.plugin.java.JavaPlugin; +import mineplex.core.MiniPlugin; +import mineplex.core.blockrestore.BlockRestore; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilBlock; +import mineplex.core.common.util.UtilEvent; +import mineplex.core.common.util.UtilEvent.ActionType; +import mineplex.core.common.util.UtilInv; +import mineplex.core.common.util.UtilItem; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.weight.Weight; +import mineplex.core.common.weight.WeightSet; +import mineplex.core.itemstack.ItemStackFactory; +import mineplex.core.recharge.Recharge; +import mineplex.game.clans.clans.ClanInfo; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.event.ClansWaterPlaceEvent; +import mineplex.game.clans.clans.event.IronDoorOpenEvent; +import mineplex.game.clans.core.repository.ClanTerritory; +import mineplex.minecraft.game.classcombat.Class.ClientClass; +import mineplex.minecraft.game.classcombat.Class.IPvpClass.ClassType; +import mineplex.minecraft.game.classcombat.Skill.event.BlockTossEvent; +import mineplex.minecraft.game.classcombat.Skill.event.BlockTossLandEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import mineplex.minecraft.game.core.damage.DamageManager; + public class Gameplay extends MiniPlugin { private static final int MAX_BUILD_HEIGHT = 120; @@ -102,6 +88,7 @@ public class Gameplay extends MiniPlugin // Register the custom recipes and mobs Bukkit.getPluginManager().registerEvents(new CustomRecipes(), plugin); Bukkit.getPluginManager().registerEvents(new CustomCreatures(), plugin); + Bukkit.getPluginManager().registerEvents(new DurabilityManager(), plugin); } // @EventHandler(priority = EventPriority.LOWEST) @@ -760,116 +747,6 @@ public class Gameplay extends MiniPlugin } } - @EventHandler - public void Repair(PlayerInteractEvent event) - { - Player player = event.getPlayer(); - - if (event.getClickedBlock() == null || event.getClickedBlock().getType() != Material.ANVIL || !UtilEvent.isAction(event, ActionType.R_BLOCK) || player.isSneaking() || player.getItemInHand().getType() == Material.AIR) - { - return; - } - - if (UtilMath.offset(player.getLocation(), event.getClickedBlock().getLocation()) > 2) - { - UtilPlayer.message(player, F.main("Repair", "You are too far from the " + F.item("Anvil") + ".")); - return; - } - - ItemStack item = player.getItemInHand(); - - if (item.getDurability() <= 0) - { - UtilPlayer.message(player, F.main("Repair", "Your " + F.item(item == null ? ChatColor.YELLOW + "Hand" : item.getItemMeta().getDisplayName()) + " does not need repairs.")); - return; - } - - if (!UtilGear.isRepairable(item)) - { - UtilPlayer.message(player, F.main("Repair", "You cannot repair " + F.item(item.getItemMeta().getDisplayName()) + ".")); - return; - } - - if (GearManager.isCustomItem(item)) - { - UtilPlayer.message(player, F.main("Repair", "You cannot repair " + F.item(item.getItemMeta().getDisplayName()) + ".")); - return; - } - - int repairs = ItemStackFactory.Instance.GetLoreVar(item, "Repaired", 0); - boolean canRepair = canRepair(item); - - if (!canRepair) - { - UtilPlayer.message(player, F.main("Repair", "This item cannot be repaired anymore.")); - return; - } - - String creator = ItemStackFactory.Instance.GetLoreVar(item, "Owner"); - - if (creator != null) - { - if (creator.length() > 2) creator = creator.substring(2, creator.length()); - - if (!creator.equals(player.getName())) - { - UtilPlayer.message(player, F.main("Repair", "You cannot repair " + F.item(item.getItemMeta().getDisplayName()) + " by " + F.name(creator) + ".")); - return; - } - } - - if (_blockRestore.contains(event.getClickedBlock())) - { - UtilPlayer.message(player, F.main("Repair", "You cannot repair using that anvil")); - return; - } - - // Repair! - UtilPlayer.message(player, F.main("Repair", "You repaired " + F.item(item.getItemMeta().getDisplayName()) + ".")); - item.setDurability((short) 0); - UtilInv.Update(player); - - // Break - if (Math.random() > 0.85) - { - byte data = event.getClickedBlock().getData(); - if (data >= 8) // Anvil has already been damaged twice - { - player.getWorld().playEffect(event.getClickedBlock().getLocation(), Effect.STEP_SOUND, 145); - event.getClickedBlock().setType(Material.AIR); - } - else - { - event.getClickedBlock().setData((byte)(data + 4)); - } - } - - // Record - ItemStackFactory.Instance.SetLoreVar(item, "Repaired", (repairs + 1) + ""); - if (!canRepair(item)) - { - ItemMeta meta = item.getItemMeta(); - meta.getLore().add(ChatColor.BLUE + "Nonfixable"); - item.setItemMeta(meta); - } - - // Effect - player.playSound(player.getLocation(), Sound.ANVIL_USE, 1f, 1f); - } - - private boolean canRepair(ItemStack item) - { - int repairs = ItemStackFactory.Instance.GetLoreVar(item, "Repaired", 0); - boolean gold = UtilGear.isGold(item); - boolean canRepair = true; - - if (repairs >= 3 && gold) - canRepair = false; - else if (repairs >= 2 && !gold) canRepair = false; - - return canRepair; - } - public DamageManager getDamageManager() { return _damageManager; diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/safelog/SafeLog.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/safelog/SafeLog.java index 44efed198..d964df566 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/safelog/SafeLog.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/safelog/SafeLog.java @@ -23,8 +23,9 @@ import mineplex.core.common.util.UtilServer; import mineplex.core.common.util.UtilTextMiddle; import mineplex.core.common.util.UtilTime; import mineplex.game.clans.clans.ClanTips.TipType; -import mineplex.game.clans.clans.ban.ClansBanManager; import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.ban.ClansBanManager; +import mineplex.game.clans.clans.worldevent.raid.RaidManager; import mineplex.game.clans.gameplay.safelog.npc.NPCManager; import mineplex.game.clans.restart.RestartManager; @@ -75,6 +76,11 @@ public class SafeLog extends MiniPlugin isSafeLog = true; } + if (Managers.get(RaidManager.class).isInRaid(player.getLocation())) + { + isSafeLog = true; + } + if (!isSafeLog) { if (!_clansManager.getIncognitoManager().Get(player).Status) diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/safelog/npc/CombatLogNPC.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/safelog/npc/CombatLogNPC.java index 24417d878..4dfa74bdd 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/safelog/npc/CombatLogNPC.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/gameplay/safelog/npc/CombatLogNPC.java @@ -10,7 +10,6 @@ import org.bukkit.Location; import org.bukkit.World; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; -import org.bukkit.entity.ArmorStand; import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -45,7 +44,6 @@ public class CombatLogNPC private boolean _creative; private LivingEntity _npc; - private ArmorStand _stand; private CraftLivingEntity _lastDamager; @@ -153,13 +151,6 @@ public class CombatLogNPC System.out.println("Despawning"); if (_npc != null) { - if (_stand != null) - { - _stand.setPassenger(null); - _stand.remove(); - _stand = null; - } - _npc.remove(); _npc = null; _hologram.stop(); @@ -211,16 +202,7 @@ public class CombatLogNPC DisguisePlayer disguise = new DisguisePlayer(skel, ((CraftPlayer) player).getHandle().getProfile()); _disguiseManager.disguise(disguise, attempted -> inRange.contains(attempted)); - if (!UtilEnt.isGrounded(player)) - { - ArmorStand stand = player.getWorld().spawn(spawnLoc.clone().subtract(0,1,0), ArmorStand.class); - - stand.setVisible(false); - stand.setPassenger(skel); - stand.setGravity(false); - - _stand = stand; - } + _hologram.setFollowEntity(skel); return skel; } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/GearManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/GearManager.java index b25959a72..dfb7547ea 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/GearManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/GearManager.java @@ -47,6 +47,7 @@ import mineplex.game.clans.items.commands.GearCommand; import mineplex.game.clans.items.commands.RuneCommand; import mineplex.game.clans.items.economy.GoldToken; import mineplex.game.clans.items.legendaries.AlligatorsTooth; +import mineplex.game.clans.items.legendaries.DemonicScythe; import mineplex.game.clans.items.legendaries.GiantsBroadsword; import mineplex.game.clans.items.legendaries.HyperAxe; import mineplex.game.clans.items.legendaries.LegendaryItem; @@ -204,6 +205,7 @@ public class GearManager extends MiniPlugin implements IPacketHandler, Runnable customItemType.registerSubtype(GoldToken.class); LEGENDARY_WEIGHTS.elements().forEach(customItemType::registerSubtype); RARE_WEIGHTS.elements().forEach(customItemType::registerSubtype); + customItemType.registerSubtype(DemonicScythe.class); // Build GSON instance off factories for future serialization of items. GSON = new GsonBuilder().registerTypeAdapterFactory(attributeFactory).registerTypeAdapterFactory(customItemType).create(); diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/legendaries/DemonicScythe.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/legendaries/DemonicScythe.java new file mode 100644 index 000000000..b054624ad --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/legendaries/DemonicScythe.java @@ -0,0 +1,30 @@ +package mineplex.game.clans.items.legendaries; + +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import mineplex.core.common.util.C; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; + +public class DemonicScythe extends LegendaryItem +{ + public DemonicScythe() + { + super("Scythe of the Fallen Lord", new String[]{ + C.cWhite + "An old blade fashioned of nothing more", + C.cWhite + "than bones and cloth which served no", + C.cWhite + "purpose. Brave adventurers however have", + C.cWhite + "imbued it with the remnant powers of a", + C.cWhite + "dark and powerful foe.", + " ", + C.cYellow + "Attack" + C.cWhite + " to use" + C.cGreen + " Leach Health", + }, Material.RECORD_8); + } + + @Override + public void onAttack(CustomDamageEvent event, Player wielder) + { + event.AddMod("Scythe of the Fallen Lord", 8); + wielder.setHealth(Math.min(wielder.getMaxHealth(), wielder.getHealth() + 2)); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/legendaries/MeridianScepter.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/legendaries/MeridianScepter.java index 26003be99..01f539904 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/legendaries/MeridianScepter.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/legendaries/MeridianScepter.java @@ -1,6 +1,19 @@ package mineplex.game.clans.items.legendaries; import java.util.HashMap; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.util.Vector; import mineplex.core.common.util.C; import mineplex.core.common.util.F; @@ -20,25 +33,13 @@ import mineplex.core.common.util.UtilTime; import mineplex.core.recharge.Recharge; import mineplex.game.clans.clans.ClansManager; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.entity.EntityDamageEvent.DamageCause; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.util.Vector; - public class MeridianScepter extends LegendaryItem { private static final RGBData[] COLORS = { UtilColor.RgbPurple, UtilColor.RgbPurple.Lighten(), UtilColor.RgbPurple.Darken() }; private long _interactWait; - private transient HashMap _animations = new HashMap(); + private transient Map _animations = new HashMap<>(); public MeridianScepter() { diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/rares/RunedPickaxe.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/rares/RunedPickaxe.java index 70837d017..33e26bbb0 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/rares/RunedPickaxe.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/rares/RunedPickaxe.java @@ -1,11 +1,8 @@ package mineplex.game.clans.items.rares; -import java.util.HashSet; - import org.bukkit.Effect; import org.bukkit.Material; import org.bukkit.Sound; -import org.bukkit.block.Block; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; @@ -39,9 +36,8 @@ public class RunedPickaxe extends RareItem static { - UtilServer.RegisterEvents(new Listener() { - - @SuppressWarnings("deprecation") + UtilServer.RegisterEvents(new Listener() + { @EventHandler public void update(UpdateEvent event) { @@ -105,6 +101,9 @@ public class RunedPickaxe extends RareItem if (ClansManager.getInstance().getNetherManager().getNetherWorld().equals(event.getBlock().getWorld())) return; + if (ClansManager.getInstance().getWorldEvent().getRaidManager().isInRaid(event.getBlock().getLocation())) + return; + if (ClansManager.getInstance().getBlockRestore().contains(event.getBlock())) return; @@ -119,7 +118,7 @@ public class RunedPickaxe extends RareItem } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void blockDamage(BlockBreakEvent event) + public void blockBreak(BlockBreakEvent event) { PlayerGear gear = ClansManager.getInstance().getGearManager().getPlayerGear(event.getPlayer()); @@ -136,6 +135,9 @@ public class RunedPickaxe extends RareItem if (ClansManager.getInstance().getBlockRestore().contains(event.getBlock())) return; + if (ClansManager.getInstance().getWorldEvent().getRaidManager().isInRaid(event.getBlock().getLocation())) + return; + if (!pick._enabled) { event.setCancelled(true); @@ -168,6 +170,5 @@ public class RunedPickaxe extends RareItem } super.onInteract(event); - } - -} + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/ui/GearPage.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/ui/GearPage.java index a2cc1a83f..7bda255f0 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/ui/GearPage.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/items/ui/GearPage.java @@ -43,6 +43,7 @@ import mineplex.game.clans.items.attributes.weapon.HasteAttribute; import mineplex.game.clans.items.attributes.weapon.JaggedAttribute; import mineplex.game.clans.items.attributes.weapon.SharpAttribute; import mineplex.game.clans.items.legendaries.AlligatorsTooth; +import mineplex.game.clans.items.legendaries.DemonicScythe; import mineplex.game.clans.items.legendaries.EnergyCrossbow; import mineplex.game.clans.items.legendaries.GiantsBroadsword; import mineplex.game.clans.items.legendaries.HyperAxe; @@ -105,7 +106,7 @@ public class GearPage extends ShopPageBase } }; - _legendaryItems = Arrays.> asList(MeridianScepter.class, AlligatorsTooth.class, WindBlade.class, GiantsBroadsword.class, HyperAxe.class, MagneticMaul.class); + _legendaryItems = Arrays.> asList(MeridianScepter.class, AlligatorsTooth.class, WindBlade.class, GiantsBroadsword.class, HyperAxe.class, MagneticMaul.class, DemonicScythe.class); _rareItems = Arrays.> asList(RunedPickaxe.class); @@ -236,7 +237,7 @@ public class GearPage extends ShopPageBase } }, _factory != null && ItemType.LEGENDARY.equals(_factory.getItemType()), new String[] { _factory != null && ItemType.LEGENDARY.equals(_factory.getItemType()) ? C.cGreen + "Selected" : C.cRed + "Not Selected" }); - addButton(indices[1], Material.RECORD_8, 0, C.cAqua + "Rare", new IButton() + addButton(indices[1], Material.RECORD_7, 0, C.cAqua + "Rare", new IButton() { public void onClick(Player player, ClickType clickType) { diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/restart/RestartManager.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/restart/RestartManager.java index 52571a49a..572534b0d 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/restart/RestartManager.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/restart/RestartManager.java @@ -11,7 +11,6 @@ import org.bukkit.event.player.PlayerLoginEvent.Result; import org.bukkit.event.server.ServerListPingEvent; import org.bukkit.plugin.java.JavaPlugin; -import mineplex.core.Managers; import mineplex.core.MiniPlugin; import mineplex.core.common.util.C; import mineplex.core.common.util.F; @@ -94,6 +93,10 @@ public class RestartManager extends MiniPlugin { return false; } + if (ClansManager.getInstance().getWorldEvent().getRaidManager().getActiveRaids() > 0) + { + return false; + } return true; } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/ClansShopItem.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/ClansShopItem.java index 636854481..d2d472edf 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/ClansShopItem.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/ClansShopItem.java @@ -48,15 +48,15 @@ public enum ClansShopItem REDSTONE(10, 2, Material.REDSTONE, 1), LAPIS_BLOCK(500, 100, Material.LAPIS_BLOCK, 1), // Farming Shop - POTATO_ITEM(15, 3, Material.POTATO_ITEM, 1), - MELON(5, 1, Material.MELON, 1), - BREAD(30, 6, Material.BREAD, 1), - COOKED_BEEF(50, 10, Material.COOKED_BEEF, 1), - GRILLED_PORK(50, 10, Material.GRILLED_PORK, 1), - COOKED_CHICKEN(35, 7, Material.COOKED_CHICKEN, 1), + POTATO_ITEM(15, 8, Material.POTATO_ITEM, 1), + MELON(5, 3, Material.MELON, 1), + BREAD(30, 16, Material.BREAD, 1), + COOKED_BEEF(50, 27, Material.COOKED_BEEF, 1), + GRILLED_PORK(50, 27, Material.GRILLED_PORK, 1), + COOKED_CHICKEN(35, 19, Material.COOKED_CHICKEN, 1), FEATHER(50, 10, Material.FEATHER, 1), - CARROT_ITEM(10, 2, Material.CARROT_ITEM, 1), - MUSHROOM_SOUP(200, 40, Material.MUSHROOM_SOUP, 1), + CARROT_ITEM(10, 5, Material.CARROT_ITEM, 1), + MUSHROOM_SOUP(200, 109, Material.MUSHROOM_SOUP, 1), SUGAR_CANE(15, 3, Material.SUGAR_CANE, 1), PUMPKIN(30, 6, Material.PUMPKIN, 1), STRING(50, 10, Material.STRING, 1), @@ -78,7 +78,7 @@ public enum ClansShopItem QUARTZ_BLOCK(75, 15, Material.QUARTZ_BLOCK, 1), CLAY(30, 6, Material.CLAY, 1), GOLD_TOKEN(50000, 50000, Material.GOLD_RECORD, 1, (byte) 0, "Gold Token"), - OUTPOST(30000, 0, Material.BEACON, 1, (byte) 0, C.cBlue + "Outpost"), + OUTPOST(100000, 0, Material.BEACON, 1, (byte) 0, C.cBlue + "Outpost"), CANNON(25000, 0, Material.SPONGE, 1, (byte) 1, C.cBlue + "Cannon"); private int _buyPrice; diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/ShopItemButton.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/ShopItemButton.java index 8a292032d..3e3a4e7b0 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/ShopItemButton.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/ShopItemButton.java @@ -9,7 +9,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import mineplex.core.common.util.C; -import mineplex.core.common.util.Callback; import mineplex.core.common.util.F; import mineplex.core.common.util.InventoryUtil; import mineplex.core.common.util.UtilItem; @@ -109,38 +108,35 @@ public class ShopItemButton> implements IButton final ItemStack eventItem = _item.clone(); eventItem.setAmount(amount); - GoldManager.getInstance().deductGold(new Callback() + GoldManager.getInstance().deductGold(success -> { - public void run(Boolean success) + if (success) { - if (success) + ClansPlayerBuyItemEvent event = new ClansPlayerBuyItemEvent(player, _page, ShopItemButton.this, eventItem, cost, amount); + UtilServer.getServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { - ClansPlayerBuyItemEvent event = new ClansPlayerBuyItemEvent(player, _page, ShopItemButton.this, eventItem, cost, amount); - UtilServer.getServer().getPluginManager().callEvent(event); - - if (event.isCancelled()) - { - GoldManager.getInstance().addGold(player, cost); - return; - } - - _item = event.getItem(); - final int finalCost = event.getCost(); - final int finalAmount = event.getAmount(); - - giftItem(player, finalAmount); - GoldManager.notify(player, String.format("You have purchased %d item(s) for %dg", finalAmount, finalCost)); - - _page.playAcceptSound(player); - } - else - { - GoldManager.notify(player, "You cannot afford that item! Please relog to update your gold count."); - _page.playDenySound(player); + GoldManager.getInstance().addGold(player, cost); + return; } - _page.refresh(); + _item = event.getItem(); + final int finalCost = event.getCost(); + final int finalAmount = event.getAmount(); + + giftItem(player, finalAmount); + GoldManager.notify(player, String.format("You have purchased %d item(s) for %dg", finalAmount, finalCost)); + + _page.playAcceptSound(player); } + else + { + GoldManager.notify(player, "You cannot afford that item! Please relog to update your gold count."); + _page.playDenySound(player); + } + + _page.refresh(); }, player, cost); } else diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/pvp/MountBuyButton.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/pvp/MountBuyButton.java new file mode 100644 index 000000000..a0838568f --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/pvp/MountBuyButton.java @@ -0,0 +1,74 @@ +package mineplex.game.clans.shop.pvp; + +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.recharge.Recharge; +import mineplex.core.shop.item.IButton; +import mineplex.core.shop.page.ShopPageBase; +import mineplex.game.clans.clans.mounts.Mount.MountType; +import mineplex.game.clans.clans.mounts.MountClaimToken; +import mineplex.game.clans.economy.GoldManager; + +public class MountBuyButton> implements IButton +{ + private int _buyPrice; + private ItemStack _item; + private T _page; + + public MountBuyButton(T page) + { + _page = page; + _buyPrice = 150000; + _item = new MountClaimToken(1, 1, 1, MountType.HORSE).toItem(); + } + + @Override + public void onClick(final Player player, ClickType clickType) + { + if (!Recharge.Instance.use(player, "Attempt Buy Clans Shop Item", 1500, false, false)) + { + return; + } + if (clickType == ClickType.SHIFT_LEFT || clickType == ClickType.LEFT) + { + int goldCount = GoldManager.getInstance().getGold(player); + + if (goldCount >= _buyPrice) + { + GoldManager.getInstance().deductGold(success -> + { + if (success) + { + giftItem(player, 1); + GoldManager.notify(player, String.format("You have purchased %d item(s) for %dg", 1, _buyPrice)); + + _page.playAcceptSound(player); + } + else + { + GoldManager.notify(player, "You cannot afford that item! Please relog to update your gold count."); + _page.playDenySound(player); + } + + _page.refresh(); + }, player, _buyPrice); + } + else + { + GoldManager.notify(player, "You cannot afford that item."); + _page.playDenySound(player); + } + } + + _page.refresh(); + } + + private void giftItem(Player player, int amount) + { + ItemStack item = _item.clone(); + item.setAmount(amount); + player.getInventory().addItem(item); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/pvp/PvpPage.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/pvp/PvpPage.java index b36ea0510..27d119e6c 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/pvp/PvpPage.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/pvp/PvpPage.java @@ -1,9 +1,12 @@ package mineplex.game.clans.shop.pvp; +import org.bukkit.Material; + import mineplex.core.account.CoreClientManager; import mineplex.core.common.util.C; import mineplex.core.donation.DonationManager; import mineplex.core.itemstack.ItemBuilder; +import mineplex.game.clans.Clans; import mineplex.game.clans.clans.ClansManager; import mineplex.game.clans.shop.ClansShopItem; import mineplex.game.clans.shop.ClansShopPage; @@ -57,14 +60,22 @@ public class PvpPage extends ClansShopPage addShopItem(33, ClansShopItem.BOW, "Standard Bow"); addShopItem(34, ClansShopItem.ARROW, (byte) 0, "Arrows", 16); - addShopItem(52 - 9, ClansShopItem.CANNON, C.cBlue + "Cannon"); - addShopItem(53 - 9, ClansShopItem.OUTPOST, C.cBlue + "Outpost"); + addButton(51 - 9, new ItemBuilder(Material.IRON_BARDING).setTitle(C.cGreenB + "Standard Mount").setLore(C.cRed, C.cYellow + "Left-Click" + C.cWhite + " to buy " + C.cGreen + "1", C.cWhite + "Costs " + C.cGreen + "150000g").build(), new MountBuyButton<>(this)); + + if (Clans.HARDCORE) + { + addShopItem(52 - 9, ClansShopItem.CANNON, C.cBlue + "Cannon"); + addShopItem(53 - 9, ClansShopItem.OUTPOST, C.cBlue + "Outpost"); + } addShopItem(51, ClansShopItem.ENCHANTMENT_TABLE, "Class Shop"); - addShopItem(52, ClansShopItem.TNT, "TNT"); - addButton(53, new ItemBuilder(ClansShopItem.TNT_GENERATOR.getMaterial()).setTitle(C.cAqua + "Manage TNT Generator").build(), (player, click) -> - new TNTGenShop(_plugin, _clientManager, _donationManager).attemptShopOpen(player) - ); + + if (Clans.HARDCORE) + { + addShopItem(52, ClansShopItem.TNT, "TNT"); + addButton(53, new ItemBuilder(ClansShopItem.TNT_GENERATOR.getMaterial()).setTitle(C.cAqua + "Manage TNT Generator").build(), (player, click) -> + new TNTGenShop(_plugin, _clientManager, _donationManager).attemptShopOpen(player) + ); + } } - -} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/pvp/tnt/TNTGenPage.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/pvp/tnt/TNTGenPage.java index 367cc8464..efae5fd11 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/pvp/tnt/TNTGenPage.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/shop/pvp/tnt/TNTGenPage.java @@ -84,7 +84,9 @@ public class TNTGenPage extends ShopPageBase nextTnt = UtilTime.MakeStr((TntGeneratorManager.SECONDS_PER_TNT - generator.getTicks()) * 1000); } - addButton(13, new ItemBuilder(Material.BREWING_STAND_ITEM) + if (clan.getMembers().containsKey(generator.getBuyer())) + { + addButton(13, new ItemBuilder(Material.BREWING_STAND_ITEM) .setTitle(C.cGreen + "TNT Generator") .setLore( " ", @@ -95,7 +97,24 @@ public class TNTGenPage extends ShopPageBase C.cWhite + "Next TNT: " + F.elem(nextTnt)).build(), (player, click) -> { clearPage(); buildPage(); - }); + } + ); + } + else + { + addButton(13, new ItemBuilder(Material.BREWING_STAND_ITEM) + .setTitle(C.cGreen + "TNT Generator") + .setLore( + " ", + C.cWhite + "TNT Available: " + F.elem(Integer.valueOf(generator.getStock())), + " ", + C.cWhite + "Next TNT: " + F.elem(nextTnt)).build(), (player, click) -> + { + clearPage(); + buildPage(); + } + ); + } if (generator.getStock() == 0) { @@ -138,5 +157,4 @@ public class TNTGenPage extends ShopPageBase } } } - -} +} \ No newline at end of file diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/spawn/Spawn.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/spawn/Spawn.java index 979b9743e..07750faf6 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/spawn/Spawn.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/spawn/Spawn.java @@ -470,17 +470,17 @@ public class Spawn extends MiniPlugin public static Location getEastTown() { - return new Location(getSpawnWorld(), 440.91, 72, -23.08); + return new Location(getSpawnWorld(), 440.91, 63, -23.08); } public static Location getEastTownCenter() { - return new Location(getSpawnWorld(), 425, 72, -8); + return new Location(getSpawnWorld(), 425, 63, -8); } public static Location getNorthSpawn() { - return new Location(getSpawnWorld(), 8.5, 200, -393.5); + return new Location(getSpawnWorld(), 8.5, 206, -393.5); } public static Location getSouthSpawn() diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/spawn/travel/TravelPage.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/spawn/travel/TravelPage.java index 25b584e64..93deef212 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/spawn/travel/TravelPage.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/spawn/travel/TravelPage.java @@ -20,6 +20,7 @@ import mineplex.core.portal.Intent; import mineplex.core.portal.Portal; import mineplex.core.shop.item.IButton; import mineplex.core.shop.page.ShopPageBase; +import mineplex.game.clans.Clans; import mineplex.game.clans.clans.ClanInfo; import mineplex.game.clans.clans.ClanRole; import mineplex.game.clans.clans.ClansManager; @@ -77,15 +78,18 @@ public class TravelPage extends ShopPageBase }, 14 + 10, ClanIcon.CASTLE.getData()); final ClanInfo clan = _plugin.getClan(getPlayer()); - Outpost outpost = _plugin.getSiegeManager().getOutpostManager().Get(clan); - - addTravelLocation(outpost == null ? null : outpost.getCoreLocation().clone().add(0, 1, 0), ClansShopItem.OUTPOST.getMaterial(), (outpost == null ? C.cRedB : C.cDGreenB) + "Outpost", new String[] { - C.cWhite + "Teleport to your Clan's currently", - C.cWhite + "active Outpost.", - " ", - (outpost == null ? C.cRed + "Your Clan does not have an Outpost." : ""), - }, 8, ClanIcon.CASTLE.getData()); + if (Clans.HARDCORE) + { + Outpost outpost = _plugin.getSiegeManager().getOutpostManager().Get(clan); + + addTravelLocation(outpost == null ? null : outpost.getCoreLocation().clone().add(0, 1, 0), ClansShopItem.OUTPOST.getMaterial(), (outpost == null ? C.cRedB : C.cDGreenB) + "Outpost", new String[] { + C.cWhite + "Teleport to your Clan's currently", + C.cWhite + "active Outpost.", + " ", + (outpost == null ? C.cRed + "Your Clan does not have an Outpost." : ""), + }, 8, ClanIcon.CASTLE.getData()); + } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorial/tutorials/clans/ClansMainTutorial.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorial/tutorials/clans/ClansMainTutorial.java index 804966bb3..9e843924e 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorial/tutorials/clans/ClansMainTutorial.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/tutorial/tutorials/clans/ClansMainTutorial.java @@ -137,15 +137,10 @@ public class ClansMainTutorial extends Tutorial if (!_taskManager.hasCompletedTask(player, getTaskIdentifier())) { - _taskManager.completedTask(new Callback() + _taskManager.completedTask(data -> { - @Override - public void run(Boolean data) - { - - GoldManager.getInstance().addGold(player, 32000); - UtilPlayer.message(player, F.main("Clans", "You have earned " + F.elem(32000 + " Gold") + " for finishing the tutorial!")); - } + GoldManager.getInstance().addGold(player, 32000); + UtilPlayer.message(player, F.main("Clans", "You have earned " + F.elem(32000 + " Gold") + " for finishing the tutorial!")); }, player, getTaskIdentifier()); } @@ -469,7 +464,7 @@ public class ClansMainTutorial extends Tutorial // } // }); - /*if (!_taskManager.hasCompletedTask(event.getPlayer(), getTaskIdentifier())) + if (!_taskManager.hasCompletedTask(event.getPlayer(), getTaskIdentifier())) { ClanInfo clan = ClansManager.getInstance().getClan(event.getPlayer()); if (clan == null) @@ -481,7 +476,7 @@ public class ClansMainTutorial extends Tutorial UtilPlayer.message(event.getPlayer(), F.main("Clans", "It seems you already have a clan here, so we can skip the tutorial")); } } - else */if (!event.getPlayer().hasPlayedBefore() || !event.getPlayer().getLocation().getWorld().equals(Spawn.getSpawnWorld())) + else if (!event.getPlayer().hasPlayedBefore() || !event.getPlayer().getLocation().getWorld().equals(Spawn.getSpawnWorld())) { Spawn.getInstance().teleport(event.getPlayer(), Spawn.getInstance().getSpawnLocation(), 2); } diff --git a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansServerPage.java b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansServerPage.java index a561d15fc..983c5ef29 100644 --- a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansServerPage.java +++ b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansServerPage.java @@ -1,20 +1,23 @@ package mineplex.clanshub; import java.util.Collection; -import java.util.Comparator; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import mineplex.core.Managers; import mineplex.core.account.CoreClientManager; import mineplex.core.common.Rank; import mineplex.core.common.util.C; import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilTime; +import mineplex.core.common.util.UtilTime.TimeUnit; import mineplex.core.donation.DonationManager; import mineplex.core.shop.item.ShopItem; import mineplex.core.shop.page.ShopPageBase; +import mineplex.core.stats.StatsManager; import mineplex.game.clans.core.repository.tokens.SimpleClanToken; -import org.bukkit.Material; -import org.bukkit.entity.Player; - /** * GUI page for clans servers */ @@ -31,37 +34,54 @@ public class ClansServerPage extends ShopPageBase= UtilTime.convert(20, TimeUnit.HOURS, TimeUnit.SECONDS); + } + + private String timeTillUnlockHardcore() + { + if (canPlayHardcore()) + { + return "0 Seconds"; } else { - buildJoinHomeServer(clan); + long secondsPlayed = Managers.get(StatsManager.class).Get(_player).getStat("Clans.TimePlaying"); + long needed = UtilTime.convert(20, TimeUnit.HOURS, TimeUnit.SECONDS); + + return UtilTime.MakeStr(UtilTime.convert(needed - secondsPlayed, TimeUnit.SECONDS, TimeUnit.MILLISECONDS)); } } private void buildNoClanPage() { - Collection servers = UtilAlg.sortSet(getPlugin().getServers(), new Comparator() + Collection servers = UtilAlg.sortSet(getPlugin().getServers(true), (o1, o2) -> { - @Override - public int compare(ServerInfo o1, ServerInfo o2) - { - return o1.Name.compareTo(o2.Name); - } + return o1.Name.compareTo(o2.Name); }); int currentSlot = 9; @@ -93,39 +113,57 @@ public class ClansServerPage extends ShopPageBase servers = UtilAlg.sortSet(getPlugin().getServers(), new Comparator() + if (!clan.getClanName().isEmpty()) { - @Override - public int compare(ServerInfo o1, ServerInfo o2) - { - return o1.Name.compareTo(o2.Name); - } + ServerInfo serverInfo = getServerInfo(clan.getHomeServer()); + boolean serverOnline = (serverInfo != null); + String serverStatus = serverOnline ? C.cGreen + "Online" : C.cRed + "Offline"; + + String title = (serverOnline ? C.cGreen : C.cRed) + C.Bold + "Join Home Server!"; + String serverName = C.cYellow + "Server Name: " + C.cWhite + clan.getHomeServer(); + String serverDesc = C.cYellow + "Server Status: " + C.cWhite + serverStatus; + String players = C.cYellow + "Players: " + C.cWhite + (serverOnline ? serverInfo.CurrentPlayers + "/" + serverInfo.MaxPlayers : "0/0"); + String mode = C.cYellow + "Mode " + C.cWhite + (serverInfo.Hardcore ? "Hardcore" : "Casual"); + ShopItem shopItem = new ShopItem(Material.EMERALD_BLOCK, title, new String[] {" ", serverName, serverDesc, players, mode, " "}, 0, true, true); + addButton(13, shopItem, new JoinServerButton(this, getPlugin(), getServerInfo(clan.getHomeServer()))); + } + + Collection servers = UtilAlg.sortSet(getPlugin().getServers(true), (o1, o2) -> + { + return o1.Name.compareTo(o2.Name); }); int currentSlot = 27; for (ServerInfo server : servers) { - if (server.Name.equalsIgnoreCase(clan.getHomeServer())) + if (!clan.getClanName().isEmpty() && server.Name.equalsIgnoreCase(clan.getHomeServer())) { continue; } diff --git a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansTransferManager.java b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansTransferManager.java index 4bbbf3c9d..6229d8b3e 100644 --- a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansTransferManager.java +++ b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansTransferManager.java @@ -74,10 +74,16 @@ public class ClansTransferManager extends MiniDbClientPlugin * Gets a list of all loaded servers * @return A list of all loaded servers */ - public List getServers() + public List getServers(boolean onlineOnly) { List servers = Lists.newArrayList(); - servers.addAll(_servers.values()); + for (ServerInfo info : _servers.values()) + { + if (!info.MOTD.equalsIgnoreCase("Restarting soon") || !onlineOnly) + { + servers.add(info); + } + } return servers; } @@ -112,6 +118,7 @@ public class ClansTransferManager extends MiniDbClientPlugin info.MOTD = server.getMotd(); info.CurrentPlayers = server.getPlayerCount(); info.MaxPlayers = server.getMaxPlayerCount(); + info.Hardcore = server.getMotd().contains("Hardcore"); _servers.put(server, info); } } diff --git a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ServerInfo.java b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ServerInfo.java index e51c34ff6..1dc448609 100644 --- a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ServerInfo.java +++ b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ServerInfo.java @@ -9,6 +9,7 @@ public class ServerInfo public String MOTD; public int CurrentPlayers = 0; public int MaxPlayers = 0; + public boolean Hardcore = false; /** * Checks how many slots are left on this server diff --git a/Plugins/Mineplex.Minecraft.Game.Core/src/mineplex/minecraft/game/core/damage/CustomDamageEvent.java b/Plugins/Mineplex.Minecraft.Game.Core/src/mineplex/minecraft/game/core/damage/CustomDamageEvent.java index 6b4b9fde8..2ebe4cac2 100644 --- a/Plugins/Mineplex.Minecraft.Game.Core/src/mineplex/minecraft/game/core/damage/CustomDamageEvent.java +++ b/Plugins/Mineplex.Minecraft.Game.Core/src/mineplex/minecraft/game/core/damage/CustomDamageEvent.java @@ -157,9 +157,9 @@ public class CustomDamageEvent extends Event implements Cancellable return null; } - public Player GetDamagerPlayer(boolean ranged) + public Player GetDamagerPlayer(boolean passthroughRanged) { - if (ranged) + if (passthroughRanged) return _damagerPlayer; else if (_projectile == null) diff --git a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/database/RepositoryBase.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/database/RepositoryBase.java index f5066fea9..996b5ed40 100644 --- a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/database/RepositoryBase.java +++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/database/RepositoryBase.java @@ -87,7 +87,7 @@ public abstract class RepositoryBase protected int executeUpdate(String query, Runnable onSQLError, Column...columns) { - return executeInsert(query, null, columns); + return executeInsert(query, null, onSQLError, columns); } /** diff --git a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/customerSupport/CustomerSupport.java b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/customerSupport/CustomerSupport.java index d9e82ba75..b51a9c8e1 100644 --- a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/customerSupport/CustomerSupport.java +++ b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/customerSupport/CustomerSupport.java @@ -139,7 +139,7 @@ public class CustomerSupport extends MiniPlugin implements ResultSetCallable int ancientChestsReceived = 0; int mythicalChestsReceived = 0; int winterChestsReceived = 0; - int illuminatedChestsReceived = 0; + int illuminatedChestsReceived = 0; int valentinesGiftsReceived = 0; int boostersReceived = 0; int freedomChestsReceived = 0; @@ -155,6 +155,8 @@ public class CustomerSupport extends MiniPlugin implements ResultSetCallable int loveChestsReceived = 0; int stPatricksChestReceived = 0; int springChestsReceived = 0; + int clansDyeBoxesReceived = 0; + int clansBuilderBoxesReceived = 0; for (CoinTransactionToken transaction : donor.getCoinTransactions()) { @@ -211,17 +213,17 @@ public class CustomerSupport extends MiniPlugin implements ResultSetCallable } } - if (transaction.SalesPackageName.startsWith("Illuminated Chest")) - { - if (transaction.Coins == 0 && transaction.Gems == 0) - { - if (transaction.SalesPackageName.split(" ").length == 3) - illuminatedChestsReceived += Integer.parseInt(transaction.SalesPackageName.split(" ")[2]); - else if (transaction.SalesPackageName.split(" ").length == 2) - illuminatedChestsReceived += 1; - } + if (transaction.SalesPackageName.startsWith("Illuminated Chest")) + { + if (transaction.Coins == 0 && transaction.Gems == 0) + { + if (transaction.SalesPackageName.split(" ").length == 3) + illuminatedChestsReceived += Integer.parseInt(transaction.SalesPackageName.split(" ")[2]); + else if (transaction.SalesPackageName.split(" ").length == 2) + illuminatedChestsReceived += 1; + } - } + } if (transaction.SalesPackageName.startsWith("Freedom Treasure")) { if (transaction.Coins == 0 && transaction.Gems == 0) @@ -369,6 +371,26 @@ public class CustomerSupport extends MiniPlugin implements ResultSetCallable runeAmplifier60 += 1; } } + if (transaction.SalesPackageName.startsWith("Clans Dye Box")) + { + if (transaction.Coins == 0 && transaction.Gems == 0) + { + if (transaction.SalesPackageName.split(" ").length == 4) + clansDyeBoxesReceived += Integer.parseInt(transaction.SalesPackageName.split(" ")[3]); + else if (transaction.SalesPackageName.split(" ").length == 3) + clansDyeBoxesReceived += 1; + } + } + if (transaction.SalesPackageName.startsWith("Clans Builder Box")) + { + if (transaction.Coins == 0 && transaction.Gems == 0) + { + if (transaction.SalesPackageName.split(" ").length == 4) + clansBuilderBoxesReceived += Integer.parseInt(transaction.SalesPackageName.split(" ")[3]); + else if (transaction.SalesPackageName.split(" ").length == 3) + clansBuilderBoxesReceived += 1; + } + } } StatsManager statsManager = Managers.get(StatsManager.class); @@ -392,10 +414,10 @@ public class CustomerSupport extends MiniPlugin implements ResultSetCallable shards.append(" "); shards.append(C.cBlue + "Shards: " + C.cYellow + donor.getBalance(GlobalCurrency.TREASURE_SHARD)); caller.sendMessage(shards.toString()); - // Strutt20 asked me to remove some stuff from the menu + // Strutt20 asked me to remove some stuff from the menu caller.sendMessage(C.cBlue + "Old Chests Received: " + C.cYellow + oldChestsReceived + " " + C.cBlue + "Ancient Chests Received: " + C.cYellow + ancientChestsReceived); caller.sendMessage(C.cBlue + "Mythical Chests Received: " + C.cYellow + mythicalChestsReceived + " " + C.cBlue + "Illuminated Chests Received: " + C.cYellow + illuminatedChestsReceived); - caller.sendMessage(C.cBlue + "Omega Chests Received: " + C.cYellow + omegaChestsReceived); + caller.sendMessage(C.cBlue + "Omega Chests Received: " + C.cYellow + omegaChestsReceived); caller.sendMessage(C.cBlue + "Haunted Chests Received: " + C.cYellow + hauntedChestsReceived + " " + C.cBlue + "Haunted Chests Opened: " + C.cYellow + hauntedChestsOpened); caller.sendMessage(C.cBlue + "Trick or Treat Chests Received: " + C.cYellow + trickOrTreatChestsReceived + " " + C.cBlue + "Thankful Chests Received: " + C.cYellow + thankfulChestsReceived); caller.sendMessage(C.cBlue + "Gingerbread Chests Received: " + C.cYellow + gingerbreadChestsReceived + " " + C.cBlue + "Minestrike Chests Received: " + C.cYellow + minestrikeChestsReceived); @@ -404,6 +426,7 @@ public class CustomerSupport extends MiniPlugin implements ResultSetCallable caller.sendMessage(C.cBlue + "Spring Chests Received: " + C.cYellow + springChestsReceived); caller.sendMessage(C.cBlue + "Game Amplifiers Received: " + C.cYellow + boostersReceived); caller.sendMessage(C.cBlue + "Rune Amplifiers (20 min/60 min) Received: " + C.cYellow + runeAmplifier20 + "/" + runeAmplifier60); + caller.sendMessage(C.cBlue + "Clans Dye Boxes Received: " + C.cYellow + clansDyeBoxesReceived + " " + C.cBlue + "Clans Builder Boxes Received: " + C.cYellow + clansBuilderBoxesReceieved); caller.sendMessage(C.cBlue + "Clan Banner Usage: " + getLockedFreedomStr(client.getUniqueId(), "Clan Banner Usage") + " " + C.cBlue + "Clan Banner Editor: " + getLockedFreedomStr(client.getUniqueId(), "Clan Banner Editor")); YearMonth yearMonth = YearMonth.now(); caller.sendMessage(C.cBlue + "Power Play Subscription (" + yearMonth.getMonth().getDisplayName(TextStyle.FULL, Locale.US) + ") " + (powerPlayData.isSubscribed() ? C.cGreen + "Active" : C.cRed + "Inactive")); diff --git a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/SalesPackageManager.java b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/SalesPackageManager.java index 2f8d3f15f..509ea9286 100644 --- a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/SalesPackageManager.java +++ b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/SalesPackageManager.java @@ -38,6 +38,7 @@ import mineplex.staffServer.salespackage.salespackages.OmegaChest; import mineplex.staffServer.salespackage.salespackages.Pet; import mineplex.staffServer.salespackage.salespackages.PowerPlayClub; import mineplex.staffServer.salespackage.salespackages.RuneAmplifier; +import mineplex.staffServer.salespackage.salespackages.ClansBox; import mineplex.staffServer.salespackage.salespackages.SalesPackageBase; import mineplex.staffServer.salespackage.salespackages.SpringChest; import mineplex.staffServer.salespackage.salespackages.StPatricksChest; @@ -80,13 +81,13 @@ public class SalesPackageManager extends MiniPlugin AddSalesPackage(new LifetimeLegend(this)); AddSalesPackage(new LifetimeTitan(this)); AddSalesPackage(new LifetimeEternal(this)); - //AddSalesPackage(new GemHunter(this, 4)); + //AddSalesPackage(new GemHunter(this, 4)); //AddSalesPackage(new GemHunter(this, 8)); AddSalesPackage(new ApplyKits(this)); AddSalesPackage(new OldChest(this)); AddSalesPackage(new AncientChest(this)); AddSalesPackage(new MythicalChest(this)); - AddSalesPackage(new IlluminatedChest(this)); + AddSalesPackage(new IlluminatedChest(this)); AddSalesPackage(new FreedomChest(this)); AddSalesPackage(new GingerbreadChest(this)); //AddSalesPackage(new ValentinesGift(this)); @@ -96,6 +97,8 @@ public class SalesPackageManager extends MiniPlugin AddSalesPackage(new ClanBannerEditor(this)); AddSalesPackage(new RuneAmplifier(this, 20)); AddSalesPackage(new RuneAmplifier(this, 60)); + AddSalesPackage(new ClansBox(this, "Dye")); + AddSalesPackage(new ClansBox(this, "Builder")); AddSalesPackage(new PowerPlayClub(this, false)); AddSalesPackage(new PowerPlayClub(this, true)); AddSalesPackage(new OmegaChest(this)); @@ -180,7 +183,7 @@ public class SalesPackageManager extends MiniPlugin { chestBuilder = chestBuilder.extra("[").color("gray").extra(salesPackage.getName()).color("green").click("run_command", "/display " + playerName + " " + salesPackage.getName()).extra("] ").color("gray"); } - else if (salesPackage instanceof ClanBannerEditor || salesPackage instanceof ClanBannerUsage || salesPackage instanceof RuneAmplifier) + else if (salesPackage instanceof ClanBannerEditor || salesPackage instanceof ClanBannerUsage || salesPackage instanceof RuneAmplifier || salesPackage instanceof ClansBox) { clanBuilder = clanBuilder.extra("[").color("gray").extra(salesPackage.getName()).color("green").click("run_command", "/display " + playerName + " " + salesPackage.getName()).extra("] ").color("gray"); } diff --git a/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/salespackages/ClansBox.java b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/salespackages/ClansBox.java new file mode 100644 index 000000000..04f5ab145 --- /dev/null +++ b/Plugins/Mineplex.StaffServer/src/mineplex/staffServer/salespackage/salespackages/ClansBox.java @@ -0,0 +1,22 @@ +package mineplex.staffServer.salespackage.salespackages; + +import mineplex.staffServer.salespackage.SalesPackageManager; +import org.bukkit.entity.Player; + +public class ClansBox extends SalesPackageBase +{ + private String _boxType; + + public ClansBox(SalesPackageManager manager, String boxType) + { + super(manager, "1 Clans " + boxType + " Box"); + _boxType = boxType; + } + + public void displayToAgent(Player agent, String playerName) + { + addButton(agent, "/sales item " + playerName + " 1 Item Clans " + _boxType + " Box", "Give 1 Clans " + _boxType + " Box."); + agent.sendMessage(" "); + addBackButton(agent, playerName); + } +}