From 9c897873b53a86c467239f49de90f66648de5e56 Mon Sep 17 00:00:00 2001 From: Andreas Troelsen Date: Mon, 24 Jun 2024 23:31:08 +0200 Subject: [PATCH] Make clashing wave resolution randomized. This commit changes two things; it allows multiple single waves to have the same wave number, and it makes the wave selection procedure pick randomly between multiple valid matches. Effectively, this means that MobArena now picks randomly when clashing recurrent waves _also_ clash on priority (rather than deferring the decision to the arbitrary but deterministic nature of sorted sets), and it also picks randomly between multiple single waves with the same wave number (which was not possible before). This should allow server owners to add variety into their wave setups while maintaining a great deal of control over the randomness involved. For instance, it's now possible to have wave 10 be a boss wave, but the _actual_ boss wave is randomly picked between three different waves all with wave number 10. Upgrade waves could be randomized as well. As for randomized recurrent waves, perhaps instead of having potentially four different mobs in the same wave, a setup could instead have two _pairs_ of mobs that are randomly selected for a different kind of randomness. Closes #795 --- changelog.md | 3 + .../MobArena/waves/WaveManager.java | 106 ++++++++++++------ .../garbagemule/MobArena/waves/WaveUtils.java | 2 +- 3 files changed, 76 insertions(+), 35 deletions(-) diff --git a/changelog.md b/changelog.md index a22cb5c1..dbf35709 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,9 @@ These changes will (most likely) be included in the next version. ## [Unreleased] +### 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. +- Single waves can now be randomized. If two or more single waves clash on wave number, MobArena will now randomly pick between them. This means it is now possible to make randomly selected bosses for boss waves, for instance. ## [0.108] - 2024-01-01 ### Added diff --git a/src/main/java/com/garbagemule/MobArena/waves/WaveManager.java b/src/main/java/com/garbagemule/MobArena/waves/WaveManager.java index 922795c9..b1dc2e4f 100644 --- a/src/main/java/com/garbagemule/MobArena/waves/WaveManager.java +++ b/src/main/java/com/garbagemule/MobArena/waves/WaveManager.java @@ -4,7 +4,9 @@ import com.garbagemule.MobArena.waves.enums.WaveBranch; import org.bukkit.configuration.ConfigurationSection; -import java.util.SortedSet; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; import java.util.TreeSet; public class WaveManager @@ -12,10 +14,11 @@ public class WaveManager private Arena arena; private ConfigurationSection section; - private Wave defaultWave, currentWave; - private TreeSet recurrentWaves, singleWaves, singleWavesInstance; + private Wave defaultWave, currentWave, nextWave; + private TreeSet recurrentWaves, singleWaves; private int wave, finalWave; + private Random random = new Random(); public WaveManager(Arena arena, ConfigurationSection section) { this.arena = arena; @@ -26,14 +29,10 @@ public WaveManager(Arena arena, ConfigurationSection section) { reloadWaves(); } - public TreeSet getRecurrentWaves() { - return recurrentWaves; - } - public void reset() { reloadWaves(); wave = 0; - singleWavesInstance = new TreeSet<>(singleWaves); + determineNextWave(); } public void reloadWaves() { @@ -61,21 +60,77 @@ public void reloadWaves() { } } + private void determineNextWave() { + // Single waves take precedence over recurrent waves + List singles = findSingleWaveCandidates(wave + 1); + if (!singles.isEmpty()) { + nextWave = pickRandomWave(singles); + return; + } + + List recurrents = findRecurrentWaveCandidates(wave + 1); + if (!recurrents.isEmpty()) { + nextWave = pickRandomWave(recurrents); + } else { + nextWave = defaultWave.copy(); + } + } + + private List findSingleWaveCandidates(int wave) { + List candidates = new ArrayList<>(singleWaves.size()); + for (Wave w : singleWaves) { + if (w.matches(wave)) { + candidates.add(w); + } + } + + return candidates; + } + + private List findRecurrentWaveCandidates(int wave) { + List matches = new ArrayList<>(recurrentWaves.size()); + for (Wave w : recurrentWaves) { + if (w.matches(wave)) { + matches.add(w); + } + } + + int priority = 0; + for (Wave w : matches) { + if (w.getPriority() > priority) { + priority = w.getPriority(); + } + } + + List candidates = new ArrayList<>(matches.size()); + for (Wave w : matches) { + if (w.getPriority() == priority) { + candidates.add(w); + } + } + + return candidates; + } + + private Wave pickRandomWave(List candidates) { + if (candidates.size() == 1) { + return candidates.get(0).copy(); + } + + int index = random.nextInt(candidates.size()); + return candidates.get(index).copy(); + } + /** * Increment the wave number and get the next Wave to be spawned. * Note that this method is a mutator. * @return the next Wave */ public Wave next() { - wave++; + currentWave = nextWave; - if (!singleWavesInstance.isEmpty() && singleWavesInstance.first().matches(wave)) { - currentWave = singleWavesInstance.pollFirst().copy(); - } - else { - SortedSet matches = getMatchingRecurrentWaves(wave); - currentWave = (matches.isEmpty() ? defaultWave : matches.last()).copy(); - } + wave++; + determineNextWave(); return currentWave; } @@ -87,14 +142,7 @@ public Wave next() { * @return the next Wave */ public Wave getNext() { - int next = wave + 1; - - if (!singleWavesInstance.isEmpty() && singleWavesInstance.first().matches(next)) { - return singleWavesInstance.first(); - } - - SortedSet matches = getMatchingRecurrentWaves(wave); - return (matches.isEmpty() ? defaultWave : matches.last()); + return nextWave; } /** @@ -121,14 +169,4 @@ public int getWaveNumber() { public int getFinalWave() { return finalWave; } - - private SortedSet getMatchingRecurrentWaves(int wave) { - TreeSet result = new TreeSet<>(WaveUtils.getRecurrentComparator()); - for (Wave w : recurrentWaves) { - if (w.matches(wave)) { - result.add(w); - } - } - return result; - } } diff --git a/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java b/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java index 633c79d8..0f134601 100644 --- a/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java +++ b/src/main/java/com/garbagemule/MobArena/waves/WaveUtils.java @@ -114,7 +114,7 @@ public int compare(Wave w1, Wave w2) return -1; else if (w1.getFirstWave() > w2.getFirstWave()) return 1; - else return 0; + else return w1.getName().compareTo(w2.getName()); } }; }