Fix moves with switch effect (u-turn) applying opponent abilities (static) on the wrong pokemon

This commit is contained in:
Paul Beslin 2024-05-04 14:19:41 +02:00
parent bde7620ac0
commit e07820db9d
3 changed files with 18 additions and 29 deletions

View File

@ -12,7 +12,7 @@ import * as Utils from "../utils";
import { WeatherType } from "./weather"; import { WeatherType } from "./weather";
import { ArenaTagSide, ArenaTrapTag } from "./arena-tag"; import { ArenaTagSide, ArenaTrapTag } from "./arena-tag";
import { ArenaTagType } from "./enums/arena-tag-type"; 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 { Abilities } from "./enums/abilities";
import { allAbilities } from './ability'; import { allAbilities } from './ability';
import { PokemonHeldItemModifier } from "../modifier/modifier"; import { PokemonHeldItemModifier } from "../modifier/modifier";
@ -448,6 +448,7 @@ export enum MoveEffectTrigger {
PRE_APPLY, PRE_APPLY,
POST_APPLY, POST_APPLY,
HIT, HIT,
POST_HIT,
/** Triggers one time after all target effects have applied */ /** Triggers one time after all target effects have applied */
POST_TARGET, POST_TARGET,
} }
@ -3000,7 +3001,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
private batonPass: boolean; private batonPass: boolean;
constructor(user?: boolean, batonPass?: boolean) { constructor(user?: boolean, batonPass?: boolean) {
super(false, MoveEffectTrigger.POST_APPLY, true); super(false, MoveEffectTrigger.POST_HIT, true);
this.user = !!user; this.user = !!user;
this.batonPass = !!batonPass; this.batonPass = !!batonPass;
} }
@ -3020,7 +3021,6 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
const switchOutTarget = this.user ? user : target; const switchOutTarget = this.user ? user : target;
if (switchOutTarget instanceof PlayerPokemon) { if (switchOutTarget instanceof PlayerPokemon) {
if (switchOutTarget.hp) { if (switchOutTarget.hp) {
applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, switchOutTarget);
(switchOutTarget as PlayerPokemon).switchOut(this.batonPass, true).then(() => resolve(true)); (switchOutTarget as PlayerPokemon).switchOut(this.batonPass, true).then(() => resolve(true));
} else } else
resolve(false); resolve(false);

View File

@ -17,7 +17,7 @@ import { initMoveAnim, loadMoveAnimAssets } from '../data/battle-anims';
import { Status, StatusEffect, getRandomStatus } from '../data/status-effect'; import { Status, StatusEffect, getRandomStatus } from '../data/status-effect';
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from '../data/pokemon-evolutions'; import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from '../data/pokemon-evolutions';
import { reverseCompatibleTms, tmSpecies } from '../data/tms'; 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 { BattleStat } from '../data/battle-stat';
import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from '../data/battler-tags'; import { BattlerTag, BattlerTagLapseType, EncoreTag, HelpingHandTag, HighestStatBoostTag, TypeBoostTag, getBattlerTag } from '../data/battler-tags';
import { BattlerTagType } from "../data/enums/battler-tag-type"; 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 { 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 { Abilities } from "#app/data/enums/abilities";
import PokemonData from '../system/pokemon-data'; import PokemonData from '../system/pokemon-data';
import Battle, { BattlerIndex } from '../battle'; import { BattlerIndex } from '../battle';
import { BattleSpec } from "../enums/battle-spec"; 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 SoundFade from 'phaser3-rex-plugins/plugins/soundfade';
import { LevelMoves } from '../data/pokemon-level-moves'; import { LevelMoves } from '../data/pokemon-level-moves';
import { DamageAchv, achvs } from '../system/achv'; import { DamageAchv, achvs } from '../system/achv';
@ -2390,22 +2388,8 @@ export class PlayerPokemon extends Pokemon {
switchOut(batonPass: boolean, removeFromField: boolean = false): Promise<void> { switchOut(batonPass: boolean, removeFromField: boolean = false): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
this.resetTurnData(); this.scene.unshiftPhase(new SwitchPhase(this.scene, this.getFieldIndex(), true, removeFromField, batonPass));
if (!batonPass) resolve()
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);
}); });
} }

View File

@ -2474,14 +2474,17 @@ export class MoveEffectPhase extends PokemonPhase {
return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move, hitResult).then(() => { return Utils.executeIf(!target.isFainted() || target.canApplyAbility(), () => applyPostDefendAbAttrs(PostDefendAbAttr, target, user, this.move, hitResult).then(() => {
if (!user.isPlayer() && this.move.getMove() instanceof AttackMove) if (!user.isPlayer() && this.move.getMove() instanceof AttackMove)
user.scene.applyShuffledModifiers(this.scene, EnemyAttackStatusEffectChanceModifier, false, target); user.scene.applyShuffledModifiers(this.scene, EnemyAttackStatusEffectChanceModifier, false, target);
})).then(() => { })).then(() =>
applyPostAttackAbAttrs(PostAttackAbAttr, user, target, this.move, hitResult).then(() => { applyPostAttackAbAttrs(PostAttackAbAttr, user, target, this.move, hitResult).then(() => {
if (this.move.getMove() instanceof AttackMove) if (this.move.getMove() instanceof AttackMove)
this.scene.applyModifiers(ContactHeldItemTransferChanceModifier, this.player, user, target.getFieldIndex()); 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()); ).then(() => resolve());
}); });
} else } else
@ -3592,13 +3595,15 @@ export class SwitchPhase extends BattlePhase {
protected fieldIndex: integer; protected fieldIndex: integer;
private isModal: boolean; private isModal: boolean;
private doReturn: 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); super(scene);
this.fieldIndex = fieldIndex; this.fieldIndex = fieldIndex;
this.isModal = isModal; this.isModal = isModal;
this.doReturn = doReturn; this.doReturn = doReturn;
this.batonPass = batonPass;
} }
start() { 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) => { 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) 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()); this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end());
}, PartyUiHandler.FilterNonFainted); }, PartyUiHandler.FilterNonFainted);
} }