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 { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
import { addPokemonDataToDexAndValidateAchievements } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { addPokemonDataToDexAndValidateAchievements } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
import type { PokeballType } from "#enums/pokeball"; import type { PokeballType } from "#enums/pokeball";
import { doShinySparkleAnim } from "#app/field/anims";
/** the i18n namespace for the encounter */ /** the i18n namespace for the encounter */
const namespace = "mysteryEncounters/globalTradeSystem"; const namespace = "mysteryEncounters/globalTradeSystem";
@ -846,8 +847,7 @@ function doTradeReceivedSequence(scene: BattleScene, receivedPokemon: PlayerPoke
onComplete: () => { onComplete: () => {
if (receivedPokemon.shiny) { if (receivedPokemon.shiny) {
scene.time.delayedCall(500, () => { scene.time.delayedCall(500, () => {
pokemonShinySparkle.play(`sparkle${receivedPokemon.variant ? `_${receivedPokemon.variant + 1}` : ""}`); doShinySparkleAnim(scene, pokemonShinySparkle, receivedPokemon.variant);
scene.playSound("se/sparkle");
}); });
} }
receivedPokeballSprite.destroy(); 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 { 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 { export function addPokeballOpenParticles(scene: BattleScene, x: number, y: number, pokeballType: PokeballType): void {
switch (pokeballType) { switch (pokeballType) {
@ -127,7 +128,7 @@ function doFanOutParticle(scene: BattleScene, trigIndex: integer, x: integer, y:
const particleTimer = scene.tweens.addCounter({ const particleTimer = scene.tweens.addCounter({
repeat: -1, repeat: -1,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
updateParticle(); 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({ scene.tweens.add({
targets: particle, targets: particle,
x: pokeball.x + dist, x: pokeball.x + dist,
@ -185,3 +186,31 @@ export function sin(index: integer, amplitude: integer): number {
export function cos(index: integer, amplitude: integer): number { export function cos(index: integer, amplitude: integer): number {
return amplitude * Math.cos(index * (Math.PI / 128)); 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 { GameObjects } from "phaser";
import BattleScene from "../battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter from "../data/mystery-encounters/mystery-encounter"; import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils";
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
import PlayAnimationConfig = Phaser.Types.Animations.PlayAnimationConfig; import PlayAnimationConfig = Phaser.Types.Animations.PlayAnimationConfig;
import { Variant, variantColorCache, variantData, VariantSet } from "#app/data/variant"; import { Variant, variantColorCache, variantData, VariantSet } from "#app/data/variant";
import { doShinySparkleAnim } from "#app/field/anims";
type KnownFileRoot = type KnownFileRoot =
| "arenas" | "arenas"
@ -294,12 +295,18 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
this.getSprites().map((sprite, i) => { this.getSprites().map((sprite, i) => {
if (!this.spriteConfigs[i].isItem) { 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) => { this.getTintSprites().map((tintSprite, i) => {
if (!this.spriteConfigs[i].isItem) { 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() { playShinySparkles() {
for (const sparkleConfig of this.shinySparkleSprites) { for (const sparkleConfig of this.shinySparkleSprites) {
this.scene.time.delayedCall(500, () => { this.scene.time.delayedCall(500, () => {
sparkleConfig.sprite.play(`sparkle${sparkleConfig.variant ? `_${sparkleConfig.variant + 1}` : ""}`); doShinySparkleAnim(this.scene, sparkleConfig.sprite, sparkleConfig.variant);
this.scene.playSound("se/sparkle");
}); });
} }
} }

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 { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE, SHINY_EPIC_CHANCE, SHINY_VARIANT_CHANCE } from "#app/data/balance/rates";
import { Nature } from "#enums/nature"; import { Nature } from "#enums/nature";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import { doShinySparkleAnim } from "#app/field/anims";
export enum FieldPosition { export enum FieldPosition {
CENTER, CENTER,
@ -668,22 +669,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
initShinySparkle(): void { initShinySparkle(): void {
// TODO const shinySparkle = this.scene.addFieldSprite(0, 0, "shiny");
const keySuffix = this.variant ? `_${this.variant + 1}` : "";
const key = `shiny${keySuffix}`;
const shinySparkle = this.scene.addFieldSprite(0, 0, key);
shinySparkle.setVisible(false); shinySparkle.setVisible(false);
shinySparkle.setOrigin(0.5, 1); 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.add(shinySparkle);
this.shinySparkle = shinySparkle; this.shinySparkle = shinySparkle;
@ -3746,8 +3734,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
sparkle(): void { sparkle(): void {
if (this.shinySparkle) { if (this.shinySparkle) {
this.shinySparkle.play(`sparkle${this.variant ? `_${this.variant + 1}` : ""}`); doShinySparkleAnim(this.scene, this.shinySparkle, this.variant);
this.scene.playSound("se/sparkle");
} }
} }

View File

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