From e477fccaab2efba4b6efd1e034825858e7b27fec Mon Sep 17 00:00:00 2001 From: innerthunder <168692175+innerthunder@users.noreply.github.com> Date: Wed, 26 Jun 2024 21:41:31 -0700 Subject: [PATCH] [Bug] Fix multi-hit early stopping (#2648) --- src/data/battler-tags.ts | 3 +-- src/field/pokemon.ts | 15 +++++++-------- src/phases.ts | 28 ++++++++++++++++++++++++---- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 766217d36f3..015b8b44984 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -900,8 +900,7 @@ export class ProtectedTag extends BattlerTag { // Stop multi-hit moves early const effectPhase = pokemon.scene.getCurrentPhase(); if (effectPhase instanceof MoveEffectPhase) { - const attacker = effectPhase.getPokemon(); - attacker.stopMultiHit(); + effectPhase.stopMultiHit(pokemon); } return true; } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 8bda55fec4b..b1e7f48d3db 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1800,7 +1800,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } if (cancelled.value) { - source.stopMultiHit(); + source.stopMultiHit(this); result = HitResult.NO_EFFECT; } else { const typeBoost = source.findTag(t => t instanceof TypeBoostTag && t.boostedType === move.type) as TypeBoostTag; @@ -2261,15 +2261,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } /** - * If this Pokemon is using a multi-hit move, stop the move - * after the next hit resolves. + * If this Pokemon is using a multi-hit move, cancels all subsequent strikes + * @param {Pokemon} target If specified, this only cancels subsequent strikes against this Pokemon */ - stopMultiHit(): void { - if (!this.turnData) { - return; + stopMultiHit(target?: Pokemon): void { + const effectPhase = this.scene.getCurrentPhase(); + if (effectPhase instanceof MoveEffectPhase) { + effectPhase.stopMultiHit(target); } - this.turnData.hitCount = 1; - this.turnData.hitsLeft = 1; } changeForm(formChange: SpeciesFormChange): Promise { diff --git a/src/phases.ts b/src/phases.ts index 43208f83743..fcaf3ca4160 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2890,8 +2890,7 @@ export class MoveEffectPhase extends PokemonPhase { const targetHitChecks = Object.fromEntries(targets.map(p => [p.getBattlerIndex(), this.hitCheck(p)])); const activeTargets = targets.map(t => t.isActive(true)); if (!activeTargets.length || (!move.hasAttr(VariableTargetAttr) && !move.isMultiTarget() && !targetHitChecks[this.targets[0]])) { - user.turnData.hitCount = 1; - user.turnData.hitsLeft = 1; + this.stopMultiHit(); if (activeTargets.length) { this.scene.queueMessage(getPokemonMessage(user, "'s\nattack missed!")); moveHistoryEntry.result = MoveResult.MISS; @@ -2910,8 +2909,7 @@ export class MoveEffectPhase extends PokemonPhase { new MoveAnim(move.id as Moves, user, this.getTarget()?.getBattlerIndex()).play(this.scene, () => { for (const target of targets) { if (!targetHitChecks[target.getBattlerIndex()]) { - user.turnData.hitCount = 1; - user.turnData.hitsLeft = 1; + this.stopMultiHit(target); this.scene.queueMessage(getPokemonMessage(user, "'s\nattack missed!")); if (moveHistoryEntry.result === MoveResult.PENDING) { moveHistoryEntry.result = MoveResult.MISS; @@ -3116,6 +3114,28 @@ export class MoveEffectPhase extends PokemonPhase { return this.getTargets().find(() => true); } + removeTarget(target: Pokemon): void { + const targetIndex = this.targets.findIndex(ind => ind === target.getBattlerIndex()); + if (targetIndex !== -1) { + this.targets.splice(this.targets.findIndex(ind => ind === target.getBattlerIndex()), 1); + } + } + + stopMultiHit(target?: Pokemon): void { + /** If given a specific target, remove the target from subsequent strikes */ + if (target) { + this.removeTarget(target); + } + /** + * If no target specified, or the specified target was the last of this move's + * targets, completely cancel all subsequent strikes. + */ + if (!target || this.targets.length === 0 ) { + this.getUserPokemon().turnData.hitCount = 1; + this.getUserPokemon().turnData.hitsLeft = 1; + } + } + getNewHitPhase() { return new MoveEffectPhase(this.scene, this.battlerIndex, this.targets, this.move); }