fix switch moves again

This commit is contained in:
Alex Van Liew 2024-08-08 16:16:50 -07:00 committed by snoozbuster
parent 5e21005fe9
commit a086b3a0ad
2 changed files with 19 additions and 18 deletions

View File

@ -4965,7 +4965,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
if (switchOutTarget.hp > 0) { if (switchOutTarget.hp > 0) {
user.scene.prependToPhase( user.scene.prependToPhase(
new SwitchPhase(user.scene, switchOutTarget.getFieldIndex(), true, willBePursued), new SwitchPhase(user.scene, switchOutTarget.getFieldIndex(), "moveEffect", willBePursued),
MoveEndPhase MoveEndPhase
); );
resolve(true); resolve(true);

View File

@ -1842,7 +1842,7 @@ export class CheckSwitchPhase extends BattlePhase {
this.scene.ui.setMode(Mode.CONFIRM, () => { this.scene.ui.setMode(Mode.CONFIRM, () => {
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
this.scene.tryRemovePhase(p => p instanceof PostSummonPhase && p.player && p.fieldIndex === this.fieldIndex); 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.end();
}, () => { }, () => {
this.scene.ui.setMode(Mode.MESSAGE); this.scene.ui.setMode(Mode.MESSAGE);
@ -4077,7 +4077,7 @@ export class FaintPhase extends PokemonPhase {
} else if (nonFaintedPartyMemberCount === 1 && this.scene.currentBattle.double) { } else if (nonFaintedPartyMemberCount === 1 && this.scene.currentBattle.double) {
this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true)); this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true));
} else if (nonFaintedPartyMemberCount >= this.scene.currentBattle.getBattlerCount()) { } 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 { } else {
this.scene.unshiftPhase(new VictoryPhase(this.scene, this.battlerIndex)); this.scene.unshiftPhase(new VictoryPhase(this.scene, this.battlerIndex));
@ -4721,55 +4721,56 @@ export class PostGameOverPhase extends Phase {
*/ */
export class SwitchPhase extends BattlePhase { export class SwitchPhase extends BattlePhase {
protected fieldIndex: integer; protected fieldIndex: integer;
private isModal: boolean; private switchReason: "faint" | "moveEffect" | "switchMode";
private doReturn: boolean; private doReturn: boolean;
/** /**
* Creates a new SwitchPhase * Creates a new SwitchPhase
* @param scene {@linkcode BattleScene} Current battle scene * @param scene {@linkcode BattleScene} Current battle scene
* @param fieldIndex Field index to switch out * @param fieldIndex Field index to switch out
* @param isModal Indicates if the switch should be forced (true) or is * @param switchReason Indicates why this switch is occurring. The valid options are
* optional (false). * `'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 * @param doReturn Indicates if this switch should call back the pokemon at
* the {@linkcode fieldIndex} (true), or if the mon has already been recalled * the {@linkcode fieldIndex} (true), or if the mon has already been recalled
* (false). * (false).
*/ */
constructor(scene: BattleScene, fieldIndex: integer, isModal: boolean, doReturn: boolean) { constructor(scene: BattleScene, fieldIndex: integer, switchReason: "faint" | "moveEffect" | "switchMode", doReturn: boolean) {
super(scene); super(scene);
this.fieldIndex = fieldIndex; this.fieldIndex = fieldIndex;
this.isModal = isModal; this.switchReason = switchReason;
this.doReturn = doReturn; this.doReturn = doReturn;
} }
start() { start() {
super.start(); super.start();
// Skip modal switch if impossible (no remaining party members that aren't in battle) const isForcedSwitch = this.switchReason !== "switchMode";
if (this.isModal && !this.scene.getParty().filter(p => p.isAllowedInBattle() && !p.isActive(true)).length) {
// 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(); return super.end();
} }
// Skip if the fainted party member has been revived already. doReturn is // Skip if the fainted party member has been revived already. see also; battle.test.ts
// only passed as `false` from FaintPhase (as opposed to other usages such if (this.switchReason === "faint" && !this.scene.getParty()[this.fieldIndex].isFainted()) {
// 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()) {
return super.end(); return super.end();
} }
// Check if there is any space still in field // Check if there is any space still in field
const numActiveBattlers = this.scene.getPlayerField().filter(p => p.isAllowedInBattle() && p.isActive(true)).length; 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) 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(); return super.end();
} }
// Override field index to 0 in case of double battle where 2/3 remaining legal party members fainted at once // 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; 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) { if (slotIndex >= this.scene.currentBattle.getBattlerCount() && slotIndex < 6) {
this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, fieldIndex, slotIndex, this.doReturn, option === PartyOption.PASS_BATON)); this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, fieldIndex, slotIndex, this.doReturn, option === PartyOption.PASS_BATON));
} }