package com.github.jamesnorris.ablockalypse.utility; import java.util.List; import java.util.Random; import org.bukkit.Location; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import com.github.jamesnorris.ablockalypse.aspect.Barrier; import com.github.jamesnorris.ablockalypse.aspect.Game; import com.github.jamesnorris.ablockalypse.aspect.Hellhound; import com.github.jamesnorris.ablockalypse.aspect.MobSpawner; import com.github.jamesnorris.ablockalypse.aspect.ZAMob; import com.github.jamesnorris.ablockalypse.aspect.Zombie; import com.github.jamesnorris.ablockalypse.enumerated.Setting; import com.github.jamesnorris.ablockalypse.threading.inherent.MobSpawningTask; import com.github.jamesnorris.mcpath.PathNode; import com.github.jamesnorris.mcpath.Pathfinder; public class SpawnUtility { private static Random random = new Random(); /** * Checks if all of the mobs of a game are spawned in to the game for this round. * This does not check if they are all alive, just if they have spawned. * * @param game The game to check the mobs for * @return Whether or not all mobs have been spawned for this round */ public static boolean allSpawnedIn(Game game) { return game.getMobCountSpawnedInThisRound() >= getCurrentSpawnAmount(game); } /** * Gets the barrier closest to the location. * * @param loc The location to check for * @return The closest barrier */ public static Barrier getClosestBarrier(Game game, Location loc) { double distanceSquared = Double.MAX_VALUE; Barrier lp = null;// low priority Barrier hp = null;// high priority for (Barrier gb : game.getObjectsOfType(Barrier.class)) { Location l = gb.getCenter(); double current = loc.distanceSquared(l); if (current < distanceSquared) { distanceSquared = current; lp = gb; if (pathIsClear(loc, l)) { hp = gb; } } } return hp != null ? hp : lp; } /** * Gets the barrier closest to the player. * * @param p The player to check for * @return The closest barrier */ public static Barrier getClosestBarrier(Game game, Player p) { return getClosestBarrier(game, p.getLocation()); } /** * Gets the closest spawner to the location. * * @param loc The location to check for * @return The closest spawner */ public static MobSpawner getClosestSpawner(Game game, Location loc, boolean active) { double distanceSquared = Double.MAX_VALUE; MobSpawner lp = null;// low priority MobSpawner hp = null;// high priority for (MobSpawner l1 : game.getObjectsOfType(MobSpawner.class)) { Location l = l1.getBukkitLocation(); double current = loc.distanceSquared(l); if (current < distanceSquared && (!active || l1.isActive())) { distanceSquared = current; lp = l1; if (pathIsClear(loc, l)) { hp = l1; } } } return hp != null ? hp : lp; } /** * Gets the closest spawner to the player. * * @param p The player to check for * @return The closest spawner */ public static MobSpawner getClosestSpawner(Game game, Player p, boolean active) { return getClosestSpawner(game, p.getLocation(), active); } /** * Gets the amount of spawns in the current level of the game. * * @return The amount of spawns in the current level */ public static int getCurrentSpawnAmount(Game game) { return getSpawnAmount(game.getLevel(), game.getPlayers().size(), game.isWolfRound()); } /** * Gets the amount of spawns in the given level, with the given amount of players. * * @param level The level you are looking for * @param playeramt The amount of players you are looking for * @param wolfround Whether or not the game is a wolf round or not * @return The amount of spawns in this hypathetical level */ public static int getSpawnAmount(int level, int playeramt, boolean wolfround) { /* The mob spawn amount equation for the entire game */ return (int) ((wolfround ? 1 / 3 : 1) * (Math.sqrt(10 * level) + Math.sqrt(level) * playeramt)); } /** * Checks that the blocks from the one location to the next in the distance are empty. * * @param start The starting location * @param end The ending location * @param distance The distance from the start to end * @return Whether or not all blocks from start to end are empty */ public static boolean pathIsClear(Location start, Location end) { if (!start.getWorld().equals(end.getWorld())) { return false; } List<PathNode> nodes = new Pathfinder(start, end, AblockalypseUtility.getGoals(start.getWorld(), .891D, 1.031D, 2D, 0/* uses player size */)).calculate((Integer) Setting.MAX_PATHFINDER_NODES.getSetting()).getNodes(); return nodes.get(nodes.size() - 1).H <= 2; } /** * Gamespawns a mob at the specified location. * * @param game The game to spawn the mob in * @param loc The location to spawn the mob at * @param exactLocation Whether or not to spawn right next to the target, or to find a closeby location. * @param percentage The percent chance of a hellhound spawning */ public static ZAMob spawn(Game game, Location loc, boolean exactLocation, int percentage) { return spawn(game, exactLocation ? loc : BukkitUtility.getNearbyLocation(loc, 10, 20, 0, 0, 10, 20), percentage); } public static ZAMob spawn(Game game, Location loc, int percentage) { if (random.nextInt(99) + 1 <= percentage) { return new Hellhound(loc.getWorld(), loc.getWorld().spawnEntity(loc, EntityType.WOLF).getUniqueId(), game); } return new Zombie(loc.getWorld(), loc.getWorld().spawnEntity(loc, EntityType.ZOMBIE).getUniqueId(), game); } /** * Spawns a wave of mobs around random living players in this game. * If barriers are present and accessible, spawns the mobs at the barriers. * If mob spawners are set in the game and are accessible, spawns the mobs at a mob spawner. * This will only spawn mobs if the game has a mob count of 0. */ public static void spawnWave(Game game) { spawnWave(game, getCurrentSpawnAmount(game)); } public static void spawnWave(Game game, int amt) { if (game.getRemainingPlayers().size() < 1 && game.getMobCount() <= 0) { game.end(true); return; } if ((Boolean) Setting.DEBUG.getSetting()) { System.out.println("[Ablockalypse] [DEBUG] Amount of zombies in this wave: (" + game.getName() + ") " + amt); } for (int i = 1; i <= amt; i++) { new MobSpawningTask(game, i * 80, true); } } }