diff --git a/.env.development b/.env.development index e4e5053016f..91c228d6761 100644 --- a/.env.development +++ b/.env.development @@ -1,6 +1,7 @@ VITE_BYPASS_LOGIN=1 VITE_BYPASS_TUTORIAL=0 VITE_SERVER_URL=http://localhost:8001 +# IDs for discord/google auth go unused due to VITE_BYPASS_LOGIN VITE_DISCORD_CLIENT_ID=1234567890 VITE_GOOGLE_CLIENT_ID=1234567890 VITE_I18N_DEBUG=0 diff --git a/scripts/create-test/create-test.js b/scripts/create-test/create-test.js index e71994472f3..d5cac5cd408 100644 --- a/scripts/create-test/create-test.js +++ b/scripts/create-test/create-test.js @@ -48,7 +48,7 @@ async function promptTestType() { { type: "list", name: "selectedOption", - message: "What type of test would you like to create:", + message: "What type of test would you like to create?", choices: [...choices.map(choice => ({ name: choice.label, value: choice })), "EXIT"], }, ]); diff --git a/scripts/create-test/test-boilerplate.ts b/scripts/create-test/test-boilerplate.ts index 40912be6c5f..1fbd3c8040a 100644 --- a/scripts/create-test/test-boilerplate.ts +++ b/scripts/create-test/test-boilerplate.ts @@ -24,7 +24,7 @@ describe("{{description}}", () => { game.override .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 81c65d85e06..14b0c6a3d19 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -2094,12 +2094,15 @@ export default class BattleScene extends SceneBase { } getMaxExpLevel(ignoreLevelCap = false): number { - if (Overrides.LEVEL_CAP_OVERRIDE > 0) { - return Overrides.LEVEL_CAP_OVERRIDE; + const capOverride = Overrides.LEVEL_CAP_OVERRIDE ?? 0; + if (capOverride > 0) { + return capOverride; } - if (ignoreLevelCap || Overrides.LEVEL_CAP_OVERRIDE < 0) { + + if (ignoreLevelCap || capOverride < 0) { return Number.MAX_SAFE_INTEGER; } + const waveIndex = Math.ceil((this.currentBattle?.waveIndex || 1) / 10) * 10; const difficultyWaveIndex = this.gameMode.getWaveForDifficulty(waveIndex); const baseLevel = (1 + difficultyWaveIndex / 2 + Math.pow(difficultyWaveIndex / 25, 2)) * 1.2; @@ -3492,17 +3495,13 @@ export default class BattleScene extends SceneBase { sessionEncounterRate + Math.min(currentRunDiffFromAvg * ANTI_VARIANCE_WEIGHT_MODIFIER, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT / 2); - const successRate = isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_RATE_OVERRIDE) - ? favoredEncounterRate - : Overrides.MYSTERY_ENCOUNTER_RATE_OVERRIDE!; + const successRate = Overrides.MYSTERY_ENCOUNTER_RATE_OVERRIDE ?? favoredEncounterRate; - // If the most recent ME was 3 or fewer waves ago, can never spawn a ME + // MEs can only spawn 3 or more waves after the previous ME, barring overrides const canSpawn = - encounteredEvents.length === 0 || - waveIndex - encounteredEvents[encounteredEvents.length - 1].waveIndex > 3 || - !isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_RATE_OVERRIDE); + encounteredEvents.length === 0 || waveIndex - encounteredEvents[encounteredEvents.length - 1].waveIndex > 3; - if (canSpawn) { + if (canSpawn || Overrides.MYSTERY_ENCOUNTER_RATE_OVERRIDE !== null) { let roll = MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT; // Always rolls the check on the same offset to ensure no RNG changes from reloading session this.executeWithSeedOffset( diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index ef4529c361e..a605ffe5637 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -4616,7 +4616,7 @@ export class ConditionalUserFieldProtectStatAbAttr extends PreStatStageChangeAbA * @param stat The stat being affected * @param cancelled Holds whether the stat change was already prevented. * @param args Args[0] is the target pokemon of the stat change. - * @returns + * @returns `true` if the ability can be applied */ override canApplyPreStatStageChange( _pokemon: Pokemon, @@ -4777,17 +4777,17 @@ export class BlockCritAbAttr extends AbAttr { } /** - * Apply the block crit ability by setting the value in the provided boolean holder to false - * @param args - [0] is a boolean holder representing whether the attack can crit + * Apply the block crit ability by setting the value in the provided boolean holder to `true`. + * @param args `[0]` - A {@linkcode BooleanHolder} containing whether the attack is prevented from critting. */ override apply( _pokemon: Pokemon, _passive: boolean, _simulated: boolean, _cancelled: BooleanHolder, - args: [BooleanHolder, ...any], + args: [BooleanHolder], ): void { - args[0].value = false; + args[0].value = true; } } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 834c65437af..26def895b51 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1356,8 +1356,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } /** - * Calculate the critical-hit stage of a move used against this pokemon by - * the given source + * Calculate the critical-hit stage of a move used **against** this pokemon by + * the given source. + * * @param source - The {@linkcode Pokemon} using the move * @param move - The {@linkcode Move} being used * @returns The final critical-hit stage value @@ -1370,11 +1371,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { applyAbAttrs("BonusCritAbAttr", source, null, false, critStage); const critBoostTag = source.getTag(CritBoostTag); if (critBoostTag) { - if (critBoostTag instanceof DragonCheerTag) { - critStage.value += critBoostTag.typesOnAdd.includes(PokemonType.DRAGON) ? 2 : 1; - } else { - critStage.value += 2; - } + // Dragon cheer only gives +1 crit stage to non-dragon types + critStage.value += + critBoostTag instanceof DragonCheerTag && !critBoostTag.typesOnAdd.includes(PokemonType.DRAGON) ? 1 : 2; } console.log(`crit stage: +${critStage.value}`); @@ -3888,33 +3887,39 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { }; } - /** Calculate whether the given move critically hits this pokemon + /** + * Determine whether the given move will score a critical hit **against** this Pokemon. * @param source - The {@linkcode Pokemon} using the move * @param move - The {@linkcode Move} being used - * @param simulated - If `true`, suppresses changes to game state during calculation (defaults to `true`) - * @returns whether the move critically hits the pokemon + * @returns Whether the move will critically hit the defender. */ - getCriticalHitResult(source: Pokemon, move: Move, simulated = true): boolean { - const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; - const noCritTag = globalScene.arena.getTagOnSide(NoCritTag, defendingSide); - if (noCritTag || Overrides.NEVER_CRIT_OVERRIDE || move.hasAttr("FixedDamageAttr")) { + getCriticalHitResult(source: Pokemon, move: Move): boolean { + if (move.hasAttr("FixedDamageAttr")) { + // fixed damage moves (Dragon Rage, etc.) will nevet crit return false; } - const isCritical = new BooleanHolder(false); - if (source.getTag(BattlerTagType.ALWAYS_CRIT)) { - isCritical.value = true; - } - applyMoveAttrs("CritOnlyAttr", source, this, move, isCritical); - applyAbAttrs("ConditionalCritAbAttr", source, null, simulated, isCritical, this, move); - if (!isCritical.value) { - const critChance = [24, 8, 2, 1][Math.max(0, Math.min(this.getCritStage(source, move), 3))]; - isCritical.value = critChance === 1 || !globalScene.randBattleSeedInt(critChance); - } + const alwaysCrit = new BooleanHolder(false); + applyMoveAttrs("CritOnlyAttr", source, this, move, alwaysCrit); + applyAbAttrs("ConditionalCritAbAttr", source, null, false, alwaysCrit, this, move); + const alwaysCritTag = !!source.getTag(BattlerTagType.ALWAYS_CRIT); + const critChance = [24, 8, 2, 1][Phaser.Math.Clamp(this.getCritStage(source, move), 0, 3)]; - applyAbAttrs("BlockCritAbAttr", this, null, simulated, isCritical); + let isCritical = alwaysCrit.value || alwaysCritTag || critChance === 1; - return isCritical.value; + // If we aren't already guaranteed to crit, do a random roll & check overrides + isCritical ||= Overrides.CRITICAL_HIT_OVERRIDE ?? globalScene.randBattleSeedInt(critChance) === 0; + + // apply crit block effects from lucky chant & co., overridding previous effects + const blockCrit = new BooleanHolder(false); + applyAbAttrs("BlockCritAbAttr", this, null, false, blockCrit); + const blockCritTag = globalScene.arena.getTagOnSide( + NoCritTag, + this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, + ); + isCritical &&= !blockCritTag && !blockCrit.value; // need to roll a crit and not be blocked by either crit prevention effect + + return isCritical; } /** diff --git a/src/game-mode.ts b/src/game-mode.ts index a6fc8195175..a83de95e6af 100644 --- a/src/game-mode.ts +++ b/src/game-mode.ts @@ -90,13 +90,14 @@ export class GameMode implements GameModeConfig { } /** + * Helper function to get starting level for game mode. * @returns either: - * - override from overrides.ts + * - starting level override from overrides.ts * - 20 for Daily Runs * - 5 for all other modes */ getStartingLevel(): number { - if (Overrides.STARTING_LEVEL_OVERRIDE) { + if (Overrides.STARTING_LEVEL_OVERRIDE && Overrides.STARTING_LEVEL_OVERRIDE > 0) { return Overrides.STARTING_LEVEL_OVERRIDE; } switch (this.modeId) { diff --git a/src/overrides.ts b/src/overrides.ts index b5df1073c28..20103b8322b 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -80,7 +80,11 @@ class DefaultOverrides { /** Sets the level cap to this number during experience gain calculations. Set to `0` to disable override & use normal wave-based level caps, or any negative number to set it to 9 quadrillion (effectively disabling it). */ readonly LEVEL_CAP_OVERRIDE: number = 0; - readonly NEVER_CRIT_OVERRIDE: boolean = false; + /** + * If defined, overrides random critical hit rolls to always or never succeed. + * Ignored if the move is guaranteed to always/never crit. + */ + readonly CRITICAL_HIT_OVERRIDE: boolean | null = null; /** default 1000 */ readonly STARTING_MONEY_OVERRIDE: number = 0; /** Sets all shop item prices to 0 */ @@ -272,7 +276,7 @@ class DefaultOverrides { /** * Set all non-scripted waves to use the selected battle type. - * + * * Ignored if set to {@linkcode BattleType.TRAINER} and `DISABLE_STANDARD_TRAINERS_OVERRIDE` is `true`. */ readonly BATTLE_TYPE_OVERRIDE: Exclude | null = null; diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 770d9c79a2a..2338811191b 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -797,7 +797,7 @@ export class MoveEffectPhase extends PokemonPhase { * @param effectiveness - The effectiveness of the move against the target */ protected applyMoveDamage(user: Pokemon, target: Pokemon, effectiveness: TypeDamageMultiplier): HitResult { - const isCritical = target.getCriticalHitResult(user, this.move, false); + const isCritical = target.getCriticalHitResult(user, this.move); /* * Apply stat changes from {@linkcode move} and gives it to {@linkcode source} diff --git a/test/abilities/ability_activation_order.test.ts b/test/abilities/ability_activation_order.test.ts index 04adf40b623..0b8e354cc7d 100644 --- a/test/abilities/ability_activation_order.test.ts +++ b/test/abilities/ability_activation_order.test.ts @@ -27,7 +27,7 @@ describe("Ability Activation Order", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/analytic.test.ts b/test/abilities/analytic.test.ts index 2cfea64d20e..5dbf4365186 100644 --- a/test/abilities/analytic.test.ts +++ b/test/abilities/analytic.test.ts @@ -27,7 +27,7 @@ describe("Abilities - Analytic", () => { .moveset([MoveId.SPLASH, MoveId.TACKLE]) .ability(AbilityId.ANALYTIC) .battleStyle("single") - .disableCrits() + .criticalHits(false) .startingLevel(200) .enemyLevel(200) .enemySpecies(SpeciesId.SNORLAX) diff --git a/test/abilities/commander.test.ts b/test/abilities/commander.test.ts index 39d9d0f4d7f..99512d7a733 100644 --- a/test/abilities/commander.test.ts +++ b/test/abilities/commander.test.ts @@ -35,7 +35,7 @@ describe("Abilities - Commander", () => { .moveset([MoveId.LIQUIDATION, MoveId.MEMENTO, MoveId.SPLASH, MoveId.FLIP_TURN]) .ability(AbilityId.COMMANDER) .battleStyle("double") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.SNORLAX) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.TACKLE); diff --git a/test/abilities/corrosion.test.ts b/test/abilities/corrosion.test.ts index 81b04ef340c..2a0464d1146 100644 --- a/test/abilities/corrosion.test.ts +++ b/test/abilities/corrosion.test.ts @@ -24,7 +24,7 @@ describe("Abilities - Corrosion", () => { game.override .moveset([MoveId.SPLASH]) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.GRIMER) .enemyAbility(AbilityId.CORROSION) .enemyMoveset(MoveId.TOXIC); diff --git a/test/abilities/cud_chew.test.ts b/test/abilities/cud_chew.test.ts index 8a80c6625cc..70c282bf8a8 100644 --- a/test/abilities/cud_chew.test.ts +++ b/test/abilities/cud_chew.test.ts @@ -33,7 +33,7 @@ describe("Abilities - Cud Chew", () => { .startingHeldItems([{ name: "BERRY", type: BerryType.SITRUS, count: 1 }]) .ability(AbilityId.CUD_CHEW) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/dry_skin.test.ts b/test/abilities/dry_skin.test.ts index 549bb45ba9a..31620beb9bd 100644 --- a/test/abilities/dry_skin.test.ts +++ b/test/abilities/dry_skin.test.ts @@ -23,7 +23,7 @@ describe("Abilities - Dry Skin", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemyAbility(AbilityId.DRY_SKIN) .enemyMoveset(MoveId.SPLASH) .enemySpecies(SpeciesId.CHARMANDER) diff --git a/test/abilities/early_bird.test.ts b/test/abilities/early_bird.test.ts index e19f2653b57..dcdfd8e4956 100644 --- a/test/abilities/early_bird.test.ts +++ b/test/abilities/early_bird.test.ts @@ -28,7 +28,7 @@ describe("Abilities - Early Bird", () => { .moveset([MoveId.REST, MoveId.BELLY_DRUM, MoveId.SPLASH]) .ability(AbilityId.EARLY_BIRD) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/flash_fire.test.ts b/test/abilities/flash_fire.test.ts index 92bd7b52e57..1095b715bff 100644 --- a/test/abilities/flash_fire.test.ts +++ b/test/abilities/flash_fire.test.ts @@ -32,7 +32,7 @@ describe("Abilities - Flash Fire", () => { .enemyAbility(AbilityId.BALL_FETCH) .startingLevel(20) .enemyLevel(20) - .disableCrits(); + .criticalHits(false); }); it("immune to Fire-type moves", async () => { diff --git a/test/abilities/flower_veil.test.ts b/test/abilities/flower_veil.test.ts index c59d8c6eb29..2cb57d275d1 100644 --- a/test/abilities/flower_veil.test.ts +++ b/test/abilities/flower_veil.test.ts @@ -32,7 +32,7 @@ describe("Abilities - Flower Veil", () => { .enemySpecies(SpeciesId.BULBASAUR) .ability(AbilityId.FLOWER_VEIL) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/good_as_gold.test.ts b/test/abilities/good_as_gold.test.ts index 85fadd472dc..fa18b7380ef 100644 --- a/test/abilities/good_as_gold.test.ts +++ b/test/abilities/good_as_gold.test.ts @@ -33,7 +33,7 @@ describe("Abilities - Good As Gold", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.GOOD_AS_GOLD) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/gulp_missile.test.ts b/test/abilities/gulp_missile.test.ts index b41eea9ce18..e47b22f0c06 100644 --- a/test/abilities/gulp_missile.test.ts +++ b/test/abilities/gulp_missile.test.ts @@ -41,7 +41,7 @@ describe("Abilities - Gulp Missile", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .disableCrits() + .criticalHits(false) .battleStyle("single") .moveset([MoveId.SURF, MoveId.DIVE, MoveId.SPLASH, MoveId.SUBSTITUTE]) .enemySpecies(SpeciesId.SNORLAX) diff --git a/test/abilities/harvest.test.ts b/test/abilities/harvest.test.ts index 40e6a6abd62..662eeed6dd0 100644 --- a/test/abilities/harvest.test.ts +++ b/test/abilities/harvest.test.ts @@ -47,7 +47,7 @@ describe("Abilities - Harvest", () => { .ability(AbilityId.HARVEST) .startingLevel(100) .battleStyle("single") - .disableCrits() + .criticalHits(false) .statusActivation(false) // Since we're using nuzzle to proc both enigma and sitrus berries .weather(WeatherType.SUNNY) // guaranteed recovery .enemyLevel(1) diff --git a/test/abilities/healer.test.ts b/test/abilities/healer.test.ts index 9d252523cc8..02f6e7c46d2 100644 --- a/test/abilities/healer.test.ts +++ b/test/abilities/healer.test.ts @@ -33,7 +33,7 @@ describe("Abilities - Healer", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("double") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/heatproof.test.ts b/test/abilities/heatproof.test.ts index f705e8bf785..39c9dff8289 100644 --- a/test/abilities/heatproof.test.ts +++ b/test/abilities/heatproof.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Heatproof", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.CHARMANDER) .enemyAbility(AbilityId.HEATPROOF) .enemyMoveset(MoveId.SPLASH) diff --git a/test/abilities/honey_gather.test.ts b/test/abilities/honey_gather.test.ts index 06d351b2a61..f8700f3e6f7 100644 --- a/test/abilities/honey_gather.test.ts +++ b/test/abilities/honey_gather.test.ts @@ -29,7 +29,7 @@ describe("Abilities - Honey Gather", () => { .ability(AbilityId.HONEY_GATHER) .passiveAbility(AbilityId.RUN_AWAY) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/hustle.test.ts b/test/abilities/hustle.test.ts index 58aa01bb39a..ae66b796cc3 100644 --- a/test/abilities/hustle.test.ts +++ b/test/abilities/hustle.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Hustle", () => { game.override .ability(AbilityId.HUSTLE) .moveset([MoveId.TACKLE, MoveId.GIGA_DRAIN, MoveId.FISSURE]) - .disableCrits() + .criticalHits(false) .battleStyle("single") .enemyMoveset(MoveId.SPLASH) .enemySpecies(SpeciesId.SHUCKLE) diff --git a/test/abilities/immunity.test.ts b/test/abilities/immunity.test.ts index b6ca34bfaa3..063ab57f11a 100644 --- a/test/abilities/immunity.test.ts +++ b/test/abilities/immunity.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Immunity", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/infiltrator.test.ts b/test/abilities/infiltrator.test.ts index 03b55e925cd..a5de035a136 100644 --- a/test/abilities/infiltrator.test.ts +++ b/test/abilities/infiltrator.test.ts @@ -31,7 +31,7 @@ describe("Abilities - Infiltrator", () => { .moveset([MoveId.TACKLE, MoveId.WATER_GUN, MoveId.SPORE, MoveId.BABY_DOLL_EYES]) .ability(AbilityId.INFILTRATOR) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.SNORLAX) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH) diff --git a/test/abilities/insomnia.test.ts b/test/abilities/insomnia.test.ts index 418e0ed1345..800663823c3 100644 --- a/test/abilities/insomnia.test.ts +++ b/test/abilities/insomnia.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Insomnia", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/lightningrod.test.ts b/test/abilities/lightningrod.test.ts index a69f5e94067..2dc29500454 100644 --- a/test/abilities/lightningrod.test.ts +++ b/test/abilities/lightningrod.test.ts @@ -27,7 +27,7 @@ describe("Abilities - Lightningrod", () => { .moveset([MoveId.SPLASH, MoveId.SHOCK_WAVE]) .ability(AbilityId.BALL_FETCH) .battleStyle("double") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/limber.test.ts b/test/abilities/limber.test.ts index 2ca469dcaa1..77acd8b3dab 100644 --- a/test/abilities/limber.test.ts +++ b/test/abilities/limber.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Limber", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/magic_bounce.test.ts b/test/abilities/magic_bounce.test.ts index 3c4ff2ad909..1816c312678 100644 --- a/test/abilities/magic_bounce.test.ts +++ b/test/abilities/magic_bounce.test.ts @@ -32,7 +32,7 @@ describe("Abilities - Magic Bounce", () => { .ability(AbilityId.BALL_FETCH) .battleStyle("single") .moveset([MoveId.GROWL, MoveId.SPLASH]) - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.MAGIC_BOUNCE) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/magic_guard.test.ts b/test/abilities/magic_guard.test.ts index 40bb3203673..1f58812e756 100644 --- a/test/abilities/magic_guard.test.ts +++ b/test/abilities/magic_guard.test.ts @@ -89,7 +89,7 @@ describe("Abilities - Magic Guard", () => { }); it("ability effect should not persist when the ability is replaced", async () => { - game.override.enemyMoveset([MoveId.WORRY_SEED, MoveId.WORRY_SEED, MoveId.WORRY_SEED, MoveId.WORRY_SEED]); + game.override.enemyMoveset([MoveId.WORRY_SEED]); game.override.statusEffect(StatusEffect.POISON); await game.classicMode.startBattle([SpeciesId.MAGIKARP]); diff --git a/test/abilities/magma_armor.test.ts b/test/abilities/magma_armor.test.ts index 74493fac365..0a8f3024291 100644 --- a/test/abilities/magma_armor.test.ts +++ b/test/abilities/magma_armor.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Magma Armor", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/mimicry.test.ts b/test/abilities/mimicry.test.ts index df6facc3755..7ac7aeb599f 100644 --- a/test/abilities/mimicry.test.ts +++ b/test/abilities/mimicry.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Mimicry", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.MIMICRY) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyMoveset(MoveId.SPLASH); }); diff --git a/test/abilities/mold_breaker.test.ts b/test/abilities/mold_breaker.test.ts index e2e8a73da9d..28a077e8908 100644 --- a/test/abilities/mold_breaker.test.ts +++ b/test/abilities/mold_breaker.test.ts @@ -27,7 +27,7 @@ describe("Abilities - Mold Breaker", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.MOLD_BREAKER) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/mummy.test.ts b/test/abilities/mummy.test.ts index 2b35e801677..d6c40541d25 100644 --- a/test/abilities/mummy.test.ts +++ b/test/abilities/mummy.test.ts @@ -25,7 +25,7 @@ describe("Abilities - Mummy", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.MUMMY) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.TACKLE); diff --git a/test/abilities/mycelium_might.test.ts b/test/abilities/mycelium_might.test.ts index 1f236f2c2fe..48f75f501cd 100644 --- a/test/abilities/mycelium_might.test.ts +++ b/test/abilities/mycelium_might.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Mycelium Might", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.SHUCKLE) .enemyAbility(AbilityId.CLEAR_BODY) diff --git a/test/abilities/neutralizing_gas.test.ts b/test/abilities/neutralizing_gas.test.ts index 51d2bed3ff0..2408a78f11d 100644 --- a/test/abilities/neutralizing_gas.test.ts +++ b/test/abilities/neutralizing_gas.test.ts @@ -31,7 +31,7 @@ describe("Abilities - Neutralizing Gas", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.NEUTRALIZING_GAS) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/normalize.test.ts b/test/abilities/normalize.test.ts index 821ce9589a1..4719df77710 100644 --- a/test/abilities/normalize.test.ts +++ b/test/abilities/normalize.test.ts @@ -29,7 +29,7 @@ describe("Abilities - Normalize", () => { .moveset([MoveId.TACKLE]) .ability(AbilityId.NORMALIZE) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/oblivious.test.ts b/test/abilities/oblivious.test.ts index e340d3c867d..dab8394edd0 100644 --- a/test/abilities/oblivious.test.ts +++ b/test/abilities/oblivious.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Oblivious", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/own_tempo.test.ts b/test/abilities/own_tempo.test.ts index 1d6d8aa76e5..869953b4e93 100644 --- a/test/abilities/own_tempo.test.ts +++ b/test/abilities/own_tempo.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Own Tempo", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/parental_bond.test.ts b/test/abilities/parental_bond.test.ts index 73efd0f57e2..5a3af238b70 100644 --- a/test/abilities/parental_bond.test.ts +++ b/test/abilities/parental_bond.test.ts @@ -27,7 +27,7 @@ describe("Abilities - Parental Bond", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleStyle("single"); - game.override.disableCrits(); + game.override.criticalHits(false); game.override.ability(AbilityId.PARENTAL_BOND); game.override.enemySpecies(SpeciesId.SNORLAX); game.override.enemyAbility(AbilityId.FUR_COAT); diff --git a/test/abilities/perish_body.test.ts b/test/abilities/perish_body.test.ts index 9668bf349a8..82dd53cba1f 100644 --- a/test/abilities/perish_body.test.ts +++ b/test/abilities/perish_body.test.ts @@ -22,7 +22,7 @@ describe("Abilities - Perish Song", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleStyle("single"); - game.override.disableCrits(); + game.override.criticalHits(false); game.override.enemySpecies(SpeciesId.MAGIKARP); game.override.enemyAbility(AbilityId.BALL_FETCH); diff --git a/test/abilities/protosynthesis.test.ts b/test/abilities/protosynthesis.test.ts index ba7bb5d084b..ef860fc0cd5 100644 --- a/test/abilities/protosynthesis.test.ts +++ b/test/abilities/protosynthesis.test.ts @@ -28,7 +28,7 @@ describe("Abilities - Protosynthesis", () => { .moveset([MoveId.SPLASH, MoveId.TACKLE]) .ability(AbilityId.PROTOSYNTHESIS) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/sand_spit.test.ts b/test/abilities/sand_spit.test.ts index 96e6380ae88..d7a99f99c42 100644 --- a/test/abilities/sand_spit.test.ts +++ b/test/abilities/sand_spit.test.ts @@ -23,7 +23,7 @@ describe("Abilities - Sand Spit", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleStyle("single"); - game.override.disableCrits(); + game.override.criticalHits(false); game.override.enemySpecies(SpeciesId.MAGIKARP); game.override.enemyAbility(AbilityId.BALL_FETCH); diff --git a/test/abilities/sap_sipper.test.ts b/test/abilities/sap_sipper.test.ts index 16559fb563f..c70730f0711 100644 --- a/test/abilities/sap_sipper.test.ts +++ b/test/abilities/sap_sipper.test.ts @@ -31,7 +31,7 @@ describe("Abilities - Sap Sipper", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .ability(AbilityId.SAP_SIPPER) .enemySpecies(SpeciesId.RATTATA) .enemyAbility(AbilityId.SAP_SIPPER) diff --git a/test/abilities/seed_sower.test.ts b/test/abilities/seed_sower.test.ts index 761342bfb27..e473c5786c8 100644 --- a/test/abilities/seed_sower.test.ts +++ b/test/abilities/seed_sower.test.ts @@ -23,7 +23,7 @@ describe("Abilities - Seed Sower", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleStyle("single"); - game.override.disableCrits(); + game.override.criticalHits(false); game.override.enemySpecies(SpeciesId.MAGIKARP); game.override.enemyAbility(AbilityId.BALL_FETCH); diff --git a/test/abilities/serene_grace.test.ts b/test/abilities/serene_grace.test.ts index c5c12fe217e..2acf2981537 100644 --- a/test/abilities/serene_grace.test.ts +++ b/test/abilities/serene_grace.test.ts @@ -24,7 +24,7 @@ describe("Abilities - Serene Grace", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .disableCrits() + .criticalHits(false) .battleStyle("single") .ability(AbilityId.SERENE_GRACE) .moveset([MoveId.AIR_SLASH]) diff --git a/test/abilities/sheer_force.test.ts b/test/abilities/sheer_force.test.ts index 922025d8be2..f119feb5df5 100644 --- a/test/abilities/sheer_force.test.ts +++ b/test/abilities/sheer_force.test.ts @@ -31,7 +31,7 @@ describe("Abilities - Sheer Force", () => { .enemySpecies(SpeciesId.ONIX) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset([MoveId.SPLASH]) - .disableCrits(); + .criticalHits(false); }); const SHEER_FORCE_MULT = 1.3; diff --git a/test/abilities/shell-armor.test.ts b/test/abilities/shell-armor.test.ts new file mode 100644 index 00000000000..ea0ed4a95dd --- /dev/null +++ b/test/abilities/shell-armor.test.ts @@ -0,0 +1,69 @@ +import type Move from "#app/data/moves/move"; +import Pokemon from "#app/field/pokemon"; +import { AbilityId } from "#enums/ability-id"; +import { MoveId } from "#enums/move-id"; +import { SpeciesId } from "#enums/species-id"; +import { StatusEffect } from "#enums/status-effect"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi, type MockInstance } from "vitest"; + +describe("Abilities - Shell Armor", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + let critSpy: MockInstance<(source: Pokemon, move: Move, simulated?: boolean) => boolean>; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .ability(AbilityId.SHELL_ARMOR) + .battleStyle("single") + .enemySpecies(SpeciesId.MAGIKARP) + .enemyAbility(AbilityId.BALL_FETCH) + .statusEffect(StatusEffect.POISON); + + critSpy = vi.spyOn(Pokemon.prototype, "getCriticalHitResult"); + }); + + it("should prevent natural crit rolls from suceeding", async () => { + game.override.criticalHits(true); // force random crit rolls to always succeed + await game.classicMode.startBattle([SpeciesId.ABOMASNOW]); + + game.move.use(MoveId.SPLASH); + await game.move.forceEnemyMove(MoveId.TACKLE); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(critSpy).toHaveReturnedWith(false); + }); + + it("should prevent guaranteed-crit moves from critting", async () => { + await game.classicMode.startBattle([SpeciesId.ABOMASNOW]); + + game.move.use(MoveId.SPLASH); + await game.move.forceEnemyMove(MoveId.FLOWER_TRICK); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(critSpy).toHaveReturnedWith(false); + }); + + it("should block Merciless guaranteed crits", async () => { + game.override.enemyAbility(AbilityId.MERCILESS); + await game.classicMode.startBattle([SpeciesId.ABOMASNOW]); + + game.move.use(MoveId.SPLASH); + await game.move.forceEnemyMove(MoveId.TACKLE); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(critSpy).toHaveReturnedWith(false); + }); +}); diff --git a/test/abilities/stakeout.test.ts b/test/abilities/stakeout.test.ts index ba4325e0295..b3844bf17ca 100644 --- a/test/abilities/stakeout.test.ts +++ b/test/abilities/stakeout.test.ts @@ -27,7 +27,7 @@ describe("Abilities - Stakeout", () => { .moveset([MoveId.SPLASH, MoveId.SURF]) .ability(AbilityId.STAKEOUT) .battleStyle("single") - .disableCrits() + .criticalHits(false) .startingLevel(100) .enemyLevel(100) .enemySpecies(SpeciesId.SNORLAX) diff --git a/test/abilities/stall.test.ts b/test/abilities/stall.test.ts index df40bed3e90..9d4bee3cd0a 100644 --- a/test/abilities/stall.test.ts +++ b/test/abilities/stall.test.ts @@ -24,7 +24,7 @@ describe("Abilities - Stall", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.REGIELEKI) .enemyAbility(AbilityId.STALL) .enemyMoveset(MoveId.QUICK_ATTACK) diff --git a/test/abilities/storm_drain.test.ts b/test/abilities/storm_drain.test.ts index 3a6c0aba100..8eedf0c7ce8 100644 --- a/test/abilities/storm_drain.test.ts +++ b/test/abilities/storm_drain.test.ts @@ -27,7 +27,7 @@ describe("Abilities - Storm Drain", () => { .moveset([MoveId.SPLASH, MoveId.WATER_GUN]) .ability(AbilityId.BALL_FETCH) .battleStyle("double") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/thermal_exchange.test.ts b/test/abilities/thermal_exchange.test.ts index f27e6da1d3b..70af864d413 100644 --- a/test/abilities/thermal_exchange.test.ts +++ b/test/abilities/thermal_exchange.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Thermal Exchange", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/trace.test.ts b/test/abilities/trace.test.ts index 9bfd2f021c8..f17bec159ab 100644 --- a/test/abilities/trace.test.ts +++ b/test/abilities/trace.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Trace", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.TRACE) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/victory_star.test.ts b/test/abilities/victory_star.test.ts index a15beac8b2c..4742dd96aa6 100644 --- a/test/abilities/victory_star.test.ts +++ b/test/abilities/victory_star.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Victory Star", () => { game.override .moveset([MoveId.TACKLE, MoveId.SPLASH]) .battleStyle("double") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/vital_spirit.test.ts b/test/abilities/vital_spirit.test.ts index c32454e9d31..18764f94a6b 100644 --- a/test/abilities/vital_spirit.test.ts +++ b/test/abilities/vital_spirit.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Vital Spirit", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/volt_absorb.test.ts b/test/abilities/volt_absorb.test.ts index 34dbbbd4783..e5bf4a1fe46 100644 --- a/test/abilities/volt_absorb.test.ts +++ b/test/abilities/volt_absorb.test.ts @@ -27,7 +27,7 @@ describe("Abilities - Volt Absorb", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleStyle("single"); - game.override.disableCrits(); + game.override.criticalHits(false); }); it("does not activate when CHARGE is used", async () => { diff --git a/test/abilities/wandering_spirit.test.ts b/test/abilities/wandering_spirit.test.ts index 360eedda4c9..950cec6d27c 100644 --- a/test/abilities/wandering_spirit.test.ts +++ b/test/abilities/wandering_spirit.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Wandering Spirit", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.WANDERING_SPIRIT) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.TACKLE); diff --git a/test/abilities/water_bubble.test.ts b/test/abilities/water_bubble.test.ts index 412c4a25035..455a2e368c4 100644 --- a/test/abilities/water_bubble.test.ts +++ b/test/abilities/water_bubble.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Water Bubble", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/water_veil.test.ts b/test/abilities/water_veil.test.ts index e67287d250f..2df06ec1a21 100644 --- a/test/abilities/water_veil.test.ts +++ b/test/abilities/water_veil.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Water Veil", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/abilities/wimp_out.test.ts b/test/abilities/wimp_out.test.ts index 05c848a75c0..1db0b80fcd0 100644 --- a/test/abilities/wimp_out.test.ts +++ b/test/abilities/wimp_out.test.ts @@ -39,7 +39,7 @@ describe("Abilities - Wimp Out", () => { .enemyLevel(70) .moveset([MoveId.SPLASH, MoveId.FALSE_SWIPE, MoveId.ENDURE]) .enemyMoveset(MoveId.FALSE_SWIPE) - .disableCrits(); + .criticalHits(false); }); function confirmSwitch(): void { diff --git a/test/abilities/zen_mode.test.ts b/test/abilities/zen_mode.test.ts index 163df7b1853..86ae26cbcb9 100644 --- a/test/abilities/zen_mode.test.ts +++ b/test/abilities/zen_mode.test.ts @@ -27,7 +27,7 @@ describe("Abilities - ZEN MODE", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyLevel(5) diff --git a/test/arena/grassy_terrain.test.ts b/test/arena/grassy_terrain.test.ts index 832f4400cf4..5f78d8f801d 100644 --- a/test/arena/grassy_terrain.test.ts +++ b/test/arena/grassy_terrain.test.ts @@ -23,7 +23,7 @@ describe("Arena - Grassy Terrain", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemyLevel(1) .enemySpecies(SpeciesId.SHUCKLE) .enemyAbility(AbilityId.STURDY) diff --git a/test/battle/ability_swap.test.ts b/test/battle/ability_swap.test.ts index 64446d703ac..3dd92576e3b 100644 --- a/test/battle/ability_swap.test.ts +++ b/test/battle/ability_swap.test.ts @@ -27,7 +27,7 @@ describe("Test Ability Swapping", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/battle/damage_calculation.test.ts b/test/battle/damage_calculation.test.ts index 555b3a9c554..19cdf6b9237 100644 --- a/test/battle/damage_calculation.test.ts +++ b/test/battle/damage_calculation.test.ts @@ -32,7 +32,7 @@ describe("Battle Mechanics - Damage Calculation", () => { .enemyMoveset(MoveId.SPLASH) .startingLevel(100) .enemyLevel(100) - .disableCrits() + .criticalHits(false) .moveset([MoveId.TACKLE, MoveId.DRAGON_RAGE, MoveId.FISSURE, MoveId.JUMP_KICK]); }); diff --git a/test/boss-pokemon.test.ts b/test/boss-pokemon.test.ts index fdfca9249f7..afcf5e8fa77 100644 --- a/test/boss-pokemon.test.ts +++ b/test/boss-pokemon.test.ts @@ -28,7 +28,7 @@ describe("Boss Pokemon / Shields", () => { game.override .battleStyle("single") .disableTrainerWaves() - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.RATTATA) .enemyMoveset(MoveId.SPLASH) .enemyHeldItems([]) diff --git a/test/data/status_effect.test.ts b/test/data/status_effect.test.ts index 06e11dfeb76..acc96c532bd 100644 --- a/test/data/status_effect.test.ts +++ b/test/data/status_effect.test.ts @@ -359,7 +359,7 @@ describe("Status Effects", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); @@ -415,7 +415,7 @@ describe("Status Effects", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.NUZZLE) diff --git a/test/endless_boss.test.ts b/test/endless_boss.test.ts index 6814cf5e12a..d219cacf317 100644 --- a/test/endless_boss.test.ts +++ b/test/endless_boss.test.ts @@ -21,7 +21,7 @@ describe("Endless Boss", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.startingBiome(BiomeId.END).disableCrits(); + game.override.startingBiome(BiomeId.END).criticalHits(false); }); afterEach(() => { diff --git a/test/final_boss.test.ts b/test/final_boss.test.ts index d3fcd3214bb..071f83285e7 100644 --- a/test/final_boss.test.ts +++ b/test/final_boss.test.ts @@ -27,7 +27,7 @@ describe("Final Boss", () => { game.override .startingWave(FinalWave.Classic) .startingBiome(BiomeId.END) - .disableCrits() + .criticalHits(false) .enemyMoveset(MoveId.SPLASH) .moveset([MoveId.SPLASH, MoveId.WILL_O_WISP, MoveId.DRAGON_PULSE]) .startingLevel(10000); diff --git a/test/items/multi_lens.test.ts b/test/items/multi_lens.test.ts index 11e4c04ec21..8a3161970c0 100644 --- a/test/items/multi_lens.test.ts +++ b/test/items/multi_lens.test.ts @@ -28,7 +28,7 @@ describe("Items - Multi Lens", () => { .ability(AbilityId.BALL_FETCH) .startingHeldItems([{ name: "MULTI_LENS" }]) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.SNORLAX) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH) diff --git a/test/items/reviver_seed.test.ts b/test/items/reviver_seed.test.ts index 54927130869..f444a6eac66 100644 --- a/test/items/reviver_seed.test.ts +++ b/test/items/reviver_seed.test.ts @@ -29,7 +29,7 @@ describe("Items - Reviver Seed", () => { .moveset([MoveId.SPLASH, MoveId.TACKLE, MoveId.ENDURE]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .startingHeldItems([{ name: "REVIVER_SEED" }]) diff --git a/test/moves/alluring_voice.test.ts b/test/moves/alluring_voice.test.ts index 132f83cd4c1..ba096391f1b 100644 --- a/test/moves/alluring_voice.test.ts +++ b/test/moves/alluring_voice.test.ts @@ -26,7 +26,7 @@ describe("Moves - Alluring Voice", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.ICE_SCALES) .enemyMoveset(MoveId.HOWL) diff --git a/test/moves/assist.test.ts b/test/moves/assist.test.ts index bc51f8bd06a..27aa5528f17 100644 --- a/test/moves/assist.test.ts +++ b/test/moves/assist.test.ts @@ -30,7 +30,7 @@ describe("Moves - Assist", () => { game.override .ability(AbilityId.BALL_FETCH) .battleStyle("double") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyLevel(100) .enemyAbility(AbilityId.BALL_FETCH) diff --git a/test/moves/aurora_veil.test.ts b/test/moves/aurora_veil.test.ts index 98b490b0e32..b9ae79e4155 100644 --- a/test/moves/aurora_veil.test.ts +++ b/test/moves/aurora_veil.test.ts @@ -42,7 +42,7 @@ describe("Moves - Aurora Veil", () => { .enemyLevel(100) .enemySpecies(SpeciesId.MAGIKARP) .enemyMoveset(MoveId.AURORA_VEIL) - .disableCrits() + .criticalHits(false) .weather(WeatherType.HAIL); }); diff --git a/test/moves/baton_pass.test.ts b/test/moves/baton_pass.test.ts index f6256e95ce8..ca4e6633e80 100644 --- a/test/moves/baton_pass.test.ts +++ b/test/moves/baton_pass.test.ts @@ -31,7 +31,7 @@ describe("Moves - Baton Pass", () => { .moveset([MoveId.BATON_PASS, MoveId.NASTY_PLOT, MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH) - .disableCrits(); + .criticalHits(false); }); it("transfers all stat stages when player uses it", async () => { diff --git a/test/moves/burning_jealousy.test.ts b/test/moves/burning_jealousy.test.ts index 9e1898d9cd1..ce0a1ce57c9 100644 --- a/test/moves/burning_jealousy.test.ts +++ b/test/moves/burning_jealousy.test.ts @@ -26,7 +26,7 @@ describe("Moves - Burning Jealousy", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.ICE_SCALES) .enemyMoveset([MoveId.HOWL]) diff --git a/test/moves/camouflage.test.ts b/test/moves/camouflage.test.ts index 03364265179..6f28493b1e5 100644 --- a/test/moves/camouflage.test.ts +++ b/test/moves/camouflage.test.ts @@ -28,7 +28,7 @@ describe("Moves - Camouflage", () => { .moveset([MoveId.CAMOUFLAGE]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.REGIELEKI) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.PSYCHIC_TERRAIN); diff --git a/test/moves/chloroblast.test.ts b/test/moves/chloroblast.test.ts index cf5e791d0b9..6c790bac150 100644 --- a/test/moves/chloroblast.test.ts +++ b/test/moves/chloroblast.test.ts @@ -25,7 +25,7 @@ describe("Moves - Chloroblast", () => { game.override .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH); }); diff --git a/test/moves/copycat.test.ts b/test/moves/copycat.test.ts index 1691cc1478c..73875701362 100644 --- a/test/moves/copycat.test.ts +++ b/test/moves/copycat.test.ts @@ -33,7 +33,7 @@ describe("Moves - Copycat", () => { .moveset([MoveId.COPYCAT, MoveId.SPIKY_SHIELD, MoveId.SWORDS_DANCE, MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .starterSpecies(SpeciesId.FEEBAS) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) diff --git a/test/moves/defog.test.ts b/test/moves/defog.test.ts index d42682c7f3f..17dc0613e9b 100644 --- a/test/moves/defog.test.ts +++ b/test/moves/defog.test.ts @@ -26,7 +26,7 @@ describe("Moves - Defog", () => { .moveset([MoveId.MIST, MoveId.SAFEGUARD, MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.SHUCKLE) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset([MoveId.DEFOG, MoveId.GROWL]); diff --git a/test/moves/doodle.test.ts b/test/moves/doodle.test.ts index d4d09b3a195..2dbd5c08c8f 100644 --- a/test/moves/doodle.test.ts +++ b/test/moves/doodle.test.ts @@ -27,7 +27,7 @@ describe("Moves - Doodle", () => { .moveset([MoveId.SPLASH, MoveId.DOODLE]) .ability(AbilityId.ADAPTABILITY) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/double_team.test.ts b/test/moves/double_team.test.ts index 9a17a542f47..d1f6c5be3e4 100644 --- a/test/moves/double_team.test.ts +++ b/test/moves/double_team.test.ts @@ -26,7 +26,7 @@ describe("Moves - Double Team", () => { game.override .battleStyle("single") .moveset([MoveId.DOUBLE_TEAM]) - .disableCrits() + .criticalHits(false) .ability(AbilityId.BALL_FETCH) .enemySpecies(SpeciesId.SHUCKLE) .enemyAbility(AbilityId.BALL_FETCH) diff --git a/test/moves/dragon_rage.test.ts b/test/moves/dragon_rage.test.ts index c2a0a1bc979..7ebac7bd345 100644 --- a/test/moves/dragon_rage.test.ts +++ b/test/moves/dragon_rage.test.ts @@ -52,7 +52,7 @@ describe("Moves - Dragon Rage", () => { }); it("ignores weaknesses", async () => { - game.override.disableCrits(); + game.override.criticalHits(false); vi.spyOn(enemyPokemon, "getTypes").mockReturnValue([PokemonType.DRAGON]); game.move.select(MoveId.DRAGON_RAGE); @@ -62,7 +62,7 @@ describe("Moves - Dragon Rage", () => { }); it("ignores resistances", async () => { - game.override.disableCrits(); + game.override.criticalHits(false); vi.spyOn(enemyPokemon, "getTypes").mockReturnValue([PokemonType.STEEL]); game.move.select(MoveId.DRAGON_RAGE); @@ -72,7 +72,7 @@ describe("Moves - Dragon Rage", () => { }); it("ignores SPATK stat stages", async () => { - game.override.disableCrits(); + game.override.criticalHits(false); partyPokemon.setStatStage(Stat.SPATK, 2); game.move.select(MoveId.DRAGON_RAGE); @@ -82,7 +82,7 @@ describe("Moves - Dragon Rage", () => { }); it("ignores stab", async () => { - game.override.disableCrits(); + game.override.criticalHits(false); vi.spyOn(partyPokemon, "getTypes").mockReturnValue([PokemonType.DRAGON]); game.move.select(MoveId.DRAGON_RAGE); @@ -101,7 +101,7 @@ describe("Moves - Dragon Rage", () => { }); it("ignores damage modification from abilities, for example ICE_SCALES", async () => { - game.override.disableCrits(); + game.override.criticalHits(false); game.override.enemyAbility(AbilityId.ICE_SCALES); game.move.select(MoveId.DRAGON_RAGE); diff --git a/test/moves/dynamax_cannon.test.ts b/test/moves/dynamax_cannon.test.ts index 2cdba48c0ea..e02153910f5 100644 --- a/test/moves/dynamax_cannon.test.ts +++ b/test/moves/dynamax_cannon.test.ts @@ -32,20 +32,12 @@ describe("Moves - Dynamax Cannon", () => { game.override .moveset(MoveId.DYNAMAX_CANNON) .startingLevel(200) - .levelCap(10) + .levelCap(100) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyMoveset(MoveId.SPLASH); - // Note that, for Waves 1-10, the level cap is 10 - game.override.startingWave(1); - game.override.battleStyle("single"); - game.override.disableCrits(); - - game.override.enemySpecies(SpeciesId.MAGIKARP); - game.override.enemyMoveset([MoveId.SPLASH, MoveId.SPLASH, MoveId.SPLASH, MoveId.SPLASH]); - vi.spyOn(dynamaxCannon, "calculateBattlePower"); }); @@ -62,7 +54,7 @@ describe("Moves - Dynamax Cannon", () => { }, 20000); it("should return 100 power against an enemy at level cap", async () => { - game.override.enemyLevel(10); + game.override.enemyLevel(100); await game.classicMode.startBattle([SpeciesId.ETERNATUS]); game.move.select(dynamaxCannon.id); diff --git a/test/moves/encore.test.ts b/test/moves/encore.test.ts index 120d065d528..772b7c96060 100644 --- a/test/moves/encore.test.ts +++ b/test/moves/encore.test.ts @@ -28,7 +28,7 @@ describe("Moves - Encore", () => { .moveset([MoveId.SPLASH, MoveId.ENCORE]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset([MoveId.SPLASH, MoveId.TACKLE]) diff --git a/test/moves/endure.test.ts b/test/moves/endure.test.ts index 799be22ba45..7738f7426fe 100644 --- a/test/moves/endure.test.ts +++ b/test/moves/endure.test.ts @@ -26,7 +26,7 @@ describe("Moves - Endure", () => { .ability(AbilityId.SKILL_LINK) .startingLevel(100) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.NO_GUARD) .enemyMoveset(MoveId.ENDURE); diff --git a/test/moves/entrainment.test.ts b/test/moves/entrainment.test.ts index 0a0cbd3b5f9..65586149492 100644 --- a/test/moves/entrainment.test.ts +++ b/test/moves/entrainment.test.ts @@ -26,7 +26,7 @@ describe("Moves - Entrainment", () => { .moveset([MoveId.SPLASH, MoveId.ENTRAINMENT]) .ability(AbilityId.ADAPTABILITY) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/fairy_lock.test.ts b/test/moves/fairy_lock.test.ts index 74524d67b38..b9f854cdc93 100644 --- a/test/moves/fairy_lock.test.ts +++ b/test/moves/fairy_lock.test.ts @@ -27,7 +27,7 @@ describe("Moves - Fairy Lock", () => { .moveset([MoveId.FAIRY_LOCK, MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("double") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset([MoveId.SPLASH, MoveId.U_TURN]); diff --git a/test/moves/fake_out.test.ts b/test/moves/fake_out.test.ts index 95f69fe792e..4fc83e5aa07 100644 --- a/test/moves/fake_out.test.ts +++ b/test/moves/fake_out.test.ts @@ -27,7 +27,7 @@ describe("Moves - Fake Out", () => { .enemyMoveset(MoveId.SPLASH) .enemyLevel(10) .startingLevel(1) // prevent LevelUpPhase from happening - .disableCrits(); + .criticalHits(false); }); it("should only work the first turn a pokemon is sent out in a battle", async () => { diff --git a/test/moves/false_swipe.test.ts b/test/moves/false_swipe.test.ts index c98b76f1ef1..bf9c8307c22 100644 --- a/test/moves/false_swipe.test.ts +++ b/test/moves/false_swipe.test.ts @@ -27,7 +27,7 @@ describe("Moves - False Swipe", () => { .ability(AbilityId.BALL_FETCH) .startingLevel(1000) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/fell_stinger.test.ts b/test/moves/fell_stinger.test.ts index d5081a3ba30..0737db9105f 100644 --- a/test/moves/fell_stinger.test.ts +++ b/test/moves/fell_stinger.test.ts @@ -30,7 +30,7 @@ describe("Moves - Fell Stinger", () => { .battleStyle("single") .moveset([MoveId.FELL_STINGER, MoveId.SALT_CURE, MoveId.BIND, MoveId.LEECH_SEED]) .startingLevel(50) - .disableCrits() + .criticalHits(false) .enemyAbility(AbilityId.STURDY) .enemySpecies(SpeciesId.HYPNO) .enemyMoveset(MoveId.SPLASH) diff --git a/test/moves/fissure.test.ts b/test/moves/fissure.test.ts index 53327b505c4..090a657c0f7 100644 --- a/test/moves/fissure.test.ts +++ b/test/moves/fissure.test.ts @@ -29,7 +29,7 @@ describe("Moves - Fissure", () => { game = new GameManager(phaserGame); game.override.battleStyle("single"); - game.override.disableCrits(); + game.override.criticalHits(false); game.override.starterSpecies(SpeciesId.SNORLAX); game.override.moveset([MoveId.FISSURE]); diff --git a/test/moves/flame_burst.test.ts b/test/moves/flame_burst.test.ts index 1d61daaacb5..8bf43faf093 100644 --- a/test/moves/flame_burst.test.ts +++ b/test/moves/flame_burst.test.ts @@ -37,7 +37,7 @@ describe("Moves - Flame Burst", () => { game = new GameManager(phaserGame); game.override.battleStyle("double"); game.override.moveset([MoveId.FLAME_BURST, MoveId.SPLASH]); - game.override.disableCrits(); + game.override.criticalHits(false); game.override.ability(AbilityId.UNNERVE); game.override.startingWave(4); game.override.enemySpecies(SpeciesId.SHUCKLE); diff --git a/test/moves/foresight.test.ts b/test/moves/foresight.test.ts index a30b4d6a444..96a341582f9 100644 --- a/test/moves/foresight.test.ts +++ b/test/moves/foresight.test.ts @@ -22,7 +22,7 @@ describe("Moves - Foresight", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.GASTLY) .enemyMoveset(MoveId.SPLASH) .enemyLevel(5) diff --git a/test/moves/forests_curse.test.ts b/test/moves/forests_curse.test.ts index 77fec5d277d..81ced674a33 100644 --- a/test/moves/forests_curse.test.ts +++ b/test/moves/forests_curse.test.ts @@ -26,7 +26,7 @@ describe("Moves - Forest's Curse", () => { .moveset([MoveId.FORESTS_CURSE, MoveId.TRICK_OR_TREAT]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/fusion_bolt.test.ts b/test/moves/fusion_bolt.test.ts index a5263bfa364..03aa540c944 100644 --- a/test/moves/fusion_bolt.test.ts +++ b/test/moves/fusion_bolt.test.ts @@ -31,7 +31,7 @@ describe("Moves - Fusion Bolt", () => { .enemyMoveset(MoveId.SPLASH) .battleStyle("single") .startingWave(97) - .disableCrits(); + .criticalHits(false); }); it("should not make contact", async () => { diff --git a/test/moves/fusion_flare.test.ts b/test/moves/fusion_flare.test.ts index df6d390686f..c0df347fcce 100644 --- a/test/moves/fusion_flare.test.ts +++ b/test/moves/fusion_flare.test.ts @@ -31,7 +31,7 @@ describe("Moves - Fusion Flare", () => { .enemyMoveset(MoveId.REST) .battleStyle("single") .startingWave(97) - .disableCrits(); + .criticalHits(false); }); it("should thaw freeze status condition", async () => { diff --git a/test/moves/fusion_flare_bolt.test.ts b/test/moves/fusion_flare_bolt.test.ts index f10ede8717c..4535d518cf6 100644 --- a/test/moves/fusion_flare_bolt.test.ts +++ b/test/moves/fusion_flare_bolt.test.ts @@ -40,7 +40,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { .enemyMoveset(MoveId.REST) .battleStyle("double") .startingWave(97) - .disableCrits(); + .criticalHits(false); vi.spyOn(fusionFlare, "calculateBattlePower"); vi.spyOn(fusionBolt, "calculateBattlePower"); diff --git a/test/moves/gigaton_hammer.test.ts b/test/moves/gigaton_hammer.test.ts index be7adf53aa7..908a697e0df 100644 --- a/test/moves/gigaton_hammer.test.ts +++ b/test/moves/gigaton_hammer.test.ts @@ -29,7 +29,7 @@ describe("Moves - Gigaton Hammer", () => { .startingLevel(10) .enemyLevel(100) .enemyMoveset(MoveId.SPLASH) - .disableCrits(); + .criticalHits(false); }); it("can't be used two turns in a row", async () => { diff --git a/test/moves/glaive_rush.test.ts b/test/moves/glaive_rush.test.ts index 768c4a691b0..9cc2be3fcdc 100644 --- a/test/moves/glaive_rush.test.ts +++ b/test/moves/glaive_rush.test.ts @@ -24,7 +24,7 @@ describe("Moves - Glaive Rush", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset([MoveId.GLAIVE_RUSH]) diff --git a/test/moves/grudge.test.ts b/test/moves/grudge.test.ts index 63018a419e3..36030c88bad 100644 --- a/test/moves/grudge.test.ts +++ b/test/moves/grudge.test.ts @@ -26,7 +26,7 @@ describe("Moves - Grudge", () => { .moveset([MoveId.EMBER, MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.SHEDINJA) .enemyAbility(AbilityId.WONDER_GUARD) .enemyMoveset([MoveId.GRUDGE, MoveId.SPLASH]); diff --git a/test/moves/heal_block.test.ts b/test/moves/heal_block.test.ts index 39e8efea827..77a10927930 100644 --- a/test/moves/heal_block.test.ts +++ b/test/moves/heal_block.test.ts @@ -33,7 +33,7 @@ describe("Moves - Heal Block", () => { .ability(AbilityId.NO_GUARD) .enemyAbility(AbilityId.BALL_FETCH) .enemySpecies(SpeciesId.BLISSEY) - .disableCrits(); + .criticalHits(false); }); it("shouldn't stop damage from HP-drain attacks, just HP restoration", async () => { diff --git a/test/moves/instruct.test.ts b/test/moves/instruct.test.ts index 74de4c5da17..261f55f4684 100644 --- a/test/moves/instruct.test.ts +++ b/test/moves/instruct.test.ts @@ -40,7 +40,7 @@ describe("Moves - Instruct", () => { .passiveAbility(AbilityId.NO_GUARD) .enemyLevel(100) .startingLevel(100) - .disableCrits(); + .criticalHits(false); }); it("should repeat target's last used move", async () => { diff --git a/test/moves/jaw_lock.test.ts b/test/moves/jaw_lock.test.ts index e0815a4c3c9..4e103c14f98 100644 --- a/test/moves/jaw_lock.test.ts +++ b/test/moves/jaw_lock.test.ts @@ -36,7 +36,7 @@ describe("Moves - Jaw Lock", () => { .moveset([MoveId.JAW_LOCK, MoveId.SPLASH]) .startingLevel(100) .enemyLevel(100) - .disableCrits(); + .criticalHits(false); }); it("should trap the move's user and target", async () => { diff --git a/test/moves/lash_out.test.ts b/test/moves/lash_out.test.ts index c0c0881b340..33a58914978 100644 --- a/test/moves/lash_out.test.ts +++ b/test/moves/lash_out.test.ts @@ -25,7 +25,7 @@ describe("Moves - Lash Out", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.FUR_COAT) .enemyMoveset([MoveId.GROWL]) diff --git a/test/moves/last-resort.test.ts b/test/moves/last-resort.test.ts index e4b8346053b..79e38fb5f8d 100644 --- a/test/moves/last-resort.test.ts +++ b/test/moves/last-resort.test.ts @@ -34,7 +34,7 @@ describe("Moves - Last Resort", () => { game.override .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/last_respects.test.ts b/test/moves/last_respects.test.ts index b2eb4c6695b..fa66e256ccd 100644 --- a/test/moves/last_respects.test.ts +++ b/test/moves/last_respects.test.ts @@ -32,7 +32,7 @@ describe("Moves - Last Respects", () => { basePower = move.power; game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .moveset([MoveId.LAST_RESPECTS, MoveId.EXPLOSION, MoveId.LUNAR_DANCE]) .ability(AbilityId.BALL_FETCH) .enemyAbility(AbilityId.BALL_FETCH) diff --git a/test/moves/light_screen.test.ts b/test/moves/light_screen.test.ts index 404d30920c7..8c436aacf6a 100644 --- a/test/moves/light_screen.test.ts +++ b/test/moves/light_screen.test.ts @@ -41,7 +41,7 @@ describe("Moves - Light Screen", () => { .enemyLevel(100) .enemySpecies(SpeciesId.MAGIKARP) .enemyMoveset(MoveId.LIGHT_SCREEN) - .disableCrits(); + .criticalHits(false); }); it("reduces damage of special attacks by half in a single battle", async () => { diff --git a/test/moves/lucky_chant.test.ts b/test/moves/lucky_chant.test.ts index 58944027398..a57d231134b 100644 --- a/test/moves/lucky_chant.test.ts +++ b/test/moves/lucky_chant.test.ts @@ -1,11 +1,10 @@ import { AbilityId } from "#enums/ability-id"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; +import { BattlerTagType } from "#enums/battler-tag-type"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; -import { BerryPhase } from "#app/phases/berry-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import GameManager from "#test/testUtils/gameManager"; +import { BattlerIndex } from "#enums/battler-index"; describe("Moves - Lucky Chant", () => { let phaserGame: Phaser.Game; @@ -29,74 +28,91 @@ describe("Moves - Lucky Chant", () => { .moveset([MoveId.LUCKY_CHANT, MoveId.SPLASH, MoveId.FOLLOW_ME]) .enemySpecies(SpeciesId.SNORLAX) .enemyAbility(AbilityId.INSOMNIA) - .enemyMoveset([MoveId.FLOWER_TRICK]) + .enemyMoveset(MoveId.TACKLE) .startingLevel(100) .enemyLevel(100); }); - it("should prevent critical hits from moves", async () => { + it("should prevent random critical hits from moves", async () => { + game.override.criticalHits(true); await game.classicMode.startBattle([SpeciesId.CHARIZARD]); - const playerPokemon = game.scene.getPlayerPokemon()!; + const charizard = game.scene.getPlayerPokemon()!; + expect(charizard).toBeDefined(); + const critSpy = vi.spyOn(charizard, "getCriticalHitResult"); // called on the defender (ie player) game.move.select(MoveId.SPLASH); + await game.phaseInterceptor.to("TurnEndPhase"); - await game.phaseInterceptor.to(TurnEndPhase); - - const firstTurnDamage = playerPokemon.getMaxHp() - playerPokemon.hp; + expect(critSpy).toHaveLastReturnedWith(true); + const firstTurnDamage = charizard.getInverseHp(); game.move.select(MoveId.LUCKY_CHANT); + await game.phaseInterceptor.to("TurnEndPhase"); - await game.phaseInterceptor.to(BerryPhase, false); + expect(critSpy).toHaveLastReturnedWith(false); + const secondTurnDamage = charizard.getInverseHp() - firstTurnDamage; + expect(secondTurnDamage).toBeLessThan(firstTurnDamage); + }); - const secondTurnDamage = playerPokemon.getMaxHp() - playerPokemon.hp - firstTurnDamage; + it("should prevent guaranteed critical hits from moves", async () => { + game.override.enemyMoveset(MoveId.FLOWER_TRICK); + await game.classicMode.startBattle([SpeciesId.CHARIZARD]); + + const charizard = game.scene.getPlayerPokemon()!; + expect(charizard).toBeDefined(); + + game.move.select(MoveId.SPLASH); + await game.phaseInterceptor.to("TurnEndPhase"); + + const firstTurnDamage = charizard.getInverseHp(); + + game.move.select(MoveId.LUCKY_CHANT); + await game.phaseInterceptor.to("TurnEndPhase"); + + const secondTurnDamage = charizard.getInverseHp() - firstTurnDamage; expect(secondTurnDamage).toBeLessThan(firstTurnDamage); }); it("should prevent critical hits against the user's ally", async () => { - game.override.battleStyle("double"); + game.override.battleStyle("double").criticalHits(true); await game.classicMode.startBattle([SpeciesId.CHARIZARD, SpeciesId.BLASTOISE]); - const playerPokemon = game.scene.getPlayerField(); + const charizard = game.scene.getPlayerPokemon()!; + expect(charizard).toBeDefined(); - game.move.select(MoveId.FOLLOW_ME); - game.move.select(MoveId.SPLASH, 1); + game.move.select(MoveId.FOLLOW_ME, BattlerIndex.PLAYER); + game.move.select(MoveId.SPLASH, BattlerIndex.PLAYER_2); + await game.phaseInterceptor.to("TurnEndPhase"); - await game.phaseInterceptor.to(TurnEndPhase); + const firstTurnDamage = charizard.getInverseHp(); - const firstTurnDamage = playerPokemon[0].getMaxHp() - playerPokemon[0].hp; + game.move.select(MoveId.FOLLOW_ME, BattlerIndex.PLAYER); + game.move.select(MoveId.LUCKY_CHANT, BattlerIndex.PLAYER_2); - game.move.select(MoveId.FOLLOW_ME); - game.move.select(MoveId.LUCKY_CHANT, 1); + await game.phaseInterceptor.to("TurnEndPhase"); - await game.phaseInterceptor.to(BerryPhase, false); - - const secondTurnDamage = playerPokemon[0].getMaxHp() - playerPokemon[0].hp - firstTurnDamage; + const secondTurnDamage = charizard.getInverseHp() - firstTurnDamage; expect(secondTurnDamage).toBeLessThan(firstTurnDamage); }); it("should prevent critical hits from field effects", async () => { - game.override.enemyMoveset([MoveId.TACKLE]); - await game.classicMode.startBattle([SpeciesId.CHARIZARD]); - const playerPokemon = game.scene.getPlayerPokemon()!; - const enemyPokemon = game.scene.getEnemyPokemon()!; - - enemyPokemon.addTag(BattlerTagType.ALWAYS_CRIT, 2, MoveId.NONE, 0); + const charizard = game.field.getPlayerPokemon(); + const snorlax = game.field.getEnemyPokemon(); + snorlax.addTag(BattlerTagType.ALWAYS_CRIT, 2, MoveId.NONE, 0); game.move.select(MoveId.SPLASH); + await game.phaseInterceptor.to("TurnEndPhase"); - await game.phaseInterceptor.to(TurnEndPhase); - - const firstTurnDamage = playerPokemon.getMaxHp() - playerPokemon.hp; + const firstTurnDamage = charizard.getInverseHp(); game.move.select(MoveId.LUCKY_CHANT); + await game.phaseInterceptor.to("TurnEndPhase"); - await game.phaseInterceptor.to(BerryPhase, false); - - const secondTurnDamage = playerPokemon.getMaxHp() - playerPokemon.hp - firstTurnDamage; + const secondTurnDamage = charizard.getInverseHp() - firstTurnDamage; expect(secondTurnDamage).toBeLessThan(firstTurnDamage); }); }); diff --git a/test/moves/magic_coat.test.ts b/test/moves/magic_coat.test.ts index a20aaf38043..7d2886c476a 100644 --- a/test/moves/magic_coat.test.ts +++ b/test/moves/magic_coat.test.ts @@ -31,7 +31,7 @@ describe("Moves - Magic Coat", () => { game.override .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.MAGIC_COAT); diff --git a/test/moves/magnet_rise.test.ts b/test/moves/magnet_rise.test.ts index 16f449899ef..2f760b83695 100644 --- a/test/moves/magnet_rise.test.ts +++ b/test/moves/magnet_rise.test.ts @@ -28,7 +28,7 @@ describe("Moves - Magnet Rise", () => { .starterSpecies(SpeciesId.MAGNEZONE) .enemySpecies(SpeciesId.RATTATA) .enemyMoveset(MoveId.DRILL_RUN) - .disableCrits() + .criticalHits(false) .enemyLevel(1) .moveset([moveToUse, MoveId.SPLASH, MoveId.GRAVITY, MoveId.BATON_PASS]); }); diff --git a/test/moves/metal_burst.test.ts b/test/moves/metal_burst.test.ts index bcb9d938985..4d07d59c16d 100644 --- a/test/moves/metal_burst.test.ts +++ b/test/moves/metal_burst.test.ts @@ -28,7 +28,7 @@ describe("Moves - Metal Burst", () => { .ability(AbilityId.PURE_POWER) .startingLevel(10) .battleStyle("double") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.PICHU) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.TACKLE); diff --git a/test/moves/miracle_eye.test.ts b/test/moves/miracle_eye.test.ts index 1238ae6a650..9281931621f 100644 --- a/test/moves/miracle_eye.test.ts +++ b/test/moves/miracle_eye.test.ts @@ -23,7 +23,7 @@ describe("Moves - Miracle Eye", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.UMBREON) .enemyMoveset(MoveId.SPLASH) .enemyLevel(5) diff --git a/test/moves/mirror_move.test.ts b/test/moves/mirror_move.test.ts index fe40402e5a2..03de93c56dc 100644 --- a/test/moves/mirror_move.test.ts +++ b/test/moves/mirror_move.test.ts @@ -28,7 +28,7 @@ describe("Moves - Mirror Move", () => { .moveset([MoveId.MIRROR_MOVE, MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/mist.test.ts b/test/moves/mist.test.ts index ea4eb95a1eb..4191aae0a46 100644 --- a/test/moves/mist.test.ts +++ b/test/moves/mist.test.ts @@ -26,7 +26,7 @@ describe("Moves - Mist", () => { .moveset([MoveId.MIST, MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("double") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.SNORLAX) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.GROWL); diff --git a/test/moves/moongeist_beam.test.ts b/test/moves/moongeist_beam.test.ts index 28bd3f70daa..367fe67cff5 100644 --- a/test/moves/moongeist_beam.test.ts +++ b/test/moves/moongeist_beam.test.ts @@ -27,7 +27,7 @@ describe("Moves - Moongeist Beam", () => { .ability(AbilityId.BALL_FETCH) .startingLevel(200) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.STURDY) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/multi_target.test.ts b/test/moves/multi_target.test.ts index 139b669da7b..bc6b24c474d 100644 --- a/test/moves/multi_target.test.ts +++ b/test/moves/multi_target.test.ts @@ -24,7 +24,7 @@ describe("Multi-target damage reduction", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .disableCrits() + .criticalHits(false) .battleStyle("double") .enemyLevel(100) .startingLevel(100) diff --git a/test/moves/order_up.test.ts b/test/moves/order_up.test.ts index adf37c0719e..fc505809fe6 100644 --- a/test/moves/order_up.test.ts +++ b/test/moves/order_up.test.ts @@ -30,7 +30,7 @@ describe("Moves - Order Up", () => { .moveset(MoveId.ORDER_UP) .ability(AbilityId.COMMANDER) .battleStyle("double") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.SNORLAX) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH) diff --git a/test/moves/pollen_puff.test.ts b/test/moves/pollen_puff.test.ts index e6dcd2c41d0..cd0a138e96c 100644 --- a/test/moves/pollen_puff.test.ts +++ b/test/moves/pollen_puff.test.ts @@ -26,7 +26,7 @@ describe("Moves - Pollen Puff", () => { .moveset([MoveId.POLLEN_PUFF]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/psycho_shift.test.ts b/test/moves/psycho_shift.test.ts index f92eea5fd38..e4eb2bd8ef6 100644 --- a/test/moves/psycho_shift.test.ts +++ b/test/moves/psycho_shift.test.ts @@ -27,7 +27,7 @@ describe("Moves - Psycho Shift", () => { .ability(AbilityId.BALL_FETCH) .statusEffect(StatusEffect.POISON) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyLevel(20) .enemyAbility(AbilityId.SYNCHRONIZE) diff --git a/test/moves/reflect.test.ts b/test/moves/reflect.test.ts index 5e10de42a3c..ef8c80070bf 100644 --- a/test/moves/reflect.test.ts +++ b/test/moves/reflect.test.ts @@ -41,7 +41,7 @@ describe("Moves - Reflect", () => { .enemyLevel(100) .enemySpecies(SpeciesId.MAGIKARP) .enemyMoveset(MoveId.REFLECT) - .disableCrits(); + .criticalHits(false); }); it("reduces damage of physical attacks by half in a single battle", async () => { diff --git a/test/moves/reflect_type.test.ts b/test/moves/reflect_type.test.ts index 86c70ed62f1..0915069764c 100644 --- a/test/moves/reflect_type.test.ts +++ b/test/moves/reflect_type.test.ts @@ -22,7 +22,11 @@ describe("Moves - Reflect Type", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.ability(AbilityId.BALL_FETCH).battleStyle("single").disableCrits().enemyAbility(AbilityId.BALL_FETCH); + game.override + .ability(AbilityId.BALL_FETCH) + .battleStyle("single") + .criticalHits(false) + .enemyAbility(AbilityId.BALL_FETCH); }); it("will make the user Normal/Grass if targetting a typeless Pokemon affected by Forest's Curse", async () => { diff --git a/test/moves/retaliate.test.ts b/test/moves/retaliate.test.ts index 16261c71dc3..dd5029a7c83 100644 --- a/test/moves/retaliate.test.ts +++ b/test/moves/retaliate.test.ts @@ -32,7 +32,7 @@ describe("Moves - Retaliate", () => { .enemyLevel(100) .moveset([MoveId.RETALIATE, MoveId.SPLASH]) .startingLevel(80) - .disableCrits(); + .criticalHits(false); }); it("increases power if ally died previous turn", async () => { diff --git a/test/moves/revival_blessing.test.ts b/test/moves/revival_blessing.test.ts index f22c0467378..1f2ba869e4f 100644 --- a/test/moves/revival_blessing.test.ts +++ b/test/moves/revival_blessing.test.ts @@ -28,7 +28,7 @@ describe("Moves - Revival Blessing", () => { .moveset([MoveId.SPLASH, MoveId.REVIVAL_BLESSING, MoveId.MEMENTO]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/role_play.test.ts b/test/moves/role_play.test.ts index 3c3f0afb1a3..cfa38ed38b7 100644 --- a/test/moves/role_play.test.ts +++ b/test/moves/role_play.test.ts @@ -26,7 +26,7 @@ describe("Moves - Role Play", () => { .moveset([MoveId.SPLASH, MoveId.ROLE_PLAY]) .ability(AbilityId.ADAPTABILITY) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/rollout.test.ts b/test/moves/rollout.test.ts index de990a1a750..4a136bc0908 100644 --- a/test/moves/rollout.test.ts +++ b/test/moves/rollout.test.ts @@ -23,7 +23,7 @@ describe("Moves - Rollout", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.disableCrits(); + game.override.criticalHits(false); game.override.battleStyle("single"); game.override.starterSpecies(SpeciesId.RATTATA); game.override.ability(AbilityId.BALL_FETCH); diff --git a/test/moves/round.test.ts b/test/moves/round.test.ts index 630137b7dce..8e07a819131 100644 --- a/test/moves/round.test.ts +++ b/test/moves/round.test.ts @@ -28,7 +28,7 @@ describe("Moves - Round", () => { .moveset([MoveId.SPLASH, MoveId.ROUND]) .ability(AbilityId.BALL_FETCH) .battleStyle("double") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset([MoveId.SPLASH, MoveId.ROUND]) diff --git a/test/moves/scale_shot.test.ts b/test/moves/scale_shot.test.ts index a5872579003..e2c86091378 100644 --- a/test/moves/scale_shot.test.ts +++ b/test/moves/scale_shot.test.ts @@ -31,7 +31,7 @@ describe("Moves - Scale Shot", () => { game.override .moveset([MoveId.SCALE_SHOT]) .battleStyle("single") - .disableCrits() + .criticalHits(false) .ability(AbilityId.NO_GUARD) .passiveAbility(AbilityId.SKILL_LINK) .enemyMoveset(MoveId.SPLASH) diff --git a/test/moves/secret_power.test.ts b/test/moves/secret_power.test.ts index 39498782b58..adb91162ae8 100644 --- a/test/moves/secret_power.test.ts +++ b/test/moves/secret_power.test.ts @@ -33,7 +33,7 @@ describe("Moves - Secret Power", () => { .moveset([MoveId.SECRET_POWER]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyLevel(60) .enemyAbility(AbilityId.BALL_FETCH); diff --git a/test/moves/simple_beam.test.ts b/test/moves/simple_beam.test.ts index 94609c3c4ac..f8549944ed9 100644 --- a/test/moves/simple_beam.test.ts +++ b/test/moves/simple_beam.test.ts @@ -25,7 +25,7 @@ describe("Moves - Simple Beam", () => { .moveset([MoveId.SPLASH, MoveId.SIMPLE_BEAM]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/sketch.test.ts b/test/moves/sketch.test.ts index c6fb7b4a32a..5e9ce9a9e84 100644 --- a/test/moves/sketch.test.ts +++ b/test/moves/sketch.test.ts @@ -30,7 +30,7 @@ describe("Moves - Sketch", () => { game.override .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.SHUCKLE) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/skill_swap.test.ts b/test/moves/skill_swap.test.ts index c4fb6005e28..7c2e6f5fd0a 100644 --- a/test/moves/skill_swap.test.ts +++ b/test/moves/skill_swap.test.ts @@ -26,7 +26,7 @@ describe("Moves - Skill Swap", () => { .moveset([MoveId.SPLASH, MoveId.SKILL_SWAP]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/sleep_talk.test.ts b/test/moves/sleep_talk.test.ts index 1d9aec77ea2..84e9d509a03 100644 --- a/test/moves/sleep_talk.test.ts +++ b/test/moves/sleep_talk.test.ts @@ -29,7 +29,7 @@ describe("Moves - Sleep Talk", () => { .statusEffect(StatusEffect.SLEEP) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH) diff --git a/test/moves/spectral_thief.test.ts b/test/moves/spectral_thief.test.ts index 808e9174caf..e7b19eda506 100644 --- a/test/moves/spectral_thief.test.ts +++ b/test/moves/spectral_thief.test.ts @@ -29,7 +29,8 @@ describe("Moves - Spectral Thief", () => { .enemyMoveset(MoveId.SPLASH) .enemyAbility(AbilityId.BALL_FETCH) .moveset([MoveId.SPECTRAL_THIEF, MoveId.SPLASH]) - .ability(AbilityId.BALL_FETCH).disableCrits; + .ability(AbilityId.BALL_FETCH) + .criticalHits(false); }); it("should steal max possible positive stat changes and ignore negative ones.", async () => { diff --git a/test/moves/struggle.test.ts b/test/moves/struggle.test.ts index cd3c65217ed..24b2b6428fc 100644 --- a/test/moves/struggle.test.ts +++ b/test/moves/struggle.test.ts @@ -25,7 +25,7 @@ describe("Moves - Struggle", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/synchronoise.test.ts b/test/moves/synchronoise.test.ts index 176137c8180..9068a40693b 100644 --- a/test/moves/synchronoise.test.ts +++ b/test/moves/synchronoise.test.ts @@ -26,7 +26,7 @@ describe("Moves - Synchronoise", () => { .moveset([MoveId.SYNCHRONOISE]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/tackle.test.ts b/test/moves/tackle.test.ts index 83a267dc7e4..29f61e8723f 100644 --- a/test/moves/tackle.test.ts +++ b/test/moves/tackle.test.ts @@ -31,7 +31,7 @@ describe("Moves - Tackle", () => { .startingWave(97) .moveset([moveToUse]) .enemyMoveset(MoveId.GROWTH) - .disableCrits(); + .criticalHits(false); }); it("TACKLE against ghost", async () => { diff --git a/test/moves/tar_shot.test.ts b/test/moves/tar_shot.test.ts index fefd1a30e1e..8d5ea4b3582 100644 --- a/test/moves/tar_shot.test.ts +++ b/test/moves/tar_shot.test.ts @@ -30,7 +30,7 @@ describe("Moves - Tar Shot", () => { .enemySpecies(SpeciesId.TANGELA) .enemyLevel(1000) .moveset([MoveId.TAR_SHOT, MoveId.FIRE_PUNCH]) - .disableCrits(); + .criticalHits(false); }); it("lowers the target's Speed stat by one stage and doubles the effectiveness of Fire-type moves used on the target", async () => { diff --git a/test/moves/tera_blast.test.ts b/test/moves/tera_blast.test.ts index 2f3bdcebfcf..06dde3ae130 100644 --- a/test/moves/tera_blast.test.ts +++ b/test/moves/tera_blast.test.ts @@ -35,7 +35,7 @@ describe("Moves - Tera Blast", () => { game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .starterSpecies(SpeciesId.FEEBAS) .moveset([MoveId.TERA_BLAST]) .ability(AbilityId.BALL_FETCH) diff --git a/test/moves/trick_or_treat.test.ts b/test/moves/trick_or_treat.test.ts index 366c6ee60fe..861115e2503 100644 --- a/test/moves/trick_or_treat.test.ts +++ b/test/moves/trick_or_treat.test.ts @@ -26,7 +26,7 @@ describe("Moves - Trick Or Treat", () => { .moveset([MoveId.FORESTS_CURSE, MoveId.TRICK_OR_TREAT]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/moves/u_turn.test.ts b/test/moves/u_turn.test.ts index 4212802298e..d5a41f41f8f 100644 --- a/test/moves/u_turn.test.ts +++ b/test/moves/u_turn.test.ts @@ -29,7 +29,7 @@ describe("Moves - U-turn", () => { .startingWave(97) .moveset([MoveId.U_TURN]) .enemyMoveset(MoveId.SPLASH) - .disableCrits(); + .criticalHits(false); }); it("triggers regenerator a single time when a regenerator user switches out with u-turn", async () => { diff --git a/test/moves/upper_hand.test.ts b/test/moves/upper_hand.test.ts index e3d490ba6fa..fe38e75cf9a 100644 --- a/test/moves/upper_hand.test.ts +++ b/test/moves/upper_hand.test.ts @@ -27,7 +27,7 @@ describe("Moves - Upper Hand", () => { .moveset(MoveId.UPPER_HAND) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.QUICK_ATTACK) diff --git a/test/moves/will_o_wisp.test.ts b/test/moves/will_o_wisp.test.ts index 40495009d2a..336e84129c5 100644 --- a/test/moves/will_o_wisp.test.ts +++ b/test/moves/will_o_wisp.test.ts @@ -27,7 +27,7 @@ describe("Moves - Will-O-Wisp", () => { .moveset([MoveId.WILL_O_WISP, MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/phases/form-change-phase.test.ts b/test/phases/form-change-phase.test.ts index 99c072bdafe..b025f72f5e4 100644 --- a/test/phases/form-change-phase.test.ts +++ b/test/phases/form-change-phase.test.ts @@ -28,7 +28,7 @@ describe("Form Change Phase", () => { .moveset([MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); diff --git a/test/phases/frenzy-move-reset.test.ts b/test/phases/frenzy-move-reset.test.ts index 878c58d8666..9c59e1da968 100644 --- a/test/phases/frenzy-move-reset.test.ts +++ b/test/phases/frenzy-move-reset.test.ts @@ -26,7 +26,7 @@ describe("Frenzy Move Reset", () => { game = new GameManager(phaserGame); game.override .battleStyle("single") - .disableCrits() + .criticalHits(false) .starterSpecies(SpeciesId.MAGIKARP) .moveset(MoveId.THRASH) .statusEffect(StatusEffect.PARALYSIS) diff --git a/test/phases/game-over-phase.test.ts b/test/phases/game-over-phase.test.ts index d45330697fc..008f9fb68e8 100644 --- a/test/phases/game-over-phase.test.ts +++ b/test/phases/game-over-phase.test.ts @@ -28,7 +28,7 @@ describe("Game Over Phase", () => { .moveset([MoveId.MEMENTO, MoveId.ICE_BEAM, MoveId.SPLASH]) .ability(AbilityId.BALL_FETCH) .battleStyle("single") - .disableCrits() + .criticalHits(false) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH) .startingWave(200) diff --git a/test/testUtils/gameManagerUtils.ts b/test/testUtils/gameManagerUtils.ts index d582f8c04e3..eda3921e9e0 100644 --- a/test/testUtils/gameManagerUtils.ts +++ b/test/testUtils/gameManagerUtils.ts @@ -97,7 +97,7 @@ export function waitUntil(truth): Promise { }); } -/** Get the index of `move` from the moveset of the pokemon on the player's field at location `pokemonIndex` */ +/** Get the index of `move` from the moveset of the pokemon on the player's field at location `pokemonIndex`. */ export function getMovePosition(scene: BattleScene, pokemonIndex: 0 | 1, move: MoveId): number { const playerPokemon = scene.getPlayerField()[pokemonIndex]; const moveSet = playerPokemon.getMoveset(); diff --git a/test/testUtils/helpers/dailyModeHelper.ts b/test/testUtils/helpers/dailyModeHelper.ts index 8ee03ce5f89..4672d4dc787 100644 --- a/test/testUtils/helpers/dailyModeHelper.ts +++ b/test/testUtils/helpers/dailyModeHelper.ts @@ -16,8 +16,9 @@ export class DailyModeHelper extends GameManagerHelper { /** * Runs the daily game to the summon phase. * @returns A promise that resolves when the summon phase is reached. + * @remarks Please do not use for starting normal battles - use {@linkcode startBattle} instead */ - async runToSummon() { + async runToSummon(): Promise { await this.game.runToTitle(); if (this.game.override.disableShinies) { @@ -45,7 +46,7 @@ export class DailyModeHelper extends GameManagerHelper { * Transitions to the start of a battle. * @returns A promise that resolves when the battle is started. */ - async startBattle() { + async startBattle(): Promise { await this.runToSummon(); if (this.game.scene.battleStyle === BattleStyle.SWITCH) { diff --git a/test/testUtils/helpers/overridesHelper.ts b/test/testUtils/helpers/overridesHelper.ts index 9869c7450e2..3bf0fbbda47 100644 --- a/test/testUtils/helpers/overridesHelper.ts +++ b/test/testUtils/helpers/overridesHelper.ts @@ -243,12 +243,15 @@ export class OverridesHelper extends GameManagerHelper { } /** - * Override each wave to not have critical hits + * Force random critical hit rolls to always or never suceed. + * @param crits - `true` to guarantee crits on eligible moves, `false` to force rolls to fail, `null` to disable override + * @remarks This does not bypass effects that guarantee or block critical hits; it merely mocks the chance-based rolls. * @returns `this` */ - public disableCrits(): this { - vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); - this.log("Critical hits are disabled!"); + public criticalHits(crits: boolean | null): this { + vi.spyOn(Overrides, "CRITICAL_HIT_OVERRIDE", "get").mockReturnValue(crits); + const freq = crits === true ? "always" : crits === false ? "never" : "randomly"; + this.log(`Critical hit rolls set to ${freq} succeed!`); return this; } diff --git a/test/testUtils/phaseInterceptor.ts b/test/testUtils/phaseInterceptor.ts index 34fba2c145d..9d046fc85ba 100644 --- a/test/testUtils/phaseInterceptor.ts +++ b/test/testUtils/phaseInterceptor.ts @@ -210,7 +210,7 @@ export default class PhaseInterceptor { /** * Method to transition to a target phase. * @param phaseTo - The phase to transition to. - * @param runTarget - Whether or not to run the target phase. + * @param runTarget - Whether or not to run the target phase; default `true`. * @returns A promise that resolves when the transition is complete. */ async to(phaseTo: PhaseInterceptorPhase, runTarget = true): Promise { @@ -439,7 +439,7 @@ export default class PhaseInterceptor { * @param mode - The mode of the UI. * @param callback - The callback function to execute. * @param expireFn - The function to determine if the prompt has expired. - * @param awaitingActionInput + * @param awaitingActionInput - ???; default `false` */ addToNextPrompt( phaseTarget: string,