pokerogue/src/field/pokemon-sprite-sparkle-handler.ts
Xavion3 90d32b886c
[Feature] Tera Rework (#5233)
* Commit old stashed changes

* Complete basic implementation of Tera

* Fix effectiveness test

* Make tera retain until forced recall or faint, regain on biome change

* Experimental sparkle fix

* Fix champion teras

* Attempted fix for double battles tera UI bug

* Fix the fix

* Fix linting and test issues

* Fix more tests

* Change int type

* Implement tera for ME trainers

* Cleanup species inclusivity check

* Make tera instant recharge if terapagos in party

* Make useless tera shards not generate

* Implement stellar tera damage boost

* Improve tera selection UI

* Tidy up animation and localisation

* Improve tera button sprite

* Fix Lance tera

* Make tera instant recharge during E4 in classic modes.

* Fix formatting in the tera common animation

The animation was also not playing due to `frameTimedEvents` being missing as well.

* Make tera effect start after animation

* Implement save migration

* Update version number for migration code

---------

Co-authored-by: Madmadness65 <blaze.the.fireman@gmail.com>
Co-authored-by: Madmadness65 <59298170+Madmadness65@users.noreply.github.com>
2025-02-16 16:20:50 -05:00

80 lines
2.7 KiB
TypeScript

import { globalScene } from "#app/global-scene";
import Pokemon from "./pokemon";
import * as Utils from "../utils";
export default class PokemonSpriteSparkleHandler {
private sprites: Set<Phaser.GameObjects.Sprite>;
setup(): void {
this.sprites = new Set();
globalScene.tweens.addCounter({
duration: Utils.fixedInt(200),
from: 0,
to: 1,
yoyo: true,
repeat: -1,
onRepeat: () => this.onLapse()
});
}
onLapse(): void {
Array.from(this.sprites.values()).filter(s => !s.scene).map(s => this.sprites.delete(s));
for (const s of this.sprites.values()) {
if (!s.pipelineData["teraColor"] || !(s.pipelineData["teraColor"] as number[]).find(c => c)) {
continue;
}
if (!s.visible || (s.parentContainer instanceof Pokemon && !s.parentContainer.parentContainer)) {
continue;
}
if (!(s.parentContainer instanceof Pokemon) || !(s.parentContainer as Pokemon).isTerastallized) {
continue;
}
const pokemon = s.parentContainer instanceof Pokemon ? s.parentContainer as Pokemon : null;
const parent = (pokemon || s).parentContainer;
const texture = s.texture;
const [ width, height ] = [ texture.source[0].width, texture.source[0].height ];
const [ pixelX, pixelY ] = [ Utils.randInt(width), Utils.randInt(height) ];
const ratioX = s.width / width;
const ratioY = s.height / height;
const pixel = texture.manager.getPixel(pixelX, pixelY, texture.key, "__BASE");
if (pixel?.alpha) {
const [ xOffset, yOffset ] = [ -s.originX * s.width, -s.originY * s.height ];
const sparkle = globalScene.addFieldSprite(((pokemon?.x || 0) + s.x + pixelX * ratioX + xOffset), ((pokemon?.y || 0) + s.y + pixelY * ratioY + yOffset), "tera_sparkle");
sparkle.pipelineData["ignoreTimeTint"] = s.pipelineData["ignoreTimeTint"];
sparkle.setName("sprite-tera-sparkle");
sparkle.play("tera_sparkle");
parent.add(sparkle);
s.scene.time.delayedCall(Utils.fixedInt(Math.floor((1000 / 12) * 13)), () => sparkle.destroy());
}
}
}
add(sprites: Phaser.GameObjects.Sprite | Phaser.GameObjects.Sprite[]): void {
if (!Array.isArray(sprites)) {
sprites = [ sprites ];
}
for (const s of sprites) {
if (this.sprites.has(s)) {
continue;
}
this.sprites.add(s);
}
}
remove(sprites: Phaser.GameObjects.Sprite | Phaser.GameObjects.Sprite[]): void {
if (!Array.isArray(sprites)) {
sprites = [ sprites ];
}
for (const s of sprites) {
this.sprites.delete(s);
}
}
removeAll(): void {
for (const s of this.sprites.values()) {
this.sprites.delete(s);
}
}
}