Phase 3: soft level pressure, less experience far above a zone's band
- Companion mod (zone/LevelPressure.kt): a Pokemon more than 5 levels above the band of the zone its trainer is in gets 10% less experience per extra level, down to 10%. Exp. Candy and commands are exempt; no hard level caps (roadmap). - Rules in world/zones.json -> level_pressure, shipped in the zone layout. - Self-test level_pressure_cuts_xp. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d105f6757d
commit
173203eeb5
10 files changed
+91
-3
No files matched your search
@@ -1,6 +1,8 @@
|
||||
package dev.cobblesurvival.selftest
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.pokemon.experience.CandyExperienceSource
|
||||
import com.cobblemon.mod.common.api.pokemon.experience.SidemodExperienceSource
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawnPools
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnCause
|
||||
import com.cobblemon.mod.common.api.spawning.detail.PokemonSpawnDetail
|
||||
@@ -9,6 +11,7 @@ import com.cobblemon.mod.common.api.spawning.position.calculators.SpawnablePosit
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.SpawningZoneInput
|
||||
import com.cobblemon.mod.common.util.spawner
|
||||
import dev.cobblesurvival.CobbleSurvival
|
||||
import dev.cobblesurvival.zone.LevelPressure
|
||||
import dev.cobblesurvival.zone.Zone
|
||||
import dev.cobblesurvival.zone.ZoneSample
|
||||
import dev.cobblesurvival.zone.Zones
|
||||
@@ -16,7 +19,9 @@ import net.minecraft.core.BlockPos
|
||||
import net.minecraft.gametest.framework.GameTestAssertException
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.levelgen.Heightmap
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Roadmap Phase 3: each zone has its own Pokémon and levels. The spawn pools come from tools/zone_spawns.py;
|
||||
@@ -30,10 +35,36 @@ object ZoneTests {
|
||||
fun all() = listOf(
|
||||
SelfTestCase("spawn_pools_are_zoned", 20, ::spawnPoolsAreZoned),
|
||||
SelfTestCase("spawn_survey", 2400, ::spawnSurvey, islandOnly = true),
|
||||
SelfTestCase("level_pressure_cuts_xp", 100, ::levelPressure),
|
||||
)
|
||||
|
||||
private fun zoneOf(detail: SpawnDetail): Zone? = Zones.byId[detail.id.substringBefore('-')]
|
||||
|
||||
/** On Button Isle (band up to 10, 5 levels' grace): a Lv 10 Pokémon keeps its experience, a Lv 25 one 10 %. */
|
||||
private fun levelPressure(s: Scenario) {
|
||||
val zone = Zones.byId["button_isle"] ?: throw GameTestAssertException("no Button Isle zone")
|
||||
val sample = Zones.samples["button_isle"] ?: throw GameTestAssertException("no sample point for Button Isle")
|
||||
val player = s.player()
|
||||
val inBand = s.give(player, s.pokemon("bidoof", zone.maxLevel))
|
||||
val farAbove = s.give(player, s.pokemon("bidoof", zone.maxLevel + 15))
|
||||
val expected = (1000 * LevelPressure.factor(farAbove.level, zone)).roundToInt()
|
||||
s.helper.startSequence()
|
||||
.thenExecute {
|
||||
s.level.getChunk(sample.x shr 4, sample.z shr 4)
|
||||
s.moveTo(player, sample.x + 0.5, s.level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, sample.x, sample.z).toDouble(), sample.z + 0.5)
|
||||
}
|
||||
.thenExecute {
|
||||
val battle = SidemodExperienceSource(CobbleSurvival.MOD_ID)
|
||||
val kept = inBand.addExperienceWithPlayer(player, battle, 1000).experienceAdded
|
||||
val cut = farAbove.addExperienceWithPlayer(player, battle, 1000).experienceAdded
|
||||
val candy = farAbove.addExperienceWithPlayer(player, CandyExperienceSource(player, ItemStack.EMPTY), 1000).experienceAdded
|
||||
s.check(kept == 1000) { "a Pokémon at the band's top got $kept of 1000 experience" }
|
||||
s.check(cut == expected) { "a Pokémon 15 levels above the band got $cut of 1000 experience, not $expected" }
|
||||
s.check(candy == 1000) { "Exp. Candy was cut too: $candy of 1000" }
|
||||
}
|
||||
.thenSucceed()
|
||||
}
|
||||
|
||||
/** Every loaded spawn entry belongs to a zone and spawns within its level band; none of Cobblemon's is left. */
|
||||
private fun spawnPoolsAreZoned(s: Scenario) {
|
||||
val details = CobblemonSpawnPools.WORLD_SPAWN_POOL.details
|
||||
|
||||
Reference in new issue
Block a user