From ae7c1ef4f03159c2c411de1fb71eb613b83e78bf Mon Sep 17 00:00:00 2001 From: Benjamin Odom Date: Sat, 11 May 2024 08:22:26 -0500 Subject: [PATCH] Fix Charge Move Infinites (#741) Fixed an issue where two turn charge moves could be paused by status or Truant causing some infinite sequences if not careful. --- src/field/pokemon.ts | 2 +- src/phases.ts | 38 +++++++++++++++++++++----------------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index cc2c93d9094..f879ec1a8db 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -731,7 +731,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const overrideArray: Array = this.isPlayer() ? Overrides.MOVESET_OVERRIDE : Overrides.OPP_MOVESET_OVERRIDE; if (overrideArray.length > 0) { overrideArray.forEach((move: Moves, index: number) => { - const ppUsed = this.moveset[index]?.ppUp || 0; + const ppUsed = this.moveset[index]?.ppUsed || 0; this.moveset[index] = new PokemonMove(move, Math.min(ppUsed, allMoves[move].pp)) }); } diff --git a/src/phases.ts b/src/phases.ts index 5341dc33545..d8ce55e95a7 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2211,22 +2211,22 @@ export class MovePhase extends BattlePhase { } // Move redirection abilities (ie. Storm Drain) only support single target moves -const moveTarget = this.targets.length === 1 - ? new Utils.IntegerHolder(this.targets[0]) - : null; - if (moveTarget) { - var oldTarget = moveTarget.value; - this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, this.move.moveId, moveTarget)); - //Check if this move is immune to being redirected, and restore its target to the intended target if it is. - if ((this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr) || this.move.getMove().getAttrs(BypassRedirectAttr).length)) { - //If an ability prevented this move from being redirected, display its ability pop up. - if ((this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr) && !this.move.getMove().getAttrs(BypassRedirectAttr).length) && oldTarget != moveTarget.value) { - this.scene.unshiftPhase(new ShowAbilityPhase(this.scene, this.pokemon.getBattlerIndex(), this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr))); - } + const moveTarget = this.targets.length === 1 + ? new Utils.IntegerHolder(this.targets[0]) + : null; + if (moveTarget) { + var oldTarget = moveTarget.value; + this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, this.move.moveId, moveTarget)); + //Check if this move is immune to being redirected, and restore its target to the intended target if it is. + if ((this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr) || this.move.getMove().getAttrs(BypassRedirectAttr).length)) { + //If an ability prevented this move from being redirected, display its ability pop up. + if ((this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr) && !this.move.getMove().getAttrs(BypassRedirectAttr).length) && oldTarget != moveTarget.value) { + this.scene.unshiftPhase(new ShowAbilityPhase(this.scene, this.pokemon.getBattlerIndex(), this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr))); + } moveTarget.value = oldTarget; - } - this.targets[0] = moveTarget.value; -} + } + this.targets[0] = moveTarget.value; + } if (this.targets.length === 1 && this.targets[0] === BattlerIndex.ATTACKER) { if (this.pokemon.turnData.attacksReceived.length) { @@ -2269,16 +2269,20 @@ const moveTarget = this.targets.length === 1 if (!this.followUp && this.canMove() && !this.cancelled) { this.pokemon.lapseTags(BattlerTagLapseType.MOVE); } + + const moveQueue = this.pokemon.getMoveQueue(); if (this.cancelled || this.failed) { if (this.failed) this.move.usePp(ppUsed); // Only use PP if the move failed + // Record a failed move so Abilities like Truant don't trigger next turn and soft-lock this.pokemon.pushMoveHistory({ move: Moves.NONE, result: MoveResult.FAIL }); + + this.pokemon.lapseTags(BattlerTagLapseType.MOVE_EFFECT); // Remove any tags from moves like Fly/Dive/etc. + moveQueue.shift(); // Remove the second turn of charge moves return this.end(); } - const moveQueue = this.pokemon.getMoveQueue(); - this.scene.triggerPokemonFormChange(this.pokemon, SpeciesFormChangePreMoveTrigger); if (this.move.moveId)