From 9a601b80a2dbcf6f85d2e599c94cfb7581f3163d Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Tue, 29 Apr 2025 23:50:36 -0500 Subject: [PATCH] Refactor form change phase --- src/phases/form-change-phase.ts | 270 +++++++++++++++++--------------- 1 file changed, 141 insertions(+), 129 deletions(-) diff --git a/src/phases/form-change-phase.ts b/src/phases/form-change-phase.ts index 13cd410ef87..caf9ca18c26 100644 --- a/src/phases/form-change-phase.ts +++ b/src/phases/form-change-phase.ts @@ -1,9 +1,9 @@ import { globalScene } from "#app/global-scene"; -import { fixedInt } from "#app/utils/common"; +import { FixedInt, fixedInt } from "#app/utils/common"; import { achvs } from "../system/achv"; import type { SpeciesFormChange } from "../data/pokemon-forms"; import { getSpeciesFormChangeMessage } from "#app/data/pokemon-forms/form-change-triggers"; -import type { PlayerPokemon } from "../field/pokemon"; +import type { default as Pokemon, PlayerPokemon } from "../field/pokemon"; import { UiMode } from "#enums/ui-mode"; import type PartyUiHandler from "../ui/party-ui-handler"; import { getPokemonNameWithAffix } from "../messages"; @@ -34,146 +34,158 @@ export class FormChangePhase extends EvolutionPhase { return globalScene.ui.setOverlayMode(UiMode.EVOLUTION_SCENE); } - doEvolution(): void { - const preName = getPokemonNameWithAffix(this.pokemon); - - this.pokemon.getPossibleForm(this.formChange).then(transformedPokemon => { - [this.pokemonEvoSprite, this.pokemonEvoTintSprite].map(sprite => { - const spriteKey = transformedPokemon.getSpriteKey(true); - try { - sprite.play(spriteKey); - } catch (err: unknown) { - console.error(`Failed to play animation for ${spriteKey}`, err); + /** + * Commence the tweens that play after the form change animation finishes + * @param transformedPokemon - The Pokemon after the evolution + * @param preName - The name of the Pokemon before the evolution + */ + private postFormChangeTweens(transformedPokemon: Pokemon, preName: string): void { + globalScene.tweens.chain({ + targets: null, + tweens: [ + { + targets: this.evolutionOverlay, + alpha: 1, + duration: 250, + easing: "Sine.easeIn", + onComplete: () => { + this.evolutionBgOverlay.setAlpha(1); + this.evolutionBg.setVisible(false); + }, + }, + { + targets: [this.evolutionOverlay, this.pokemonEvoTintSprite], + alpha: 0, + duration: 2000, + delay: 150, + easing: "Sine.easeIn", + }, + { + targets: this.evolutionBgOverlay, + alpha: 0, + duration: 250, + completeDelay: 250, + onComplete: () => this.pokemon.cry(), + }, + ], + // 1.25 seconds after the pokemon cry + completeDelay: 1250, + onComplete: () => { + let playEvolutionFanfare = false; + if (this.formChange.formKey.indexOf(SpeciesFormKey.MEGA) > -1) { + globalScene.validateAchv(achvs.MEGA_EVOLVE); + playEvolutionFanfare = true; + } else if ( + this.formChange.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1 || + this.formChange.formKey.indexOf(SpeciesFormKey.ETERNAMAX) > -1 + ) { + globalScene.validateAchv(achvs.GIGANTAMAX); + playEvolutionFanfare = true; } - sprite.setPipelineData("ignoreTimeTint", true); - sprite.setPipelineData("spriteKey", transformedPokemon.getSpriteKey()); - sprite.setPipelineData("shiny", transformedPokemon.shiny); - sprite.setPipelineData("variant", transformedPokemon.variant); - ["spriteColors", "fusionSpriteColors"].map(k => { - if (transformedPokemon.summonData.speciesForm) { - k += "Base"; - } - sprite.pipelineData[k] = transformedPokemon.getSprite().pipelineData[k]; - }); - }); + const delay = playEvolutionFanfare ? 4000 : 1750; + globalScene.playSoundWithoutBgm(playEvolutionFanfare ? "evolution_fanfare" : "minor_fanfare"); + transformedPokemon.destroy(); + globalScene.ui.showText( + getSpeciesFormChangeMessage(this.pokemon, this.formChange, preName), + null, + () => this.end(), + null, + true, + fixedInt(delay), + ); + globalScene.time.delayedCall(fixedInt(delay + 250), () => globalScene.playBgm()); + }, + }); + } - globalScene.time.delayedCall(250, () => { - globalScene.tweens.add({ + /** + * Commence the animations that occur once the form change evolution cycle ({@linkcode doCycle}) is complete + * + * @privateRemarks + * This would prefer {@linkcode doCycle} to be refactored and de-promisified so this can be moved into {@linkcode beginTweens} + * @param preName - The name of the Pokemon before the evolution + * @param transformedPokemon - The Pokemon being transformed into + */ + private afterCycle(preName: string, transformedPokemon: Pokemon): void { + globalScene.playSound("se/sparkle"); + this.pokemonEvoSprite.setVisible(true); + this.doCircleInward(); + globalScene.time.delayedCall(900, () => { + this.pokemon.changeForm(this.formChange).then(() => { + if (!this.modal) { + globalScene.phaseManager.unshiftNew("EndEvolutionPhase"); + } + globalScene.playSound("se/shine"); + this.doSpray(); + this.postFormChangeTweens(transformedPokemon, preName); + }); + }); + } + + /** + * Commence the sequence of tweens and events that occur during the evolution animation + * @param preName The name of the Pokemon before the evolution + * @param transformedPokemon The Pokemon after the evolution + */ + private beginTweens(preName: string, transformedPokemon: Pokemon): void { + globalScene.tweens.chain({ + // Starts 250ms after sprites have been configured + delay: 250, + targets: null, + tweens: [ + // Step 1: Fade in the background overlay + { targets: this.evolutionBgOverlay, alpha: 1, - delay: 500, duration: 1500, ease: "Sine.easeOut", + // We want the backkground overlay to fade out after it fades in onComplete: () => { - globalScene.time.delayedCall(1000, () => { - globalScene.tweens.add({ - targets: this.evolutionBgOverlay, - alpha: 0, - duration: 250, - }); - this.evolutionBg.setVisible(true); - this.evolutionBg.play(); + globalScene.tweens.add({ + targets: this.evolutionBgOverlay, + alpha: 0, + duration: 250, + delay: fixedInt(1000), }); + this.evolutionBg.setVisible(true).play(); + }, + }, + // Step 2: Play the sounds and fade in the tint sprite + { + targets: this.pokemonTintSprite, + alpha: { from: 0, to: 1 }, + duration: 2000, + onStart: () => { globalScene.playSound("se/charge"); this.doSpiralUpward(); - globalScene.tweens.addCounter({ - from: 0, - to: 1, - duration: 2000, - onUpdate: t => { - this.pokemonTintSprite.setAlpha(t.getValue()); - }, - onComplete: () => { - this.pokemonSprite.setVisible(false); - globalScene.time.delayedCall(1100, () => { - globalScene.playSound("se/beam"); - this.doArcDownward(); - globalScene.time.delayedCall(1000, () => { - this.pokemonEvoTintSprite.setScale(0.25); - this.pokemonEvoTintSprite.setVisible(true); - this.doCycle(1, 1).then(_success => { - globalScene.playSound("se/sparkle"); - this.pokemonEvoSprite.setVisible(true); - this.doCircleInward(); - globalScene.time.delayedCall(900, () => { - this.pokemon.changeForm(this.formChange).then(() => { - if (!this.modal) { - globalScene.phaseManager.unshiftNew("EndEvolutionPhase"); - } - - globalScene.playSound("se/shine"); - this.doSpray(); - globalScene.tweens.add({ - targets: this.evolutionOverlay, - alpha: 1, - duration: 250, - easing: "Sine.easeIn", - onComplete: () => { - this.evolutionBgOverlay.setAlpha(1); - this.evolutionBg.setVisible(false); - globalScene.tweens.add({ - targets: [this.evolutionOverlay, this.pokemonEvoTintSprite], - alpha: 0, - duration: 2000, - delay: 150, - easing: "Sine.easeIn", - onComplete: () => { - globalScene.tweens.add({ - targets: this.evolutionBgOverlay, - alpha: 0, - duration: 250, - onComplete: () => { - globalScene.time.delayedCall(250, () => { - this.pokemon.cry(); - globalScene.time.delayedCall(1250, () => { - let playEvolutionFanfare = false; - if (this.formChange.formKey.indexOf(SpeciesFormKey.MEGA) > -1) { - globalScene.validateAchv(achvs.MEGA_EVOLVE); - playEvolutionFanfare = true; - } else if ( - this.formChange.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1 || - this.formChange.formKey.indexOf(SpeciesFormKey.ETERNAMAX) > -1 - ) { - globalScene.validateAchv(achvs.GIGANTAMAX); - playEvolutionFanfare = true; - } - - const delay = playEvolutionFanfare ? 4000 : 1750; - globalScene.playSoundWithoutBgm( - playEvolutionFanfare ? "evolution_fanfare" : "minor_fanfare", - ); - - transformedPokemon.destroy(); - globalScene.ui.showText( - getSpeciesFormChangeMessage(this.pokemon, this.formChange, preName), - null, - () => this.end(), - null, - true, - fixedInt(delay), - ); - globalScene.time.delayedCall(fixedInt(delay + 250), () => - globalScene.playBgm(), - ); - }); - }); - }, - }); - }, - }); - }, - }); - }); - }); - }); - }); - }); - }, - }); }, + onComplete: () => { + this.pokemonSprite.setVisible(false); + }, + }, + ], + + // Step 3: Commence the form change animation via doCycle then continue the animation chain with afterCycle + completeDelay: new FixedInt(1100), + onComplete: () => { + globalScene.playSound("se/beam"); + this.doArcDownward(); + globalScene.time.delayedCall(1000, () => { + this.pokemonEvoTintSprite.setScale(0.25).setVisible(true); + this.doCycle(1, 1).then(() => this.afterCycle(preName, transformedPokemon)); }); - }); + }, + }); + } + + doEvolution(): void { + const preName = getPokemonNameWithAffix(this.pokemon, false); + + this.pokemon.getPossibleForm(this.formChange).then(transformedPokemon => { + this.configureSprite(transformedPokemon, this.pokemonEvoSprite, false); + this.configureSprite(transformedPokemon, this.pokemonEvoTintSprite, false); + this.beginTweens(preName, transformedPokemon); }); }