[Refactor] Refactored duplicated code into a common Pokemon#leaveField() function (#3310)

* refactor duplicated code into leaveField function

* replace bugfix code
This commit is contained in:
Alex Van Liew 2024-08-03 12:13:42 -07:00 committed by GitHub
parent bb6ec94c02
commit a2a1f3ec24
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 49 additions and 51 deletions

View File

@ -13,10 +13,9 @@ import { ArenaTagSide, ArenaTrapTag, WeakenMoveTypeTag } from "./arena-tag";
import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr, HealFromBerryUseAbAttr, IgnoreProtectOnContactAbAttr, IgnoreMoveEffectsAbAttr, applyPreDefendAbAttrs, MoveEffectChanceMultiplierAbAttr, WonderSkinAbAttr, applyPreAttackAbAttrs, MoveTypeChangeAttr, UserFieldMoveTypePowerBoostAbAttr, FieldMoveTypePowerBoostAbAttr, AllyMoveCategoryPowerBoostAbAttr, VariableMovePowerAbAttr } from "./ability"; import { UnswappableAbilityAbAttr, UncopiableAbilityAbAttr, UnsuppressableAbilityAbAttr, BlockRecoilDamageAttr, BlockOneHitKOAbAttr, IgnoreContactAbAttr, MaxMultiHitAbAttr, applyAbAttrs, BlockNonDirectDamageAbAttr, applyPreSwitchOutAbAttrs, PreSwitchOutAbAttr, applyPostDefendAbAttrs, PostDefendContactApplyStatusEffectAbAttr, MoveAbilityBypassAbAttr, ReverseDrainAbAttr, FieldPreventExplosiveMovesAbAttr, ForceSwitchOutImmunityAbAttr, BlockItemTheftAbAttr, applyPostAttackAbAttrs, ConfusionOnStatusEffectAbAttr, HealFromBerryUseAbAttr, IgnoreProtectOnContactAbAttr, IgnoreMoveEffectsAbAttr, applyPreDefendAbAttrs, MoveEffectChanceMultiplierAbAttr, WonderSkinAbAttr, applyPreAttackAbAttrs, MoveTypeChangeAttr, UserFieldMoveTypePowerBoostAbAttr, FieldMoveTypePowerBoostAbAttr, AllyMoveCategoryPowerBoostAbAttr, VariableMovePowerAbAttr } from "./ability";
import { allAbilities } from "./ability"; import { allAbilities } from "./ability";
import { PokemonHeldItemModifier, BerryModifier, PreserveBerryModifier, PokemonMoveAccuracyBoosterModifier, AttackTypeBoosterModifier, PokemonMultiHitModifier } from "../modifier/modifier"; import { PokemonHeldItemModifier, BerryModifier, PreserveBerryModifier, PokemonMoveAccuracyBoosterModifier, AttackTypeBoosterModifier, PokemonMultiHitModifier } from "../modifier/modifier";
import { BattlerIndex } from "../battle"; import { BattlerIndex, BattleType } from "../battle";
import { Stat } from "./pokemon-stat"; import { Stat } from "./pokemon-stat";
import { TerrainType } from "./terrain"; import { TerrainType } from "./terrain";
import { SpeciesFormChangeActiveTrigger } from "./pokemon-forms";
import { ModifierPoolType } from "#app/modifier/modifier-type"; import { ModifierPoolType } from "#app/modifier/modifier-type";
import { Command } from "../ui/command-ui-handler"; import { Command } from "../ui/command-ui-handler";
import i18next from "i18next"; import i18next from "i18next";
@ -1817,13 +1816,10 @@ export class MultiHitAttr extends MoveAttr {
} }
case MultiHitType._2: case MultiHitType._2:
return 2; return 2;
break;
case MultiHitType._3: case MultiHitType._3:
return 3; return 3;
break;
case MultiHitType._10: case MultiHitType._10:
return 10; return 10;
break;
case MultiHitType.BEAT_UP: case MultiHitType.BEAT_UP:
const party = user.isPlayer() ? user.scene.getParty() : user.scene.getEnemyParty(); const party = user.isPlayer() ? user.scene.getParty() : user.scene.getEnemyParty();
// No status means the ally pokemon can contribute to Beat Up // No status means the ally pokemon can contribute to Beat Up
@ -4780,19 +4776,14 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
if (switchOutTarget.hp > 0) { if (switchOutTarget.hp > 0) {
applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, switchOutTarget); applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, switchOutTarget);
// switchOut below sets the UI to select party(this is not a separate Phase), then adds a SwitchSummonPhase with selected 'mon // switchOut below sets the UI to select party(this is not a separate Phase), then adds a SwitchSummonPhase with selected 'mon
(switchOutTarget as PlayerPokemon).switchOut(this.batonPass, true).then(() => resolve(true)); (switchOutTarget as PlayerPokemon).switchOut(this.batonPass).then(() => resolve(true));
} else { } else {
resolve(false); resolve(false);
} }
return; return;
} else if (user.scene.currentBattle.battleType) { } else if (user.scene.currentBattle.battleType !== BattleType.WILD) {
// Switch out logic for the battle type // Switch out logic for trainer battles
switchOutTarget.resetTurnData(); switchOutTarget.leaveField(!this.batonPass);
switchOutTarget.resetSummonData();
switchOutTarget.hideInfo();
switchOutTarget.setVisible(false);
switchOutTarget.scene.field.remove(switchOutTarget);
user.scene.triggerPokemonFormChange(switchOutTarget, SpeciesFormChangeActiveTrigger, true);
if (switchOutTarget.hp > 0) { if (switchOutTarget.hp > 0) {
// for opponent switching out // for opponent switching out

View File

@ -3161,6 +3161,23 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return this.randSeedInt((max - min) + 1, min); return this.randSeedInt((max - min) + 1, min);
} }
/**
* Causes a Pokemon to leave the field (such as in preparation for a switch out/escape).
* @param clearEffects Indicates if effects should be cleared (true) or passed
* to the next pokemon, such as during a baton pass (false)
*/
leaveField(clearEffects: boolean = true) {
this.resetTurnData();
if (clearEffects) {
this.resetSummonData();
this.resetBattleData();
}
this.hideInfo();
this.setVisible(false);
this.scene.field.remove(this);
this.scene.triggerPokemonFormChange(this, SpeciesFormChangeActiveTrigger, true);
}
destroy(): void { destroy(): void {
this.battleInfo?.destroy(); this.battleInfo?.destroy();
super.destroy(); super.destroy();
@ -3272,25 +3289,21 @@ export class PlayerPokemon extends Pokemon {
return true; return true;
} }
switchOut(batonPass: boolean, removeFromField: boolean = false): Promise<void> { /**
* Causes this mon to leave the field (via {@linkcode leaveField}) and then
* opens the party switcher UI to switch a new mon in
* @param batonPass Indicates if this switch was caused by a baton pass (and
* thus should maintain active mon effects)
*/
switchOut(batonPass: boolean): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
this.resetTurnData(); this.leaveField(!batonPass);
if (!batonPass) {
this.resetSummonData();
}
this.hideInfo();
this.setVisible(false);
this.scene.ui.setMode(Mode.PARTY, PartyUiMode.FAINT_SWITCH, this.getFieldIndex(), (slotIndex: integer, option: PartyOption) => { this.scene.ui.setMode(Mode.PARTY, PartyUiMode.FAINT_SWITCH, this.getFieldIndex(), (slotIndex: integer, option: PartyOption) => {
if (slotIndex >= this.scene.currentBattle.getBattlerCount() && slotIndex < 6) { if (slotIndex >= this.scene.currentBattle.getBattlerCount() && slotIndex < 6) {
this.scene.prependToPhase(new SwitchSummonPhase(this.scene, this.getFieldIndex(), slotIndex, false, batonPass), MoveEndPhase); this.scene.prependToPhase(new SwitchSummonPhase(this.scene, this.getFieldIndex(), slotIndex, false, batonPass), MoveEndPhase);
} }
if (removeFromField) { this.scene.ui.setMode(Mode.MESSAGE).then(resolve);
this.setVisible(false);
this.scene.field.remove(this);
this.scene.triggerPokemonFormChange(this, SpeciesFormChangeActiveTrigger, true);
}
this.scene.ui.setMode(Mode.MESSAGE).then(() => resolve());
}, PartyUiHandler.FilterNonFainted); }, PartyUiHandler.FilterNonFainted);
}); });
} }

View File

@ -1392,10 +1392,7 @@ export class SummonPhase extends PartyMemberPokemonPhase {
// First check if they're somehow still in play, if so remove them. // First check if they're somehow still in play, if so remove them.
if (partyMember.isOnField()) { if (partyMember.isOnField()) {
partyMember.hideInfo(); partyMember.leaveField();
partyMember.setVisible(false);
this.scene.field.remove(partyMember);
this.scene.triggerPokemonFormChange(partyMember, SpeciesFormChangeActiveTrigger, true);
} }
const party = this.getParty(); const party = this.getParty();
@ -1611,7 +1608,7 @@ export class SwitchSummonPhase extends SummonPhase {
}) })
); );
this.scene.playSound("pb_rel"); this.scene.playSound("pb_rel");
pokemon.hideInfo(); pokemon.hideInfo(); // this is also done by pokemon.leaveField(), but needs to go earlier for animation purposes
pokemon.tint(getPokeballTintColor(pokemon.pokeball), 1, 250, "Sine.easeIn"); pokemon.tint(getPokeballTintColor(pokemon.pokeball), 1, 250, "Sine.easeIn");
this.scene.tweens.add({ this.scene.tweens.add({
targets: pokemon, targets: pokemon,
@ -1619,9 +1616,9 @@ export class SwitchSummonPhase extends SummonPhase {
ease: "Sine.easeIn", ease: "Sine.easeIn",
scale: 0.5, scale: 0.5,
onComplete: () => { onComplete: () => {
pokemon.setVisible(false); // 250ms delay on leaveField is necessary to avoid calling hideInfo() twice
this.scene.field.remove(pokemon); // and double-animating the stats panel slideout
this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true); this.scene.time.delayedCall(250, () => pokemon.leaveField(!this.batonPass));
this.scene.time.delayedCall(750, () => this.switchAndSummon()); this.scene.time.delayedCall(750, () => this.switchAndSummon());
} }
}); });
@ -1629,25 +1626,25 @@ export class SwitchSummonPhase extends SummonPhase {
switchAndSummon() { switchAndSummon() {
const party = this.player ? this.getParty() : this.scene.getEnemyParty(); const party = this.player ? this.getParty() : this.scene.getEnemyParty();
const switchedPokemon = party[this.slotIndex]; const switchedInPokemon = party[this.slotIndex];
this.lastPokemon = this.getPokemon(); this.lastPokemon = this.getPokemon();
applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, this.lastPokemon); applyPreSwitchOutAbAttrs(PreSwitchOutAbAttr, this.lastPokemon);
if (this.batonPass && switchedPokemon) { if (this.batonPass && switchedInPokemon) {
(this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.transferTagsBySourceId(this.lastPokemon.id, switchedPokemon.id)); (this.player ? this.scene.getEnemyField() : this.scene.getPlayerField()).forEach(enemyPokemon => enemyPokemon.transferTagsBySourceId(this.lastPokemon.id, switchedInPokemon.id));
if (!this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === switchedPokemon.id)) { if (!this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === switchedInPokemon.id)) {
const batonPassModifier = this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier const batonPassModifier = this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier
&& (m as SwitchEffectTransferModifier).pokemonId === this.lastPokemon.id) as SwitchEffectTransferModifier; && (m as SwitchEffectTransferModifier).pokemonId === this.lastPokemon.id) as SwitchEffectTransferModifier;
if (batonPassModifier && !this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === switchedPokemon.id)) { if (batonPassModifier && !this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === switchedInPokemon.id)) {
this.scene.tryTransferHeldItemModifier(batonPassModifier, switchedPokemon, false); this.scene.tryTransferHeldItemModifier(batonPassModifier, switchedInPokemon, false);
} }
} }
} }
if (switchedPokemon) { if (switchedInPokemon) {
party[this.slotIndex] = this.lastPokemon; party[this.slotIndex] = this.lastPokemon;
party[this.fieldIndex] = switchedPokemon; party[this.fieldIndex] = switchedInPokemon;
const showTextAndSummon = () => { const showTextAndSummon = () => {
this.scene.ui.showText(this.player ? this.scene.ui.showText(this.player ?
i18next.t("battle:playerGo", { pokemonName: getPokemonNameWithAffix(switchedPokemon) }) : i18next.t("battle:playerGo", { pokemonName: getPokemonNameWithAffix(switchedInPokemon) }) :
i18next.t("battle:trainerGo", { i18next.t("battle:trainerGo", {
trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER), trainerName: this.scene.currentBattle.trainer.getName(!(this.fieldIndex % 2) ? TrainerSlot.TRAINER : TrainerSlot.TRAINER_PARTNER),
pokemonName: this.getPokemon().getNameToRender() pokemonName: this.getPokemon().getNameToRender()
@ -1655,8 +1652,8 @@ export class SwitchSummonPhase extends SummonPhase {
); );
// Ensure improperly persisted summon data (such as tags) is cleared upon switching // Ensure improperly persisted summon data (such as tags) is cleared upon switching
if (!this.batonPass) { if (!this.batonPass) {
party[this.fieldIndex].resetBattleData(); switchedInPokemon.resetBattleData();
party[this.fieldIndex].resetSummonData(); switchedInPokemon.resetSummonData();
} }
this.summon(); this.summon();
}; };
@ -1876,14 +1873,11 @@ export class TurnInitPhase extends FieldPhase {
this.scene.unshiftPhase(new GameOverPhase(this.scene)); this.scene.unshiftPhase(new GameOverPhase(this.scene));
} else if (allowedPokemon.length >= this.scene.currentBattle.getBattlerCount() || (this.scene.currentBattle.double && !allowedPokemon[0].isActive(true))) { } else if (allowedPokemon.length >= this.scene.currentBattle.getBattlerCount() || (this.scene.currentBattle.double && !allowedPokemon[0].isActive(true))) {
// If there is at least one pokemon in the back that is legal to switch in, force a switch. // If there is at least one pokemon in the back that is legal to switch in, force a switch.
p.switchOut(false, true); p.switchOut(false);
} else { } else {
// If there are no pokemon in the back but we're not game overing, just hide the pokemon. // If there are no pokemon in the back but we're not game overing, just hide the pokemon.
// This should only happen in double battles. // This should only happen in double battles.
p.hideInfo(); p.leaveField();
p.setVisible(false);
this.scene.field.remove(p);
this.scene.triggerPokemonFormChange(p, SpeciesFormChangeActiveTrigger, true);
} }
if (allowedPokemon.length === 1 && this.scene.currentBattle.double) { if (allowedPokemon.length === 1 && this.scene.currentBattle.double) {
this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true)); this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true));