diff --git a/changelog.md b/changelog.md index 1b1c8e6..be6d1ff 100644 --- a/changelog.md +++ b/changelog.md @@ -14,6 +14,8 @@ These changes will (most likely) be included in the next version. ### Added - MobArena now properly supports Vault economy providers registered after MobArena has started. This should make it possible to use custom economy providers that aren't built into Vault, such as those created with Denizen. - New wave rewards section `tiers` allows for _non-stacking_ reward tiers for beating certain waves. This allows for configuring reward sets that get "upgraded" as the waves progress, e.g. by granting a full leather armor set for beating wave 15, but beating wave 20 _replaces_ that leather armor set with an iron armor set. +- New per-arena setting `spawnpoint-max-distance` can be used to tweak how close to any player a given spawnpoint must be to be considered valid when spawning monsters. This should help reduce the amount of spawnpoints required, especially for larger arenas. +- New per-arena setting `spawnpoint-min-distance` can be used to tweak how far away from all players a given spawnpoint must be to be considered valid when spawning monsters. This should help prevent monsters from spawning directly on top of players. ### Changed - Recurrent waves can now be randomized. If two or more recurrent waves clash on wave number, frequency, _and_ priority, MobArena will now randomly pick between them. This should make it easier to create more varied and interesting wave setups without having to resort to only massively randomized default waves. diff --git a/src/main/java/com/garbagemule/MobArena/ArenaImpl.java b/src/main/java/com/garbagemule/MobArena/ArenaImpl.java index 1f4801a..ed8eeb1 100644 --- a/src/main/java/com/garbagemule/MobArena/ArenaImpl.java +++ b/src/main/java/com/garbagemule/MobArena/ArenaImpl.java @@ -125,6 +125,8 @@ public class ArenaImpl implements Arena private MASpawnThread spawnThread; private SheepBouncer sheepBouncer; private Map everyWaveMap, afterWaveMap, waveTiersMap; + private double spawnpointMinDistanceSquared; + private double spawnpointMaxDistanceSquared; // Misc private ArenaListener eventListener; @@ -209,6 +211,8 @@ public class ArenaImpl implements Arena this.everyWaveMap = MAUtils.getArenaRewardMap(plugin, section, name, "every"); this.afterWaveMap = MAUtils.getArenaRewardMap(plugin, section, name, "after"); this.waveTiersMap = MAUtils.getArenaRewardMap(plugin, section, name, "tiers"); + this.spawnpointMinDistanceSquared = Math.pow(settings.getDouble("spawnpoint-min-distance", 0), 2); + this.spawnpointMaxDistanceSquared = Math.pow(settings.getDouble("spawnpoint-max-distance", 15), 2); // Misc this.eventListener = new ArenaListener(this, plugin); @@ -382,6 +386,16 @@ public class ArenaImpl implements Arena return spawnThread; } + @Override + public double getSpawnpointMinDistanceSquared() { + return spawnpointMinDistanceSquared; + } + + @Override + public double getSpawnpointMaxDistanceSquared() { + return spawnpointMaxDistanceSquared; + } + @Override public WaveManager getWaveManager() { return waveManager; diff --git a/src/main/java/com/garbagemule/MobArena/MAUtils.java b/src/main/java/com/garbagemule/MobArena/MAUtils.java index 3a0afc9..2d08b99 100644 --- a/src/main/java/com/garbagemule/MobArena/MAUtils.java +++ b/src/main/java/com/garbagemule/MobArena/MAUtils.java @@ -88,6 +88,7 @@ public class MAUtils /* Iterate through the ArrayList, and update current and result every * time a squared distance smaller than current is found. */ List players = new ArrayList<>(arena.getPlayersInArena()); + double max = arena.getSpawnpointMaxDistanceSquared(); for (Player p : players) { if (!arena.getWorld().equals(p.getWorld())) { plugin.getLogger().info("Player '" + p.getName() + "' is not in the right world. Kicking..."); @@ -97,7 +98,7 @@ public class MAUtils } double dist = distanceSquared(plugin, p, e.getLocation()); - if (dist < current && dist < 256D) { + if (dist < current && dist < max) { current = dist; result = p; } diff --git a/src/main/java/com/garbagemule/MobArena/framework/Arena.java b/src/main/java/com/garbagemule/MobArena/framework/Arena.java index e0059b4..d9f556a 100644 --- a/src/main/java/com/garbagemule/MobArena/framework/Arena.java +++ b/src/main/java/com/garbagemule/MobArena/framework/Arena.java @@ -82,6 +82,10 @@ public interface Arena MASpawnThread getSpawnThread(); + double getSpawnpointMinDistanceSquared(); + + double getSpawnpointMaxDistanceSquared(); + WaveManager getWaveManager(); ArenaListener getEventListener(); diff --git a/src/main/java/com/garbagemule/MobArena/region/ArenaRegion.java b/src/main/java/com/garbagemule/MobArena/region/ArenaRegion.java index 1d6cd3b..d68ee1b 100644 --- a/src/main/java/com/garbagemule/MobArena/region/ArenaRegion.java +++ b/src/main/java/com/garbagemule/MobArena/region/ArenaRegion.java @@ -648,9 +648,12 @@ public class ArenaRegion } // Find all the spawnpoints that cover the location + double min = arena.getSpawnpointMinDistanceSquared(); + double max = arena.getSpawnpointMaxDistanceSquared(); Map map = new HashMap<>(); for (Map.Entry entry : spawnpoints.entrySet()) { - if (p.getLocation().distanceSquared(entry.getValue()) < MobArena.MIN_PLAYER_DISTANCE_SQUARED) { + double dist = p.getLocation().distanceSquared(entry.getValue()); + if (min <= dist && dist <= max) { map.put(entry.getKey(), entry.getValue()); } } diff --git a/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java b/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java index 0f13460..53320dc 100644 --- a/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java +++ b/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java @@ -27,14 +27,42 @@ public class WaveUtils spawnpoints = arena.getRegion().getSpawnpointList(); } - // Loop through each one and check if any players are in range. - for (Location l : spawnpoints) { - for (Player p : players) { - if (MAUtils.distanceSquared(plugin, p, l) >= MobArena.MIN_PLAYER_DISTANCE_SQUARED) { - continue; + double min = arena.getSpawnpointMinDistanceSquared(); + double max = arena.getSpawnpointMaxDistanceSquared(); + + if (min > 0) { + // If the min distance is greater than 0, we need to check the + // distance of every player, because one player within the max + // range is no longer enough to make a spawnpoint valid. If even + // a single player is too close, the spawnpoint is invalid. + for (Location l : spawnpoints) { + boolean valid = false; + for (Player p : players) { + double dist = MAUtils.distanceSquared(plugin, p, l); + if (dist < min) { + valid = false; + break; + } + if (dist <= max) { + valid = true; + } + } + if (valid) { + result.add(l); + } + } + } else { + // If the min distance is 0, the old "any player within range" + // approach is sufficient, because we can never invalidate a + // spawnpoint for being too close to a player. + for (Location l : spawnpoints) { + for (Player p : players) { + double dist = MAUtils.distanceSquared(plugin, p, l); + if (dist <= max) { + result.add(l); + break; + } } - result.add(l); - break; } } @@ -70,7 +98,7 @@ public class WaveUtils } dist = p.getLocation().distanceSquared(e.getLocation()); - if (dist < current && dist < MobArena.MIN_PLAYER_DISTANCE_SQUARED) + if (dist < current && dist < arena.getSpawnpointMaxDistanceSquared()) { current = dist; result = p; diff --git a/src/main/resources/res/settings.yml b/src/main/resources/res/settings.yml index 862238e..54719e5 100644 --- a/src/main/resources/res/settings.yml +++ b/src/main/resources/res/settings.yml @@ -27,6 +27,8 @@ first-wave-delay: 5 next-wave-delay: 0 wave-interval: 15 final-wave: 0 +spawnpoint-min-distance: 0 +spawnpoint-max-distance: 15 monster-limit: 100 monster-exp: false keep-exp: false