Scale round difficulty over time and add claimable powerups
Build / build (push) Successful in 1m17s

Reshuffles the floor so the target color's share shrinks each round
(TargetDensityCalculator) instead of always averaging ~1/paletteSize,
making later rounds progressively harder to read.

Adds Super Speed and Air Blast powerups that spawn on the floor each
round, claimable by walking over or left-clicking their marker, expiring
after 2-3 unclaimed rounds. Usage is tracked in player stats.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
Michael Burgess
2026-08-08 11:31:30 -04:00
co-authored by Claude Sonnet 5
parent 8049aa04af
commit 4c4f5a1215
16 changed files with 739 additions and 51 deletions
@@ -97,6 +97,71 @@ public class ConfigManager {
return config.getBoolean("floor.shuffle-each-round", true);
}
/** Fraction of the floor made of the target color on round 1 (0-1). Below the natural
* 1/paletteSize average so even the first round is harder than a plain uniform shuffle. */
public double getStartingTargetBlockFraction() {
return config.getDouble("floor.starting-target-fraction", 0.5);
}
/** Fraction of the floor made of the target color on the hardest (late-game) rounds. */
public double getMinimumTargetBlockFraction() {
return config.getDouble("floor.minimum-target-fraction", 0.06);
}
/** How much the target color's share of the floor shrinks per round after the first. */
public double getTargetBlockFractionReductionPerRound() {
return config.getDouble("floor.target-fraction-reduction-per-round", 0.04);
}
public boolean isPowerupsEnabled() {
return config.getBoolean("powerups.enabled", true);
}
/** Chance (0-1), rolled once per round, that a new powerup spawns on the floor. */
public double getPowerupSpawnChance() {
return config.getDouble("powerups.spawn-chance-per-round", 0.35);
}
/** Cap on how many unclaimed powerups can sit on the floor at once. */
public int getPowerupMaxActive() {
return config.getInt("powerups.max-active", 1);
}
/** Minimum number of rounds an unclaimed powerup lingers before disappearing. */
public int getPowerupMinLifetimeRounds() {
return config.getInt("powerups.min-lifetime-rounds", 2);
}
/** Maximum number of rounds an unclaimed powerup lingers before disappearing. */
public int getPowerupMaxLifetimeRounds() {
return config.getInt("powerups.max-lifetime-rounds", 3);
}
public org.bukkit.Material getPowerupMarkerMaterial(String typeKey) {
String name = config.getString("powerups.types." + typeKey + ".marker-block", "TORCH");
org.bukkit.Material material = org.bukkit.Material.matchMaterial(name);
return material != null ? material : org.bukkit.Material.TORCH;
}
public int getSuperSpeedDurationSeconds() {
return config.getInt("powerups.types.super-speed.duration-seconds", 8);
}
/** Potion effect amplifier, i.e. Speed (amplifier + 1) - amplifier 1 = Speed II. */
public int getSuperSpeedAmplifier() {
return config.getInt("powerups.types.super-speed.amplifier", 1);
}
/** Radius, in blocks, that Air Blast pushes other nearby players within. */
public double getAirBlastRadius() {
return config.getDouble("powerups.types.air-blast.radius", 4.0);
}
/** Horizontal+vertical knockback strength applied to players caught in an Air Blast. */
public double getAirBlastStrength() {
return config.getDouble("powerups.types.air-blast.strength", 1.4);
}
public boolean isMusicEnabled() {
return config.getBoolean("music.enabled", false);
}