Ensure shiny sparkle animation is initialized before playing it (Fixes #3924)

This commit is contained in:
Moka 2024-11-09 15:47:28 +01:00
parent 2bb7888cb6
commit 9fe58c52e2
5 changed files with 52 additions and 31 deletions

View File

@ -26,6 +26,7 @@ import { trainerNamePools } from "#app/data/trainer-names";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
import { addPokemonDataToDexAndValidateAchievements } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
import type { PokeballType } from "#enums/pokeball";
import { doShinySparkleAnim } from "#app/field/anims";
/** the i18n namespace for the encounter */
const namespace = "mysteryEncounters/globalTradeSystem";
@ -846,8 +847,7 @@ function doTradeReceivedSequence(scene: BattleScene, receivedPokemon: PlayerPoke
onComplete: () => {
if (receivedPokemon.shiny) {
scene.time.delayedCall(500, () => {
pokemonShinySparkle.play(`sparkle${receivedPokemon.variant ? `_${receivedPokemon.variant + 1}` : ""}`);
scene.playSound("se/sparkle");
doShinySparkleAnim(scene, pokemonShinySparkle, receivedPokemon.variant);
});
}
receivedPokeballSprite.destroy();

View File

@ -1,6 +1,7 @@
import BattleScene from "../battle-scene";
import BattleScene from "#app/battle-scene";
import { PokeballType } from "#enums/pokeball";
import * as Utils from "../utils";
import { Variant } from "#app/data/variant";
import { getFrameMs, randGauss } from "#app/utils";
export function addPokeballOpenParticles(scene: BattleScene, x: number, y: number, pokeballType: PokeballType): void {
switch (pokeballType) {
@ -127,7 +128,7 @@ function doFanOutParticle(scene: BattleScene, trigIndex: integer, x: integer, y:
const particleTimer = scene.tweens.addCounter({
repeat: -1,
duration: Utils.getFrameMs(1),
duration: getFrameMs(1),
onRepeat: () => {
updateParticle();
}
@ -159,7 +160,7 @@ export function addPokeballCaptureStars(scene: BattleScene, pokeball: Phaser.Gam
}
});
const dist = Utils.randGauss(25);
const dist = randGauss(25);
scene.tweens.add({
targets: particle,
x: pokeball.x + dist,
@ -185,3 +186,31 @@ export function sin(index: integer, amplitude: integer): number {
export function cos(index: integer, amplitude: integer): number {
return amplitude * Math.cos(index * (Math.PI / 128));
}
/**
* Play the shiny sparkle animation and sound effect for the given sprite
* First ensures that the animation has been properly initialized
* @param sparkleSprite the Sprite to play the animation on
* @param variant which shiny {@linkcode variant} to play the animation for
*/
export function doShinySparkleAnim(scene: BattleScene, sparkleSprite: Phaser.GameObjects.Sprite, variant: Variant) {
const keySuffix = variant ? `_${variant + 1}` : "";
const spriteKey = `shiny${keySuffix}`;
const animationKey = `sparkle${keySuffix}`;
// Make sure the animation exists, and create it if not
if (!scene.anims.exists(animationKey)) {
const frameNames = scene.anims.generateFrameNames(spriteKey, { suffix: ".png", end: 34 });
scene.anims.create({
key: `sparkle${keySuffix}`,
frames: frameNames,
frameRate: 32,
showOnStart: true,
hideOnComplete: true,
});
}
// Play the animation
sparkleSprite.play(animationKey);
scene.playSound("se/sparkle");
}

View File

@ -1,11 +1,12 @@
import { GameObjects } from "phaser";
import BattleScene from "../battle-scene";
import MysteryEncounter from "../data/mystery-encounters/mystery-encounter";
import BattleScene from "#app/battle-scene";
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
import { Species } from "#enums/species";
import { isNullOrUndefined } from "#app/utils";
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
import PlayAnimationConfig = Phaser.Types.Animations.PlayAnimationConfig;
import { Variant, variantColorCache, variantData, VariantSet } from "#app/data/variant";
import { doShinySparkleAnim } from "#app/field/anims";
type KnownFileRoot =
| "arenas"
@ -294,12 +295,18 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
this.getSprites().map((sprite, i) => {
if (!this.spriteConfigs[i].isItem) {
sprite.setTexture(this.spriteConfigs[i].spriteKey).setFrame(0);
sprite.setTexture(this.spriteConfigs[i].spriteKey);
// Show the first frame for a smooth transition when the animation starts.
const firstFrame = sprite.texture.frames["0001.png"];
sprite.setFrame(firstFrame ?? 0);
}
});
this.getTintSprites().map((tintSprite, i) => {
if (!this.spriteConfigs[i].isItem) {
tintSprite.setTexture(this.spriteConfigs[i].spriteKey).setFrame(0);
tintSprite.setTexture(this.spriteConfigs[i].spriteKey);
// Show the first frame for a smooth transition when the animation starts.
const firstFrame = tintSprite.texture.frames["0001.png"];
tintSprite.setFrame(firstFrame ?? 0);
}
});
@ -349,8 +356,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
playShinySparkles() {
for (const sparkleConfig of this.shinySparkleSprites) {
this.scene.time.delayedCall(500, () => {
sparkleConfig.sprite.play(`sparkle${sparkleConfig.variant ? `_${sparkleConfig.variant + 1}` : ""}`);
this.scene.playSound("se/sparkle");
doShinySparkleAnim(this.scene, sparkleConfig.sprite, sparkleConfig.variant);
});
}
}

View File

@ -69,6 +69,7 @@ import { SpeciesFormKey } from "#enums/species-form-key";
import { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE, SHINY_EPIC_CHANCE, SHINY_VARIANT_CHANCE } from "#app/data/balance/rates";
import { Nature } from "#enums/nature";
import { StatusEffect } from "#enums/status-effect";
import { doShinySparkleAnim } from "#app/field/anims";
export enum FieldPosition {
CENTER,
@ -668,22 +669,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}
initShinySparkle(): void {
// TODO
const keySuffix = this.variant ? `_${this.variant + 1}` : "";
const key = `shiny${keySuffix}`;
const shinySparkle = this.scene.addFieldSprite(0, 0, key);
const shinySparkle = this.scene.addFieldSprite(0, 0, "shiny");
shinySparkle.setVisible(false);
shinySparkle.setOrigin(0.5, 1);
const frameNames = this.scene.anims.generateFrameNames(key, { suffix: ".png", end: 34 });
if (!(this.scene.anims.exists(`sparkle${keySuffix}`))) {
this.scene.anims.create({
key: `sparkle${keySuffix}`,
frames: frameNames,
frameRate: 32,
showOnStart: true,
hideOnComplete: true,
});
}
this.add(shinySparkle);
this.shinySparkle = shinySparkle;
@ -3746,8 +3734,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
sparkle(): void {
if (this.shinySparkle) {
this.shinySparkle.play(`sparkle${this.variant ? `_${this.variant + 1}` : ""}`);
this.scene.playSound("se/sparkle");
doShinySparkleAnim(this.scene, this.shinySparkle, this.variant);
}
}

View File

@ -14,6 +14,7 @@ import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
import * as Utils from "#app/utils";
import { EggLapsePhase } from "./egg-lapse-phase";
import { EggHatchData } from "#app/data/egg-hatch-data";
import { doShinySparkleAnim } from "#app/field/anims";
/**
@ -341,9 +342,7 @@ export class EggHatchPhase extends Phase {
this.pokemon.cry();
if (isShiny) {
this.scene.time.delayedCall(Utils.fixedInt(500), () => {
// TODO
this.pokemonShinySparkle.play(`sparkle${this.pokemon.variant ? `_${this.pokemon.variant + 1}` : ""}`);
this.scene.playSound("se/sparkle");
doShinySparkleAnim(this.scene, this.pokemonShinySparkle, this.pokemon.variant);
});
}
this.scene.time.delayedCall(Utils.fixedInt(!this.skipped ? !isShiny ? 1250 : 1750 : !isShiny ? 250 : 750), () => {