From e07820db9db29b9677eb0bd82a293ba109e70391 Mon Sep 17 00:00:00 2001 From: Paul Beslin Date: Sat, 4 May 2024 14:19:41 +0200 Subject: [PATCH] Fix moves with switch effect (u-turn) applying opponent abilities (static) on the wrong pokemon --- src/data/move.ts | 6 +++--- src/field/pokemon.ts | 24 ++++-------------------- src/phases.ts | 17 +++++++++++------ 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/src/data/move.ts b/src/data/move.ts index 0b7b1e33c62..dd7f700d033 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -12,7 +12,7 @@ import * as Utils from "../utils"; import { WeatherType } from "./weather"; import { ArenaTagSide, ArenaTrapTag } from "./arena-tag"; import { ArenaTagType } from "./enums/arena-tag-type"; -import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, NoTransformAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr } from "./ability"; +import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr } from "./ability"; import { Abilities } from "./enums/abilities"; import { allAbilities } from './ability'; import { PokemonHeldItemModifier } from "../modifier/modifier"; @@ -448,6 +448,7 @@ export enum MoveEffectTrigger { PRE_APPLY, POST_APPLY, HIT, + POST_HIT, /** Triggers one time after all target effects have applied */ POST_TARGET, } @@ -3000,7 +3001,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { private batonPass: boolean; constructor(user?: boolean, batonPass?: boolean) { - super(false, MoveEffectTrigger.POST_APPLY, true); + super(false, MoveEffectTrigger.POST_HIT, true); this.user = !!user; this.batonPass = !!batonPass; } @@ -3020,7 +3021,6 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { const switchOutTarget = this.user ? user : target; if (switchOutTarget instanceof PlayerPokemon) { if (switchOutTarget.hp) { - applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, switchOutTarget); (switchOutTarget as PlayerPokemon).switchOut(this.batonPass, true).then(() => resolve(true)); } else resolve(false); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 2242b1ee694..d5815df6d26 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -17,7 +17,7 @@ import { initMoveAnim, loadMoveAnimAssets } from '../data/battle-anims'; import { Status, StatusEffect, getRandomStatus } from '../data/status-effect'; import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from '../data/pokemon-evolutions'; import { reverseCompatibleTms, tmSpecies } from '../data/tms'; -import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchSummonPhase } from '../phases'; +import { DamagePhase, FaintPhase, LearnMovePhase, ObtainStatusEffectPhase, StatChangePhase, SwitchPhase } from '../phases'; import { BattleStat } from '../data/battle-stat'; import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from '../data/battler-tags'; import { BattlerTagType } from "../data/enums/battler-tag-type"; @@ -30,10 +30,8 @@ import { Biome } from "../data/enums/biome"; import { Ability, AbAttr, BattleStatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, FieldVariableMovePowerAbAttr, IgnoreOpponentStatChangesAbAttr, MoveImmunityAbAttr, MoveTypeChangeAttr, NonSuperEffectiveImmunityAbAttr, PreApplyBattlerTagAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, VariableMovePowerAbAttr, VariableMoveTypeAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyBattleStatMultiplierAbAttrs, applyPostDefendAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr } from '../data/ability'; import { Abilities } from "#app/data/enums/abilities"; import PokemonData from '../system/pokemon-data'; -import Battle, { BattlerIndex } from '../battle'; +import { BattlerIndex } from '../battle'; import { BattleSpec } from "../enums/battle-spec"; -import { Mode } from '../ui/ui'; -import PartyUiHandler, { PartyOption, PartyUiMode } from '../ui/party-ui-handler'; import SoundFade from 'phaser3-rex-plugins/plugins/soundfade'; import { LevelMoves } from '../data/pokemon-level-moves'; import { DamageAchv, achvs } from '../system/achv'; @@ -2390,22 +2388,8 @@ export class PlayerPokemon extends Pokemon { switchOut(batonPass: boolean, removeFromField: boolean = false): Promise { return new Promise(resolve => { - this.resetTurnData(); - if (!batonPass) - this.resetSummonData(); - this.hideInfo(); - this.setVisible(false); - - this.scene.ui.setMode(Mode.PARTY, PartyUiMode.FAINT_SWITCH, this.getFieldIndex(), (slotIndex: integer, option: PartyOption) => { - if (slotIndex >= this.scene.currentBattle.getBattlerCount() && slotIndex < 6) - this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, this.getFieldIndex(), slotIndex, false, batonPass)); - if (removeFromField) { - this.setVisible(false); - this.scene.field.remove(this); - this.scene.triggerPokemonFormChange(this, SpeciesFormChangeActiveTrigger, true); - } - this.scene.ui.setMode(Mode.MESSAGE).then(() => resolve()); - }, PartyUiHandler.FilterNonFainted); + this.scene.unshiftPhase(new SwitchPhase(this.scene, this.getFieldIndex(), true, removeFromField, batonPass)); + resolve() }); } diff --git a/src/phases.ts b/src/phases.ts index fc6af354a2d..3b4fee5523d 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2474,14 +2474,17 @@ export class MoveEffectPhase extends PokemonPhase { return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move, hitResult).then(() => { if (!user.isPlayer() && this.move.getMove() instanceof AttackMove) user.scene.applyShuffledModifiers(this.scene, EnemyAttackStatusEffectChanceModifier, false, target); - })).then(() => { + })).then(() => applyPostAttackAbAttrs(PostAttackAbAttr, user, target, this.move, hitResult).then(() => { if (this.move.getMove() instanceof AttackMove) this.scene.applyModifiers(ContactHeldItemTransferChanceModifier, this.player, user, target.getFieldIndex()); - resolve(); - }); - }); + }) + ); }) + ).then(() => Utils.executeIf(!chargeEffect, () => applyFilteredMoveAttrs( + (attr: MoveAttr) => attr instanceof MoveEffectAttr && (attr as MoveEffectAttr).trigger === MoveEffectTrigger.POST_HIT + && (!attr.firstHitOnly || firstHit), user, target, this.move.getMove() + )) ).then(() => resolve()); }); } else @@ -3592,13 +3595,15 @@ export class SwitchPhase extends BattlePhase { protected fieldIndex: integer; private isModal: boolean; private doReturn: boolean; + private batonPass: boolean; - constructor(scene: BattleScene, fieldIndex: integer, isModal: boolean, doReturn: boolean) { + constructor(scene: BattleScene, fieldIndex: integer, isModal: boolean, doReturn: boolean, batonPass: boolean = false) { super(scene); this.fieldIndex = fieldIndex; this.isModal = isModal; this.doReturn = doReturn; + this.batonPass = batonPass; } start() { @@ -3613,7 +3618,7 @@ export class SwitchPhase extends BattlePhase { this.scene.ui.setMode(Mode.PARTY, this.isModal ? 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)); + this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, fieldIndex, slotIndex, this.doReturn, option === PartyOption.PASS_BATON || this.batonPass)); this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end()); }, PartyUiHandler.FilterNonFainted); }