Refactor form change phase

This commit is contained in:
Sirz Benjie 2025-04-29 23:50:36 -05:00
parent 75511354ee
commit 9a601b80a2
No known key found for this signature in database
GPG Key ID: 38AC42D68CF5E138

View File

@ -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,77 +34,16 @@ 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);
}
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];
});
});
globalScene.time.delayedCall(250, () => {
globalScene.tweens.add({
targets: this.evolutionBgOverlay,
alpha: 1,
delay: 500,
duration: 1500,
ease: "Sine.easeOut",
onComplete: () => {
globalScene.time.delayedCall(1000, () => {
globalScene.tweens.add({
targets: this.evolutionBgOverlay,
alpha: 0,
duration: 250,
});
this.evolutionBg.setVisible(true);
this.evolutionBg.play();
});
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({
/**
* 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,
@ -112,21 +51,26 @@ export class FormChangePhase extends EvolutionPhase {
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,
completeDelay: 250,
onComplete: () => this.pokemon.cry(),
},
],
// 1.25 seconds after the pokemon cry
completeDelay: 1250,
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);
@ -140,10 +84,7 @@ export class FormChangePhase extends EvolutionPhase {
}
const delay = playEvolutionFanfare ? 4000 : 1750;
globalScene.playSoundWithoutBgm(
playEvolutionFanfare ? "evolution_fanfare" : "minor_fanfare",
);
globalScene.playSoundWithoutBgm(playEvolutionFanfare ? "evolution_fanfare" : "minor_fanfare");
transformedPokemon.destroy();
globalScene.ui.showText(
getSpeciesFormChangeMessage(this.pokemon, this.formChange, preName),
@ -153,27 +94,98 @@ export class FormChangePhase extends EvolutionPhase {
true,
fixedInt(delay),
);
globalScene.time.delayedCall(fixedInt(delay + 250), () =>
globalScene.playBgm(),
);
globalScene.time.delayedCall(fixedInt(delay + 250), () => globalScene.playBgm());
},
});
}
/**
* 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,
duration: 1500,
ease: "Sine.easeOut",
// We want the backkground overlay to fade out after it fades in
onComplete: () => {
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();
},
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);
});
}