From 0eea2031fb18530a9de278a70a39496568f66cfc Mon Sep 17 00:00:00 2001 From: DustinLin <39450497+DustinLin@users.noreply.github.com> Date: Fri, 20 Sep 2024 07:27:43 -0700 Subject: [PATCH] [Bug] Fixing seed sower uturn switchout bug for trainer battles (#4113) * refactor wildFlee for seed sower animation bug * better naming functions * review suggestions --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- src/battle-scene.ts | 16 ++++++++++++++++ src/data/battle-anims.ts | 4 ++-- src/data/move.ts | 1 - src/field/pokemon.ts | 14 ++++++++------ src/test/moves/dragon_tail.test.ts | 12 ++++++------ 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 753efdaf62c..f6e4cffcf1e 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -782,6 +782,14 @@ export default class BattleScene extends SceneBase { return this.getPlayerField().find(p => p.isActive()); } + /** + * Finds the first {@linkcode Pokemon.isActive() | active PlayerPokemon} that isn't also currently switching out + * @returns Either the first {@linkcode PlayerPokemon} satisfying, or undefined if no player pokemon on the field satisfy + */ + getNonSwitchedPlayerPokemon(): PlayerPokemon | undefined { + return this.getPlayerField().find(p => p.isActive() && p.switchOutStatus === false); + } + /** * Returns an array of PlayerPokemon of length 1 or 2 depending on if double battles or not * @returns array of {@linkcode PlayerPokemon} @@ -799,6 +807,14 @@ export default class BattleScene extends SceneBase { return this.getEnemyField().find(p => p.isActive()); } + /** + * Finds the first {@linkcode Pokemon.isActive() | active EnemyPokemon} pokemon from the enemy that isn't also currently switching out + * @returns Either the first {@linkcode EnemyPokemon} satisfying, or undefined if no player pokemon on the field satisfy + */ + getNonSwitchedEnemyPokemon(): EnemyPokemon | undefined { + return this.getEnemyField().find(p => p.isActive() && p.switchOutStatus === false); + } + /** * Returns an array of EnemyPokemon of length 1 or 2 depending on if double battles or not * @returns array of {@linkcode EnemyPokemon} diff --git a/src/data/battle-anims.ts b/src/data/battle-anims.ts index d972e48df7c..d7b995f748f 100644 --- a/src/data/battle-anims.ts +++ b/src/data/battle-anims.ts @@ -428,7 +428,7 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent { moveAnim.bgSprite.setScale(1.25); moveAnim.bgSprite.setAlpha(this.opacity / 255); scene.field.add(moveAnim.bgSprite); - const fieldPokemon = scene.getEnemyPokemon() || scene.getPlayerPokemon(); + const fieldPokemon = scene.getNonSwitchedEnemyPokemon() || scene.getNonSwitchedPlayerPokemon(); if (!isNullOrUndefined(priority)) { scene.field.moveTo(moveAnim.bgSprite as Phaser.GameObjects.GameObject, priority!); } else if (fieldPokemon?.isOnField()) { @@ -989,7 +989,7 @@ export abstract class BattleAnim { const setSpritePriority = (priority: integer) => { switch (priority) { case 0: - scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, scene.getEnemyPokemon() || scene.getPlayerPokemon()!); // TODO: is this bang correct? + scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, scene.getNonSwitchedEnemyPokemon() || scene.getNonSwitchedPlayerPokemon()!); // This bang assumes that if (the EnemyPokemon is undefined, then the PlayerPokemon function must return an object), correct assumption? break; case 1: scene.field.moveTo(moveSprite, scene.field.getAll().length - 1); diff --git a/src/data/move.ts b/src/data/move.ts index ef96ff19b07..de5176c3c84 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -5221,7 +5221,6 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { switchOutTarget.leaveField(false); if (switchOutTarget.hp) { - switchOutTarget.setWildFlee(true); user.scene.queueMessage(i18next.t("moveTriggers:fled", {pokemonName: getPokemonNameWithAffix(switchOutTarget)}), null, true, 500); // in double battles redirect potential moves off fled pokemon diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 3935778296f..f7b19572038 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -99,7 +99,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { public luck: integer; public pauseEvolutions: boolean; public pokerus: boolean; - public wildFlee: boolean; + public switchOutStatus: boolean; public evoCounter: integer; public fusionSpecies: PokemonSpecies | null; @@ -145,7 +145,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.species = species; this.pokeball = dataSource?.pokeball || PokeballType.POKEBALL; this.level = level; - this.wildFlee = false; + this.switchOutStatus = false; // Determine the ability index if (abilityIndex !== undefined) { @@ -343,7 +343,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { isAllowed(): boolean { const challengeAllowed = new Utils.BooleanHolder(true); applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, this, challengeAllowed); - return !this.wildFlee && challengeAllowed.value; + return !this.isFainted() && challengeAllowed.value; } isActive(onField?: boolean): boolean { @@ -2152,11 +2152,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } /** - * sets if the pokemon has fled (implies it's a wild pokemon) + * sets if the pokemon is switching out (if it's a enemy wild implies it's going to flee) * @param status - boolean */ - setWildFlee(status: boolean): void { - this.wildFlee = status; + setSwitchOutStatus(status: boolean): void { + this.switchOutStatus = status; } updateInfo(instant?: boolean): Promise { @@ -3384,6 +3384,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.updateFusionPalette(); } this.summonData = new PokemonSummonData(); + this.setSwitchOutStatus(false); if (!this.battleData) { this.resetBattleData(); } @@ -3789,6 +3790,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.hideInfo(); } this.scene.field.remove(this); + this.setSwitchOutStatus(true); this.scene.triggerPokemonFormChange(this, SpeciesFormChangeActiveTrigger, true); } diff --git a/src/test/moves/dragon_tail.test.ts b/src/test/moves/dragon_tail.test.ts index e1af29b2db1..75b2c9ba73e 100644 --- a/src/test/moves/dragon_tail.test.ts +++ b/src/test/moves/dragon_tail.test.ts @@ -50,7 +50,7 @@ describe("Moves - Dragon Tail", () => { await game.phaseInterceptor.to(BerryPhase); const isVisible = enemyPokemon.visible; - const hasFled = enemyPokemon.wildFlee; + const hasFled = enemyPokemon.switchOutStatus; expect(!isVisible && hasFled).toBe(true); // simply want to test that the game makes it this far without crashing @@ -72,7 +72,7 @@ describe("Moves - Dragon Tail", () => { await game.phaseInterceptor.to(BerryPhase); const isVisible = enemyPokemon.visible; - const hasFled = enemyPokemon.wildFlee; + const hasFled = enemyPokemon.switchOutStatus; expect(!isVisible && hasFled).toBe(true); expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); }, TIMEOUT @@ -97,9 +97,9 @@ describe("Moves - Dragon Tail", () => { await game.phaseInterceptor.to(TurnEndPhase); const isVisibleLead = enemyLeadPokemon.visible; - const hasFledLead = enemyLeadPokemon.wildFlee; + const hasFledLead = enemyLeadPokemon.switchOutStatus; const isVisibleSec = enemySecPokemon.visible; - const hasFledSec = enemySecPokemon.wildFlee; + const hasFledSec = enemySecPokemon.switchOutStatus; expect(!isVisibleLead && hasFledLead && isVisibleSec && !hasFledSec).toBe(true); expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); @@ -133,9 +133,9 @@ describe("Moves - Dragon Tail", () => { await game.phaseInterceptor.to(BerryPhase); const isVisibleLead = enemyLeadPokemon.visible; - const hasFledLead = enemyLeadPokemon.wildFlee; + const hasFledLead = enemyLeadPokemon.switchOutStatus; const isVisibleSec = enemySecPokemon.visible; - const hasFledSec = enemySecPokemon.wildFlee; + const hasFledSec = enemySecPokemon.switchOutStatus; expect(!isVisibleLead && hasFledLead && !isVisibleSec && hasFledSec).toBe(true); expect(leadPokemon.hp).toBeLessThan(leadPokemon.getMaxHp()); expect(secPokemon.hp).toBeLessThan(secPokemon.getMaxHp());