diff --git a/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java b/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java index cc5ba27d4..63061ae7f 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/game/GameDisplay.java @@ -49,6 +49,7 @@ public enum GameDisplay Smash("Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.CLASSICS, 34, true), SmashDomination("Super Smash Mobs Domination", "Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.EXTRA, 36, false), SmashTeams("Super Smash Mobs Teams", "Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.TEAM_VARIANT, 35, false), + SmashTraining("Super Smash Mobs Training", "Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.EXTRA, 34, false), Snake("Snake", Material.WOOL, (byte)0, GameCategory.ARCADE, 37, true), SneakyAssassins("Sneaky Assassins", Material.INK_SACK, (byte)0, GameCategory.ARCADE, 38, true), SnowFight("Snow Fight", Material.SNOW_BALL, (byte)0, GameCategory.EXTRA, 39, false), diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java index 66bef53c0..fdcddb842 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/GameType.java @@ -1,5 +1,6 @@ package nautilus.game.arcade; +import nautilus.game.arcade.game.games.smash.SuperSmashTraining; import org.bukkit.Material; import mineplex.core.common.MinecraftVersion; @@ -182,6 +183,7 @@ public enum GameType Smash(SoloSuperSmash.class, GameDisplay.Smash), SmashDomination(SuperSmashDominate.class, GameDisplay.SmashDomination), SmashTeams(TeamSuperSmash.class, GameDisplay.SmashTeams, new GameType[]{GameType.Smash}, false), + SmashTraining(SuperSmashTraining.class, GameDisplay.SmashTraining), Snake(Snake.class, GameDisplay.Snake), SneakyAssassins(SneakyAssassins.class, GameDisplay.SneakyAssassins), SnowFight(SnowFight.class, GameDisplay.SnowFight), diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/smash/SuperSmash.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/smash/SuperSmash.java index b75aff778..3bcdcb304 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/smash/SuperSmash.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/smash/SuperSmash.java @@ -582,6 +582,12 @@ public abstract class SuperSmash extends Game return; } + displayKitInto(player); + event.setCancelled(true); + } + + protected void displayKitInto(Player player) + { for (int i = player.getItemInHand().getItemMeta().getLore().size(); i <= 7; i++) { UtilPlayer.message(player, ""); @@ -600,8 +606,6 @@ public abstract class SuperSmash extends Game UtilPlayer.message(player, ArcadeFormat.Line); player.playSound(player.getLocation(), Sound.NOTE_PLING, 1f, 2f); - - event.setCancelled(true); } @Override diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/smash/SuperSmashTraining.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/smash/SuperSmashTraining.java new file mode 100644 index 000000000..d4e37452e --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/smash/SuperSmashTraining.java @@ -0,0 +1,193 @@ +package nautilus.game.arcade.game.games.smash; + +import mineplex.core.common.util.C; +import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilTime; +import mineplex.core.hologram.Hologram; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import nautilus.game.arcade.ArcadeManager; +import nautilus.game.arcade.GameType; +import nautilus.game.arcade.events.GameStateChangeEvent; +import nautilus.game.arcade.game.GameTeam; +import nautilus.game.arcade.game.modules.training.TrainingBot; +import nautilus.game.arcade.game.modules.training.TrainingGameModule; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.entity.PlayerDeathEvent; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; + +public class SuperSmashTraining extends SuperSmash +{ + + private static final long GAME_TIME = TimeUnit.HOURS.toMillis(3); + private static final long GAME_WARN_TIME = GAME_TIME - TimeUnit.MINUTES.toMillis(5); + private static final String[] INFO_HOLOGRAM = { + C.cYellow + "Select a " + C.cGreen + "Kit", + C.cYellow + "Jump off the island to use your abilities", + C.cYellow + "You can then " + C.cGreen + "PVP" + C.cYellow + " other players", + C.cYellow + "Click the " + C.cGreen + "Bed" + C.cYellow + " to return to this island" + }; + + private Location _borderA; + private Location _borderB; + + private boolean _announceEnd; + + public SuperSmashTraining(ArcadeManager manager) + { + super(manager, GameType.SmashTraining, new String[]{ + "Super Smash Mobs Training Ground" + }); + + DamageTeamSelf = true; + DeathSpectateSecs = 0; + PrepareTime = 500; + GiveClock = false; + + Function playerFunction = player -> + { + return !UtilAlg.inBoundingBox(player.getLocation(), _borderA, _borderB); + }; + + new TrainingGameModule() + .setSkillFunction(playerFunction) + .setDamageFunction(playerFunction) + .addBot(TrainingBot.class) + .register(this); + } + + @Override + public void ParseData() + { + List locations = WorldData.GetDataLocs("BROWN"); + + _borderA = locations.get(0); + _borderB = locations.get(1); + } + + @EventHandler + public void customTeamGeneration(GameStateChangeEvent event) + { + if (event.GetState() != GameState.Recruit) + { + return; + } + + GameTeam players = GetTeamList().get(0); + players.SetColor(ChatColor.YELLOW); + players.SetName("Players"); + players.setDisplayName(C.cYellowB + "Players"); + } + + @EventHandler + public void live(GameStateChangeEvent event) + { + if (event.GetState() != GameState.Live) + { + return; + } + + List locations = WorldData.GetDataLocs("BLUE"); + + for (Location location : locations) + { + spawnInfoHologram(location); + } + } + + @Override + @EventHandler + public void ScoreboardUpdate(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + { + return; + } + + Scoreboard.writeNewLine(); + + List alive = GetPlayers(true); + + Scoreboard.write(C.cYellowB + "Players"); + + if (alive.size() > 9) + { + Scoreboard.write(alive.size() + " Alive"); + } + else + { + for (Player player : alive) + { + Scoreboard.write(player.getName()); + } + } + + Scoreboard.writeNewLine(); + + Scoreboard.write(C.cYellowB + "Time"); + Scoreboard.write(UtilTime.MakeStr(System.currentTimeMillis() - GetStateTime())); + + Scoreboard.writeNewLine(); + + Scoreboard.draw(); + } + + @Override + public List getWinners() + { + return null; + } + + @Override + public List getLosers() + { + return null; + } + + @Override + @EventHandler + public void playerDeath(PlayerDeathEvent event) + { + } + + @Override + public void EndCheck() + { + if (!IsLive()) + { + return; + } + + if (UtilTime.elapsed(GetStateTime(), GAME_TIME)) + { + SetState(GameState.Dead); + Announce(C.cRedB + "Game Over! Resetting the map, you will be able to play again."); + } + else if (UtilTime.elapsed(GetStateTime(), GAME_WARN_TIME) && !_announceEnd) + { + _announceEnd = true; + Announce(C.cRedB + "The Game Will End In 5 Minutes."); + } + } + + @Override + public long getNewSmashTime() + { + return (long) (System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(2) + TimeUnit.MINUTES.toMillis(2) * Math.random()); + } + + private void spawnInfoHologram(Location location) + { + CreatureAllowOverride = true; + + new Hologram(getArcadeManager().getHologramManager(), location, true, INFO_HOLOGRAM).start(); + + CreatureAllowOverride = false; + } +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/training/TrainingBot.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/training/TrainingBot.java new file mode 100644 index 000000000..c311b5d35 --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/training/TrainingBot.java @@ -0,0 +1,138 @@ +package nautilus.game.arcade.game.modules.training; + +import mineplex.core.common.skin.SkinData; +import mineplex.core.common.util.*; +import mineplex.core.disguise.disguises.DisguisePlayer; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.combat.DeathMessageType; +import mineplex.minecraft.game.core.combat.event.CombatDeathEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import org.bukkit.Location; +import org.bukkit.entity.ArmorStand; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import java.text.DecimalFormat; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +public class TrainingBot implements Listener +{ + + private static final SkinData[] SKIN_DATAS = + { + SkinData.SNOWMAN, + SkinData.MOOSHROOM, + SkinData.WITCH + }; + private static final int DAMAGE_HOLOGRAMS_LIFE = 40; + private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.0"); + private static final long RESPAWN_TIME = TimeUnit.SECONDS.toMillis(5); + + private TrainingGameModule _module; + private Location _location; + private int _number; + + protected ArmorStand _stand; + private long _lastDeath; + + private final Set _damageHolograms; + + public TrainingBot(TrainingGameModule module, Location location, int number) + { + _module = module; + _location = location; + _number = number; + _lastDeath = System.currentTimeMillis(); + _damageHolograms = new HashSet<>(); + + UtilServer.RegisterEvents(this); + } + + public void cleanup() + { + UtilServer.Unregister(this); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void botDamage(CustomDamageEvent event) + { + if (_stand == null || !_stand.equals(event.GetDamageeEntity())) + { + return; + } + + spawnDamageHologram(event.GetDamage()); + } + + @EventHandler + public void botDeath(CombatDeathEvent event) + { + if (_stand == null || !_stand.equals(event.GetEvent().getEntity())) + { + return; + } + + event.SetBroadcastType(DeathMessageType.Detailed); + _stand.remove(); + } + + private void spawnDamageHologram(double damage) + { + String damageSting = DECIMAL_FORMAT.format(damage); + Location location = UtilAlg.getRandomLocation(_stand.getLocation().add(0, 1, 0), 1, 0, 1); + ArmorStand stand = location.getWorld().spawn(location, ArmorStand.class); + + stand.setVisible(false); + stand.setGravity(false); + stand.setCustomName(C.cRedB + "-" + damageSting); + stand.setCustomNameVisible(true); + + _damageHolograms.add(stand); + } + + @EventHandler + public void cleanupDamageHolograms(UpdateEvent event) + { + if (event.getType() != UpdateType.FASTEST) + { + return; + } + + Iterator iterator = _damageHolograms.iterator(); + + while (iterator.hasNext()) + { + ArmorStand stand = iterator.next(); + + if (stand.getTicksLived() > DAMAGE_HOLOGRAMS_LIFE) + { + stand.remove(); + iterator.remove(); + continue; + } + + stand.teleport(stand.getLocation().add(0, 0.25, 0)); + } + } + + @EventHandler + public void respawn(UpdateEvent event) + { + if (event.getType() != UpdateType.SEC || !UtilTime.elapsed(_lastDeath, RESPAWN_TIME)) + { + return; + } + + _lastDeath = System.currentTimeMillis(); + _stand = _location.getWorld().spawn(_location, ArmorStand.class); + + DisguisePlayer disguise = new DisguisePlayer(_stand, C.cYellowB + "Bot #" + _number, SKIN_DATAS[UtilMath.r(SKIN_DATAS.length)]); + disguise.setSendSkinDataToSelf(false); + _module.getGame().getArcadeManager().GetDisguise().disguise(disguise); + } +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/training/TrainingGameModule.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/training/TrainingGameModule.java new file mode 100644 index 000000000..e3c19bf3f --- /dev/null +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/modules/training/TrainingGameModule.java @@ -0,0 +1,398 @@ +package nautilus.game.arcade.game.modules.training; + +import mineplex.core.command.CommandCenter; +import mineplex.core.common.util.*; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.recharge.Recharge; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.minecraft.game.core.damage.CustomDamageEvent; +import nautilus.game.arcade.events.GameStateChangeEvent; +import nautilus.game.arcade.game.Game; +import nautilus.game.arcade.game.GameTeam; +import nautilus.game.arcade.game.modules.Module; +import nautilus.game.arcade.kit.Kit; +import nautilus.game.arcade.kit.ProgressingKit; +import nautilus.game.arcade.managers.LobbyEnt; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.entity.EntityCombustEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.*; +import java.util.function.Function; + +public class TrainingGameModule extends Module +{ + + private static final String RETURN_TO_SPAWN_RECHARGE = "Return To Select A Kit"; + private static final int RETURN_TO_SPAWN_COOLDOWN = 8000; + private static final ItemStack RETURN_TO_SPAWN_ITEM = new ItemBuilder(Material.BED) + .setTitle(C.cGreenB + RETURN_TO_SPAWN_RECHARGE) + .addLore("Click to return to the spawn island", "where you can select a new kit.") + .build(); + + private final Set _kits; + private Function _teamFunction; + private Function _skillFunction; + private Function _damageFunction; + private final Set> _botClasses; + private final Set _bots; + + public TrainingGameModule() + { + _kits = new HashSet<>(); + _botClasses = new HashSet<>(); + _bots = new HashSet<>(); + } + + @EventHandler + public void live(GameStateChangeEvent event) + { + if (event.GetState() != Game.GameState.Live) + { + return; + } + + List locations = getGame().WorldData.GetDataLocs("PURPLE"); + int i = 0; + getGame().CreatureAllowOverride = true; + + for (Kit kit : getGame().GetKits()) + { + Location location = locations.get(i++); + Entity entity = kit.SpawnEntity(location); + + _kits.add(new LobbyEnt(entity, location, kit)); + } + + Location average = UtilAlg.getAverageLocation(locations); + + for (LobbyEnt entity : _kits) + { + UtilEnt.CreatureLook(entity.GetEnt(), average); + } + + Map> map = getGame().WorldData.GetAllCustomLocs(); + int j = 0; + + for (Map.Entry> entry : map.entrySet()) + { + String s = entry.getKey(); + + if (s.startsWith("BOT")) + { + String[] split = s.split(" "); + + if (split.length < 2) + { + continue; + } + + String clazzName = split[1]; + + for (Class clazz : _botClasses) + { + if (clazzName.equals(clazz.getSimpleName())) + { + for (Location location : entry.getValue()) + { + spawnBot(clazz, location, ++j); + } + } + } + } + } + + getGame().CreatureAllowOverride = false; + } + + @Override + public void cleanup() + { + for (LobbyEnt lobbyEnt : _kits) + { + lobbyEnt.GetEnt().remove(); + } + + for (TrainingBot bot : _bots) + { + bot.cleanup(); + } + + _kits.clear(); + } + + @EventHandler + public void kitMove(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + { + return; + } + + for (LobbyEnt ent : _kits) + { + Location location = ent.GetLocation(); + + ((CraftEntity) ent.GetEnt()).getHandle().setPosition(location.getX(), location.getY(), location.getZ()); + } + } + + @EventHandler + public void kitInteract(PlayerInteractEntityEvent event) + { + Player player = event.getPlayer(); + Entity entity = event.getRightClicked(); + LobbyEnt lobbyEnt = getFromEntity(entity); + + if (UtilPlayer.isSpectator(player)) + { + return; + } + + if (lobbyEnt != null) + { + getGame().getArcadeManager().Clear(player); + getGame().SetKit(event.getPlayer(), lobbyEnt.GetKit(), true); + event.setCancelled(true); + } + } + + @EventHandler + public void kitCombust(EntityCombustEvent event) + { + if (getFromEntity(event.getEntity()) != null) + { + event.setCancelled(true); + } + } + + @EventHandler + public void kitDamage(CustomDamageEvent event) + { + if (getFromEntity(event.GetDamageeEntity()) != null) + { + event.SetCancelled("Kit NPC"); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void playerLogin(PlayerLoginEvent event) + { + Player player = event.getPlayer(); + Game game = getGame(); + GameTeam team = _teamFunction == null ? game.GetTeamList().get(0) : _teamFunction.apply(player); + + team.AddPlayer(player, true); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void playerJoin(PlayerJoinEvent event) + { + Player player = event.getPlayer(); + + if (UtilPlayer.isSpectator(player)) + { + return; + } + + GameTeam team = getGame().GetTeam(player); + + team.SpawnTeleport(player); + + getGame().getArcadeManager().runSyncLater(() -> + { + Kit kit = null; + + for (Kit otherKit : getGame().GetKits()) + { + if (otherKit instanceof ProgressingKit) + { + ProgressingKit progressingKit = (ProgressingKit) otherKit; + + if (progressingKit.isDefault(player.getUniqueId())) + { + kit = progressingKit; + break; + } + } + } + + if (kit == null) + { + kit = getGame().GetKits()[0]; + } + + getGame().SetKit(player, kit, true); + }, 1); + } + + + @EventHandler(priority = EventPriority.LOWEST) + public void playerInteract(PlayerInteractEvent event) + { + if (_skillFunction == null) + { + return; + } + + Player player = event.getPlayer(); + + if (!_skillFunction.apply(player)) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void playerInteract(EntityDamageEvent event) + { + if (_skillFunction == null || !(event.getEntity() instanceof Player)) + { + return; + } + + Player player = (Player) event.getEntity(); + + if (!_skillFunction.apply(player)) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void entityDamage(CustomDamageEvent event) + { + if (!(event.GetDamageeEntity() instanceof Player)) + { + return; + } + + Player player = event.GetDamageePlayer(); + + if (!event.isCancelled()) + { + Recharge.Instance.useForce(player, RETURN_TO_SPAWN_RECHARGE, RETURN_TO_SPAWN_COOLDOWN); + } + + if (_damageFunction == null) + { + return; + } + + if (!_damageFunction.apply(player)) + { + event.SetCancelled("Training Area"); + } + } + + @EventHandler + public void giveReturnToSpawn(UpdateEvent event) + { + if (event.getType() != UpdateType.FAST) + { + return; + } + + for (Player player : getGame().GetPlayers(true)) + { + if (player.getInventory().contains(RETURN_TO_SPAWN_ITEM)) + { + continue; + } + + player.getInventory().setItem(8, RETURN_TO_SPAWN_ITEM); + } + } + + @EventHandler + public void interactReturnToSpawn(PlayerInteractEvent event) + { + Player player = event.getPlayer(); + ItemStack itemStack = player.getItemInHand(); + + if (itemStack == null || !itemStack.isSimilar(RETURN_TO_SPAWN_ITEM)) + { + return; + } + + if (event.isCancelled()) + { + player.sendMessage(F.main("Game", "You are already at the " + F.greenElem("Kit Selection Island") + ".")); + return; + } + + if (Recharge.Instance.usable(player, RETURN_TO_SPAWN_RECHARGE)) + { + getGame().RespawnPlayer(player); + } + else + { + player.sendMessage(F.main("Game", "You can't return to the " + F.greenElem("Kit Selection Island") + " if you are in " + F.greenElem("PVP") + ".")); + } + } + + private T spawnBot(Class clazz, Location location, int number) + { + try + { + T bot = clazz.getConstructor(TrainingGameModule.class, Location.class, int.class).newInstance(this, location, number); + _bots.add(bot); + return bot; + } + catch (Exception e) + { + e.printStackTrace(); + } + + return null; + } + + public TrainingGameModule setTeamFunction(Function function) + { + _teamFunction = function; + return this; + } + + public TrainingGameModule setSkillFunction(Function function) + { + _skillFunction = function; + return this; + } + + public TrainingGameModule setDamageFunction(Function function) + { + _damageFunction = function; + return this; + } + + public TrainingGameModule addBot(Class clazz) + { + _botClasses.add(clazz); + return this; + } + + private LobbyEnt getFromEntity(Entity entity) + { + for (LobbyEnt lobbyEnt : _kits) + { + if (lobbyEnt.GetEnt().equals(entity)) + { + return lobbyEnt; + } + } + + return null; + } +} diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkRopedArrow.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkRopedArrow.java index 3d0d4b759..1f022bd35 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkRopedArrow.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkRopedArrow.java @@ -49,6 +49,11 @@ public class PerkRopedArrow extends SmashPerk @EventHandler public void Fire(PlayerInteractEvent event) { + if (event.isCancelled()) + { + return; + } + if (event.getAction() != Action.LEFT_CLICK_AIR && event.getAction() != Action.LEFT_CLICK_BLOCK) return;