From a086b3a0ad03b0acca948b387fdbb5b76759f010 Mon Sep 17 00:00:00 2001 From: Alex Van Liew Date: Thu, 8 Aug 2024 16:16:50 -0700 Subject: [PATCH] fix switch moves again --- src/data/move.ts | 2 +- src/phases.ts | 35 ++++++++++++++++++----------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 6a607878e24..c056e8c7b01 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -4965,7 +4965,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { if (switchOutTarget.hp > 0) { user.scene.prependToPhase( - new SwitchPhase(user.scene, switchOutTarget.getFieldIndex(), true, willBePursued), + new SwitchPhase(user.scene, switchOutTarget.getFieldIndex(), "moveEffect", willBePursued), MoveEndPhase ); resolve(true); diff --git a/src/phases.ts b/src/phases.ts index 466ab4218d5..7a745a386fe 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1842,7 +1842,7 @@ export class CheckSwitchPhase extends BattlePhase { this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.MESSAGE); this.scene.tryRemovePhase(p => p instanceof PostSummonPhase && p.player && p.fieldIndex === this.fieldIndex); - this.scene.unshiftPhase(new SwitchPhase(this.scene, this.fieldIndex, false, true)); + this.scene.unshiftPhase(new SwitchPhase(this.scene, this.fieldIndex, "switchMode", true)); this.end(); }, () => { this.scene.ui.setMode(Mode.MESSAGE); @@ -4077,7 +4077,7 @@ export class FaintPhase extends PokemonPhase { } else if (nonFaintedPartyMemberCount === 1 && this.scene.currentBattle.double) { this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true)); } else if (nonFaintedPartyMemberCount >= this.scene.currentBattle.getBattlerCount()) { - this.scene.pushPhase(new SwitchPhase(this.scene, this.fieldIndex, true, false)); + this.scene.pushPhase(new SwitchPhase(this.scene, this.fieldIndex, "faint", false)); } } else { this.scene.unshiftPhase(new VictoryPhase(this.scene, this.battlerIndex)); @@ -4721,55 +4721,56 @@ export class PostGameOverPhase extends Phase { */ export class SwitchPhase extends BattlePhase { protected fieldIndex: integer; - private isModal: boolean; + private switchReason: "faint" | "moveEffect" | "switchMode"; private doReturn: boolean; /** * Creates a new SwitchPhase * @param scene {@linkcode BattleScene} Current battle scene * @param fieldIndex Field index to switch out - * @param isModal Indicates if the switch should be forced (true) or is - * optional (false). + * @param switchReason Indicates why this switch is occurring. The valid options are + * `'faint'` (party member fainted), `'moveEffect'` (uturn, baton pass, dragon + * tail, etc), and `'switchMode'` (start-of-battle optional switch). This + * helps the phase determine both if the switch should be cancellable by the + * user, as well as determine if the party UI should be shown at all. * @param doReturn Indicates if this switch should call back the pokemon at * the {@linkcode fieldIndex} (true), or if the mon has already been recalled * (false). */ - constructor(scene: BattleScene, fieldIndex: integer, isModal: boolean, doReturn: boolean) { + constructor(scene: BattleScene, fieldIndex: integer, switchReason: "faint" | "moveEffect" | "switchMode", doReturn: boolean) { super(scene); this.fieldIndex = fieldIndex; - this.isModal = isModal; + this.switchReason = switchReason; this.doReturn = doReturn; } start() { super.start(); - // Skip modal switch if impossible (no remaining party members that aren't in battle) - if (this.isModal && !this.scene.getParty().filter(p => p.isAllowedInBattle() && !p.isActive(true)).length) { + const isForcedSwitch = this.switchReason !== "switchMode"; + + // Skip forced switch if impossible (no remaining party members that aren't in battle) + if (isForcedSwitch && !this.scene.getParty().filter(p => p.isAllowedInBattle() && !p.isActive(true)).length) { return super.end(); } - // Skip if the fainted party member has been revived already. doReturn is - // only passed as `false` from FaintPhase (as opposed to other usages such - // as ForceSwitchOutAttr or CheckSwitchPhase), so we only want to check this - // if the mon should have already been returned but is still alive and well - // on the field. see also; battle.test.ts - if (this.isModal && !this.doReturn && !this.scene.getParty()[this.fieldIndex].isFainted()) { + // Skip if the fainted party member has been revived already. see also; battle.test.ts + if (this.switchReason === "faint" && !this.scene.getParty()[this.fieldIndex].isFainted()) { return super.end(); } // Check if there is any space still in field const numActiveBattlers = this.scene.getPlayerField().filter(p => p.isAllowedInBattle() && p.isActive(true)).length; const willReturnModifer = (this.doReturn ? 1 : 0); // need to subtract this if doReturn is true, because the pokemon in the given index hasn't left the field yet. (used for volt switch + pursuit, etc) - if (this.isModal && numActiveBattlers - willReturnModifer >= this.scene.currentBattle.getBattlerCount()) { + if (isForcedSwitch && numActiveBattlers - willReturnModifer >= this.scene.currentBattle.getBattlerCount()) { return super.end(); } // Override field index to 0 in case of double battle where 2/3 remaining legal party members fainted at once const fieldIndex = this.scene.currentBattle.getBattlerCount() === 1 || this.scene.getParty().filter(p => p.isAllowedInBattle()).length > 1 ? this.fieldIndex : 0; - this.scene.ui.setMode(Mode.PARTY, this.isModal ? PartyUiMode.FAINT_SWITCH : PartyUiMode.POST_BATTLE_SWITCH, fieldIndex, (slotIndex: integer, option: PartyOption) => { + this.scene.ui.setMode(Mode.PARTY, isForcedSwitch ? PartyUiMode.FAINT_SWITCH : PartyUiMode.POST_BATTLE_SWITCH, fieldIndex, (slotIndex: integer, option: PartyOption) => { if (slotIndex >= this.scene.currentBattle.getBattlerCount() && slotIndex < 6) { this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, fieldIndex, slotIndex, this.doReturn, option === PartyOption.PASS_BATON)); }