diff --git a/README.md b/README.md index 6df3143..2dde605 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ A Spigot 26.2 plugin that lets players earn six Creeper Aura ranks. Once unlocke ## Progression -Players earn one current-tier point when they kill a creeper directly, through a projectile, or through an owned tameable. A self-destructing creeper also awards one point to every player its explosion hits. Each tier defaults to 100 points and resets progress to zero when unlocked. +Players earn one current-tier point when they kill a creeper directly, through a projectile, or through an owned tameable. A self-destructing creeper also awards one point to every player its explosion hits. Rank I unlocks at 25 points by default; subsequent ranks require 100 points each. Progress resets to zero when a rank is unlocked. | Rank | Creeper damage | Block damage | | --- | ---: | --- | @@ -55,7 +55,7 @@ Commands provide permission-aware tab completion for subcommands, online player ```yaml progression: requirements: - I: 100 + I: 25 II: 100 III: 100 IV: 100 diff --git a/design/log.md b/design/log.md index 1d835dd..a7e0701 100644 --- a/design/log.md +++ b/design/log.md @@ -9,6 +9,7 @@ description: Chronological record of material changes to the Spigot Creeper Fear ## 2026-08-11 - Updated US-002 so an unlocked player's aura protects blocks from any creeper explosion within 25 blocks, without requiring the explosion to hit the player. +- Updated US-002 and US-006 so rank I requires 25 creeper kills by default while later ranks continue to require 100. ## 2026-08-10 diff --git a/design/user-stories/us-002-unlock-creeper-aura-ranks.md b/design/user-stories/us-002-unlock-creeper-aura-ranks.md index e313a40..da97ff7 100644 --- a/design/user-stories/us-002-unlock-creeper-aura-ranks.md +++ b/design/user-stories/us-002-unlock-creeper-aura-ranks.md @@ -13,7 +13,7 @@ As a **player**, I want Creeper Aura to become stronger as I defeat creepers so | Current state | Kills needed to unlock next rank | Damage to protected player | Creeper block damage | | --- | ---: | ---: | --- | -| Locked | 100 to unlock I | 1× | Normal | +| Locked | 25 to unlock I | 1× | Normal | | Creeper Aura I | 100 to unlock II | 3× | Prevented | | Creeper Aura II | 100 to unlock III | 2× | Prevented | | Creeper Aura III | 100 to unlock IV | 1.5× | Prevented | @@ -23,7 +23,7 @@ As a **player**, I want Creeper Aura to become stronger as I defeat creepers so ## Acceptance criteria -- [x] A player unlocks the next rank after earning the configured number of kills within their current tier. +- [x] A player unlocks rank I after 25 kills by default; subsequent ranks require 100 kills each by default. - [x] Unlocking a rank resets current-tier progress to zero. - [x] A player below rank I receives normal creeper explosion behavior. - [x] An aura protects blocks when a player with rank I or higher is within 25 blocks of a creeper at explosion time, including at exactly 25 blocks. diff --git a/design/user-stories/us-006-configure-aura-progression.md b/design/user-stories/us-006-configure-aura-progression.md index 3a65d60..12e6392 100644 --- a/design/user-stories/us-006-configure-aura-progression.md +++ b/design/user-stories/us-006-configure-aura-progression.md @@ -11,7 +11,7 @@ As a **server administrator**, I want to configure progression and aura behavior ## Acceptance criteria -- [x] Configuration provides documented defaults for the six per-rank kill requirements and six unlocked-rank damage multipliers. +- [x] Configuration defaults to 25 kills for rank I, 100 kills for each subsequent rank, and the documented six unlocked-rank damage multipliers. - [x] Rank requirements are positive integers. - [x] Damage multipliers are finite and non-negative. - [x] Progress boss-bar duration and player-facing rank messages are configurable. diff --git a/src/main/java/games/dmg/creeperfear/aura/AuraRules.java b/src/main/java/games/dmg/creeperfear/aura/AuraRules.java index c981934..9e24f7e 100644 --- a/src/main/java/games/dmg/creeperfear/aura/AuraRules.java +++ b/src/main/java/games/dmg/creeperfear/aura/AuraRules.java @@ -17,7 +17,7 @@ public final class AuraRules { public static AuraRules defaults() { Map requirements = new EnumMap<>(AuraRank.class); for (AuraRank rank : AuraRank.values()) { - if (!rank.isMaximum()) requirements.put(rank, 100); + if (!rank.isMaximum()) requirements.put(rank, rank == AuraRank.LOCKED ? 25 : 100); } Map multipliers = new EnumMap<>(AuraRank.class); multipliers.put(AuraRank.LOCKED, 1.0); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 66eef95..d301f10 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,6 +1,6 @@ progression: requirements: - I: 100 + I: 25 II: 100 III: 100 IV: 100 diff --git a/src/test/java/games/dmg/creeperfear/aura/AuraRulesTest.java b/src/test/java/games/dmg/creeperfear/aura/AuraRulesTest.java index 1aed368..9d50d74 100644 --- a/src/test/java/games/dmg/creeperfear/aura/AuraRulesTest.java +++ b/src/test/java/games/dmg/creeperfear/aura/AuraRulesTest.java @@ -11,8 +11,8 @@ class AuraRulesTest { private final AuraRules rules = AuraRules.defaults(); @Test - void unlocksOneRankAndResetsTierProgressAtOneHundredKills() { - PlayerProgress progress = new PlayerProgress(UUID.randomUUID(), "Player", AuraRank.LOCKED, 100); + void unlocksFirstRankAndResetsTierProgressAtTwentyFiveKills() { + PlayerProgress progress = new PlayerProgress(UUID.randomUUID(), "Player", AuraRank.LOCKED, 25); PlayerProgress advanced = rules.advanceIfEarned(progress); @@ -20,6 +20,12 @@ class AuraRulesTest { assertEquals(0, advanced.tierKills()); } + @Test + void usesOneHundredKillsForLaterRanksByDefault() { + assertEquals(100, rules.requirementForCurrentRank(AuraRank.I)); + assertEquals(100, rules.requirementForCurrentRank(AuraRank.V)); + } + @Test void appliesTheDefaultDamageMultipliers() { assertEquals(3.0, rules.damageMultiplier(AuraRank.I)); diff --git a/src/test/java/games/dmg/creeperfear/config/AuraConfigLoaderTest.java b/src/test/java/games/dmg/creeperfear/config/AuraConfigLoaderTest.java index 649caea..4fbe9c2 100644 --- a/src/test/java/games/dmg/creeperfear/config/AuraConfigLoaderTest.java +++ b/src/test/java/games/dmg/creeperfear/config/AuraConfigLoaderTest.java @@ -4,10 +4,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import games.dmg.creeperfear.progress.AuraRank; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import org.bukkit.configuration.file.YamlConfiguration; import org.junit.jupiter.api.Test; class AuraConfigLoaderTest { + @Test + void bundledConfigurationDefaultsFirstRankToTwentyFiveKills() throws Exception { + try (InputStream stream = getClass().getResourceAsStream("/config.yml")) { + YamlConfiguration config = YamlConfiguration.loadConfiguration( + new InputStreamReader(stream, StandardCharsets.UTF_8)); + AuraConfiguration configuration = new AuraConfigLoader().load(config); + + assertEquals(25, configuration.rules().requirementForCurrentRank(AuraRank.LOCKED)); + assertEquals(100, configuration.rules().requirementForCurrentRank(AuraRank.I)); + } + } + @Test void loadsPerRankRequirementsMultipliersAndFeedback() throws Exception { AuraConfiguration configuration = new AuraConfigLoader().load(validConfiguration()); diff --git a/src/test/java/games/dmg/creeperfear/feedback/ProgressDisplayTest.java b/src/test/java/games/dmg/creeperfear/feedback/ProgressDisplayTest.java index 37f2a1e..08d9367 100644 --- a/src/test/java/games/dmg/creeperfear/feedback/ProgressDisplayTest.java +++ b/src/test/java/games/dmg/creeperfear/feedback/ProgressDisplayTest.java @@ -15,12 +15,12 @@ class ProgressDisplayTest { @Test void describesLockedCurrentTierProgress() { - PlayerProgress progress = new PlayerProgress(UUID.randomUUID(), "Player", AuraRank.LOCKED, 42); + PlayerProgress progress = new PlayerProgress(UUID.randomUUID(), "Player", AuraRank.LOCKED, 12); ProgressDisplay.State state = display.forProgress(progress); - assertEquals("Creeper Aura: Locked — 42 / 100", state.text()); - assertEquals(0.42, state.fraction(), 0.0001); + assertEquals("Creeper Aura: Locked — 12 / 25", state.text()); + assertEquals(0.48, state.fraction(), 0.0001); assertTrue(state.visible()); }