From 8a389a13a244be55faf688a6ce5bab07b7bc3e1e Mon Sep 17 00:00:00 2001 From: Spencer Date: Sat, 6 Jan 2018 20:30:51 -0500 Subject: [PATCH] Add an overcomplicated system to prevent Necromancer Skeletons from spawning in blocks --- .../games/survivalgames/SurvivalGames.java | 35 ++++++--- .../game/arcade/kit/perks/PerkSkeletons.java | 71 ++++++++++++++++++- 2 files changed, 95 insertions(+), 11 deletions(-) diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/survivalgames/SurvivalGames.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/survivalgames/SurvivalGames.java index 1e5fac5bb..0a323ec8a 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/survivalgames/SurvivalGames.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/games/survivalgames/SurvivalGames.java @@ -306,6 +306,30 @@ public abstract class SurvivalGames extends Game } } + private double getCurrentBorder() + { + // The distance between the old border and the new + double distanceMovedSince = _currentBorder - _previousBorder; + + // Multiply that distance depending on how long its been since it moved. + long timeSinceMoved = System.currentTimeMillis() - _borderStartedMoving; + double percentageBorderMoved = Math.min(timeSinceMoved, 1000D) / 1000D; + + distanceMovedSince *= percentageBorderMoved; + + return (_previousBorder - 0.3D) + distanceMovedSince; + } + + public boolean isOutsideBorder(Location loc) + { + double border = getCurrentBorder(); + + return (loc.getX() > _spawn.getX() + border + || loc.getX() < _spawn.getX() - border + || loc.getZ() > _spawn.getZ() + border + || loc.getZ() < _spawn.getZ() - border); + } + @EventHandler public void BlockBreak(BlockBreakEvent event) { @@ -1186,16 +1210,7 @@ public abstract class SurvivalGames extends Game return; } - // The distance between the old border and the new - double distanceMovedSince = _currentBorder - _previousBorder; - - // Multiply that distance depending on how long its been since it moved. - long timeSinceMoved = System.currentTimeMillis() - _borderStartedMoving; - double percentageBorderMoved = Math.min(timeSinceMoved, 1000D) / 1000D; - - distanceMovedSince *= percentageBorderMoved; - - double border = (_previousBorder - 0.3D) + distanceMovedSince; + double border = getCurrentBorder(); // 24 @ 100+ reduced to 0 at 32- double borderAttackDist = Math.max(8, diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkSkeletons.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkSkeletons.java index 410793a3f..306b84cd4 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkSkeletons.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/kit/perks/PerkSkeletons.java @@ -1,15 +1,19 @@ package nautilus.game.arcade.kit.perks; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.bukkit.Bukkit; 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.CraftCreature; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftSkeleton; import org.bukkit.entity.Entity; @@ -24,6 +28,7 @@ import org.bukkit.event.player.PlayerEvent; import mineplex.core.common.util.C; 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; @@ -33,6 +38,7 @@ import mineplex.minecraft.game.core.combat.event.CombatDeathEvent; import mineplex.minecraft.game.core.damage.CustomDamageEvent; import nautilus.game.arcade.events.PlayerStateChangeEvent; import nautilus.game.arcade.game.GameTeam.PlayerState; +import nautilus.game.arcade.game.games.survivalgames.SurvivalGames; import nautilus.game.arcade.kit.Perk; import net.minecraft.server.v1_8_R3.EntityCreature; import net.minecraft.server.v1_8_R3.NavigationAbstract; @@ -73,6 +79,7 @@ public class PerkSkeletons extends Perk private boolean _name; private int _maxDist = 8; + private static final int MAX_SPAWN_RADIUS = 5; public PerkSkeletons(boolean name) { @@ -83,6 +90,68 @@ public class PerkSkeletons extends Perk _name = name; } + /** + * Find whether a given location is a valid + * Skeleton spawnpoint. + * + * A location is valid if it meets the following + * criteria: + * - The block at and 1 y-value above are both air + * - It is within the border on X, Y, and Z + * @param location - The location at which you want to spawn a skeleton. + * @return Whether the location is valid or not + */ + private boolean isValidSpawn(Location location) + { + return location.getBlock().getType() == Material.AIR + && location.clone().add(0, 1, 0).getBlock().getType() == Material.AIR + && !((SurvivalGames) Manager.GetGame()).isOutsideBorder(location); + + } + + private double vectorDistance(Location a, Location b) + { + return a.toVector().distance(b.toVector()); + } + + private Location getMinionLocation(Location deathLocation) + { + if (isValidSpawn(deathLocation)) + { + return deathLocation; + } + + /* + Get all blocks within the max spawn radius, + where each block is at the same Y-level as + the death location, + filter locations to those which are valid spawns, + then sort them in ascending order of distance + to the original death location. + */ + List nearbyBlocks = UtilBlock.getBlocksInRadius(deathLocation, MAX_SPAWN_RADIUS, deathLocation.getBlockY()) + .stream() + .filter(b -> isValidSpawn(b.getLocation())) + .sorted(Comparator.comparingDouble(a -> vectorDistance(a.getLocation(), deathLocation))) + .collect(Collectors.toCollection(LinkedList::new)); + + if (nearbyBlocks.size() > 0) + { + return nearbyBlocks.get(0).getLocation(); + } + else + { + Location spawnLocation = deathLocation.clone(); + + while (!isValidSpawn(spawnLocation) && spawnLocation.getY() < 256) + { + spawnLocation = spawnLocation.add(0, 1, 0); + } + + return spawnLocation; + } + } + @EventHandler public void MinionSpawn(CombatDeathEvent event) { @@ -103,7 +172,7 @@ public class PerkSkeletons extends Perk Manager.GetGame().CreatureAllowOverride = true; - Skeleton skel = killed.getWorld().spawn(killed.getLocation(), Skeleton.class); + Skeleton skel = killed.getWorld().spawn(getMinionLocation(killed.getLocation()), Skeleton.class); Manager.GetGame().CreatureAllowOverride = false;