From e73cc310c01fbe2c15c669eaa0ec61742902a01f Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Thu, 10 Apr 2025 16:42:07 -0500 Subject: [PATCH] Fixup tests and broken assumptions --- src/battle-scene.ts | 1 - src/data/abilities/ability.ts | 6 ++++-- src/data/moves/move.ts | 35 +++++++++++++++++++---------------- test/moves/whirlwind.test.ts | 25 ++++++++++++++++++++++--- 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 7557030e8f1..0fe4c7f7e4f 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1455,7 +1455,6 @@ export default class BattleScene extends SceneBase { this.executeWithSeedOffset( () => { - console.log(`Starting a new battle with ${BattleType[newBattleType]} and double: ${newDouble}`); this.currentBattle = new Battle(this.gameMode, newWaveIndex, newBattleType, newTrainer, newDouble); }, newWaveIndex << 3, diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index 2c56d018570..f781284940a 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -44,6 +44,7 @@ import { PokemonTransformPhase } from "#app/phases/pokemon-transform-phase"; import { allAbilities } from "#app/data/data-lists"; import { AbAttr } from "#app/data/abilities/ab-attrs/ab-attr"; import { Ability } from "#app/data/abilities/ability-class"; +import { TrainerVariant } from "#app/field/trainer"; // Enum imports import { Stat, type BattleStat , BATTLE_STATS, EFFECTIVE_STATS, getStatKey, type EffectiveStat } from "#enums/stat"; @@ -61,6 +62,7 @@ import { MoveFlags } from "#enums/MoveFlags"; import { MoveTarget } from "#enums/MoveTarget"; import { MoveCategory } from "#enums/MoveCategory"; + // Type imports import type { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; @@ -5526,8 +5528,8 @@ class ForceSwitchOutHelper { const party = player ? globalScene.getPlayerParty() : globalScene.getEnemyParty(); return (!player && globalScene.currentBattle.battleType === BattleType.WILD) - || party.filter(p => p.isAllowedInBattle() - && (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > globalScene.currentBattle.getBattlerCount(); + || party.filter(p => p.isAllowedInBattle() && !p.isOnField() + && (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > 0; } /** diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 2d1ef39922e..e94841feea2 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -6230,10 +6230,8 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { // Check if the move category is not STATUS or if the switch out condition is not met if (!this.getSwitchOutCondition()(user, target, move)) { - console.log("=========== Switch out condition was false!==========="); return false; } - console.log("=========== Switch out condition was true!==========="); /** The {@linkcode Pokemon} to be switched out with this effect */ const switchOutTarget = this.selfSwitch ? user : target; @@ -6376,7 +6374,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { } getCondition(): MoveConditionFunc { - return (user, target, move) => (move.category !== MoveCategory.STATUS || this.getSwitchOutCondition()(user, target, move)); + return (user, target, move) => (move.category !== MoveCategory.STATUS || this.getSwitchOutCondition(true)(user, target, move)); } getFailedText(_user: Pokemon, target: Pokemon, _move: Move): string | undefined { @@ -6387,7 +6385,13 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { } } - getSwitchOutCondition(): MoveConditionFunc { + + /** + * Check if the switch out conditions are met. + * + * @param preliminary - Whether to check for failure conditions that occur before the hit check (defaults to false) + */ + getSwitchOutCondition(preliminary = false): MoveConditionFunc { return (user, target, move) => { const switchOutTarget = (this.selfSwitch ? user : target); const player = switchOutTarget instanceof PlayerPokemon; @@ -6415,22 +6419,21 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { } } + if (preliminary) { + return true; + } + if (!player && globalScene.currentBattle.battleType === BattleType.WILD) { - // Prevent wild pokemon fr - return !(this.isBatonPass() - // Don't allow boss waves of wild pokemon to flee - && globalScene.currentBattle.waveIndex % 10 === 0 - // Don't allow wild mons to flee with U-turn et al. - && this.selfSwitch && move.category !== MoveCategory.STATUS) + // wild pokemon cannot switch out with baton pass. + return !this.isBatonPass() + && globalScene.currentBattle.waveIndex % 10 !== 0 + // Don't allow wild mons to flee with U-turn et al. + && !(this.selfSwitch && MoveCategory.STATUS !== move.category); } const party = player ? globalScene.getPlayerParty() : globalScene.getEnemyParty(); - // Determine if this is a - const currentBattle = globalScene.currentBattle; - // If the trainer battle is a partner, then they can switch out as long as they have at least one pokemon in the back - const MIN_BATTLE_COUNT = (!player && currentBattle.trainer?.variant === TrainerVariant.DOUBLE) ? 1 : currentBattle.getBattlerCount(); - return party.filter(p => p.isAllowedInBattle() - && (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > MIN_BATTLE_COUNT; + return party.filter(p => p.isAllowedInBattle() && !p.isOnField() + && (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > 0; }; } diff --git a/test/moves/whirlwind.test.ts b/test/moves/whirlwind.test.ts index 67d70891535..839c3d1e980 100644 --- a/test/moves/whirlwind.test.ts +++ b/test/moves/whirlwind.test.ts @@ -180,12 +180,15 @@ describe("Moves - Whirlwind", () => { game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH); - await game.forceEnemyMove(Moves.LUNAR_DANCE); + await game.forceEnemyMove(Moves.MEMENTO); await game.forceEnemyMove(Moves.SPLASH); await game.toNextTurn(); + // Get the enemy pokemon id so we can check if is the same after switch. + const enemy_id = game.scene.getEnemyPokemon()!.id; + // Hit the enemy that fainted with whirlwind. - game.move.select(Moves.WHIRLWIND, 0, BattlerIndex.ENEMY_2); + game.move.select(Moves.WHIRLWIND, 0, BattlerIndex.ENEMY); game.move.select(Moves.SPLASH, 1); await game.forceEnemyMove(Moves.SPLASH); @@ -194,6 +197,22 @@ describe("Moves - Whirlwind", () => { await game.toNextTurn(); // Expect the enemy pokemon to not have switched out. - expect(game.scene.getPlayerPokemon()!.getLastXMoves(1)[0].result).toBe(MoveResult.FAIL); + expect(game.scene.getEnemyPokemon()!.id).toBe(enemy_id); + }); + + it("should force a wild pokemon to flee", async () => { + game.override + .battleType(BattleType.WILD) + .moveset([Moves.WHIRLWIND, Moves.SPLASH]) + .enemyMoveset(Moves.SPLASH) + .ability(Abilities.BALL_FETCH); + await game.classicMode.startBattle([Species.MAGIKARP]); + + const user = game.scene.getPlayerPokemon()!; + + game.move.select(Moves.WHIRLWIND); + await game.phaseInterceptor.to("BerryPhase"); + + expect(user.getLastXMoves(1)[0].result).toBe(MoveResult.SUCCESS); }); });