mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-12-19 00:05:28 +01:00
* Standardize filenames to kebab-case Co-authored-by: pymilkmaiden <cassiopeiamahler56@gmail.com> * Move script outside of public folder * Move update_exp_sprites to scripts * Add ls-lint to lint file and directory names * Update lefthook.yml to skip merge / rebase on all pre-commit commands --------- Co-authored-by: pymilkmaiden <cassiopeiamahler56@gmail.com>
246 lines
8.5 KiB
TypeScript
246 lines
8.5 KiB
TypeScript
import { globalScene } from "#app/global-scene";
|
|
import { FieldSpritePipeline } from "#app/pipelines/field-sprite";
|
|
import { MysteryEncounterIntroVisuals } from "#field/mystery-encounter-intro";
|
|
import { Pokemon } from "#field/pokemon";
|
|
import { Trainer } from "#field/trainer";
|
|
import { variantColorCache } from "#sprites/variant";
|
|
import { rgbHexToRgba } from "#utils/common";
|
|
import spriteFragShader from "./glsl/sprite-frag-shader.frag?raw";
|
|
import spriteVertShader from "./glsl/sprite-shader.vert?raw";
|
|
|
|
export class SpritePipeline extends FieldSpritePipeline {
|
|
private _tone: number[];
|
|
|
|
constructor(game: Phaser.Game) {
|
|
super(game, {
|
|
game: game,
|
|
name: "sprite",
|
|
fragShader: spriteFragShader,
|
|
vertShader: spriteVertShader,
|
|
});
|
|
|
|
this._tone = [0, 0, 0, 0];
|
|
}
|
|
|
|
onPreRender(): void {
|
|
super.onPreRender();
|
|
|
|
this.set1f("teraTime", 0);
|
|
this.set3fv("teraColor", [0, 0, 0]);
|
|
this.set1i("hasShadow", 0);
|
|
this.set1i("yCenter", 0);
|
|
this.set2f("relPosition", 0, 0);
|
|
this.set2f("texFrameUv", 0, 0);
|
|
this.set2f("size", 0, 0);
|
|
this.set2f("texSize", 0, 0);
|
|
this.set1f("yOffset", 0);
|
|
this.set1f("yShadowOffset", 0);
|
|
this.set4fv("tone", this._tone);
|
|
}
|
|
|
|
onBind(gameObject: Phaser.GameObjects.GameObject): void {
|
|
super.onBind(gameObject);
|
|
|
|
const sprite = gameObject as Phaser.GameObjects.Sprite;
|
|
|
|
const data = sprite.pipelineData;
|
|
const tone = data["tone"] as number[];
|
|
const teraColor = (data["isTerastallized"] as boolean) ? ((data["teraColor"] as number[]) ?? [0, 0, 0]) : [0, 0, 0];
|
|
const hasShadow = data["hasShadow"] as boolean;
|
|
const yShadowOffset = data["yShadowOffset"] as number;
|
|
const ignoreFieldPos = data["ignoreFieldPos"] as boolean;
|
|
const ignoreOverride = data["ignoreOverride"] as boolean;
|
|
|
|
const isEntityObj =
|
|
sprite.parentContainer instanceof Pokemon ||
|
|
sprite.parentContainer instanceof Trainer ||
|
|
sprite.parentContainer instanceof MysteryEncounterIntroVisuals;
|
|
const field = isEntityObj ? sprite.parentContainer.parentContainer : sprite.parentContainer;
|
|
const position = isEntityObj ? [sprite.parentContainer.x, sprite.parentContainer.y] : [sprite.x, sprite.y];
|
|
if (field) {
|
|
position[0] += field.x / field.scale;
|
|
position[1] += field.y / field.scale;
|
|
}
|
|
position[0] +=
|
|
-(sprite.width - sprite.frame.width) / 2 + sprite.frame.x + (!ignoreFieldPos ? sprite.x - field.x : 0);
|
|
if (sprite.originY === 0.5) {
|
|
position[1] +=
|
|
(sprite.height / 2) * ((isEntityObj ? sprite.parentContainer : sprite).scale - 1) +
|
|
(!ignoreFieldPos ? sprite.y - field.y : 0);
|
|
}
|
|
this.set1f("teraTime", (this.game.getTime() % 500000) / 500000);
|
|
this.set3fv(
|
|
"teraColor",
|
|
teraColor.map(c => c / 255),
|
|
);
|
|
this.set1i("hasShadow", hasShadow ? 1 : 0);
|
|
this.set1i("yCenter", sprite.originY === 0.5 ? 1 : 0);
|
|
this.set1f("fieldScale", field?.scale || 1);
|
|
this.set2f("relPosition", position[0], position[1]);
|
|
this.set2f("texFrameUv", sprite.frame.u0, sprite.frame.v0);
|
|
this.set2f("size", sprite.frame.width, sprite.height);
|
|
this.set2f("texSize", sprite.texture.source[0].width, sprite.texture.source[0].height);
|
|
this.set1f(
|
|
"yOffset",
|
|
sprite.height - sprite.frame.height * (isEntityObj ? sprite.parentContainer.scale : sprite.scale),
|
|
);
|
|
this.set1f("yShadowOffset", yShadowOffset ?? 0);
|
|
this.set4fv("tone", tone);
|
|
this.bindTexture(this.game.textures.get("tera").source[0].glTexture!, 1); // TODO: is this bang correct?
|
|
|
|
if (globalScene.fusionPaletteSwaps) {
|
|
const spriteColors = ((ignoreOverride && data["spriteColorsBase"]) || data["spriteColors"] || []) as number[][];
|
|
const fusionSpriteColors = ((ignoreOverride && data["fusionSpriteColorsBase"]) ||
|
|
data["fusionSpriteColors"] ||
|
|
[]) as number[][];
|
|
|
|
const emptyColors = [0, 0, 0, 0];
|
|
const flatSpriteColors: number[] = [];
|
|
const flatFusionSpriteColors: number[] = [];
|
|
for (let c = 0; c < 32; c++) {
|
|
flatSpriteColors.splice(
|
|
flatSpriteColors.length,
|
|
0,
|
|
...(c < spriteColors.length ? spriteColors[c].map(x => x / 255.0) : emptyColors),
|
|
);
|
|
flatFusionSpriteColors.splice(
|
|
flatFusionSpriteColors.length,
|
|
0,
|
|
...(c < fusionSpriteColors.length ? fusionSpriteColors[c] : emptyColors),
|
|
);
|
|
}
|
|
|
|
this.set4fv("spriteColors", flatSpriteColors.flat());
|
|
this.set4iv("fusionSpriteColors", flatFusionSpriteColors.flat());
|
|
}
|
|
}
|
|
|
|
onBatch(gameObject: Phaser.GameObjects.GameObject): void {
|
|
if (gameObject) {
|
|
const sprite = gameObject as Phaser.GameObjects.Sprite;
|
|
const data = sprite.pipelineData;
|
|
|
|
const variant: number = data.hasOwnProperty("variant")
|
|
? data["variant"]
|
|
: sprite.parentContainer instanceof Pokemon
|
|
? sprite.parentContainer.variant
|
|
: 0;
|
|
let variantColors: { [x: string]: string }[];
|
|
|
|
const emptyColors = [0, 0, 0, 0];
|
|
const flatBaseColors: number[] = [];
|
|
const flatVariantColors: number[] = [];
|
|
|
|
if (
|
|
(sprite.parentContainer instanceof Pokemon ? sprite.parentContainer.shiny : !!data["shiny"]) &&
|
|
(variantColors =
|
|
variantColorCache[
|
|
sprite.parentContainer instanceof Pokemon
|
|
? sprite.parentContainer.getSprite().texture.key
|
|
: data["spriteKey"]
|
|
]) &&
|
|
variantColors.hasOwnProperty(variant)
|
|
) {
|
|
const baseColors = Object.keys(variantColors[variant]);
|
|
for (let c = 0; c < 32; c++) {
|
|
if (c < baseColors.length) {
|
|
const baseColor = Array.from(Object.values(rgbHexToRgba(baseColors[c])));
|
|
const variantColor = Array.from(Object.values(rgbHexToRgba(variantColors[variant][baseColors[c]])));
|
|
flatBaseColors.splice(flatBaseColors.length, 0, ...baseColor.map(c => c / 255.0));
|
|
flatVariantColors.splice(flatVariantColors.length, 0, ...variantColor.map(c => c / 255.0));
|
|
} else {
|
|
flatBaseColors.splice(flatBaseColors.length, 0, ...emptyColors);
|
|
flatVariantColors.splice(flatVariantColors.length, 0, ...emptyColors);
|
|
}
|
|
}
|
|
} else {
|
|
for (let c = 0; c < 32; c++) {
|
|
flatBaseColors.splice(flatBaseColors.length, 0, ...emptyColors);
|
|
flatVariantColors.splice(flatVariantColors.length, 0, ...emptyColors);
|
|
}
|
|
}
|
|
|
|
this.set4fv("baseVariantColors", flatBaseColors.flat());
|
|
this.set4fv("variantColors", flatVariantColors.flat());
|
|
}
|
|
|
|
super.onBatch(gameObject);
|
|
}
|
|
|
|
batchQuad(
|
|
gameObject: Phaser.GameObjects.GameObject,
|
|
x0: number,
|
|
y0: number,
|
|
x1: number,
|
|
y1: number,
|
|
x2: number,
|
|
y2: number,
|
|
x3: number,
|
|
y3: number,
|
|
u0: number,
|
|
v0: number,
|
|
u1: number,
|
|
v1: number,
|
|
tintTL: number,
|
|
tintTR: number,
|
|
tintBL: number,
|
|
tintBR: number,
|
|
tintEffect: number | boolean,
|
|
texture?: Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper,
|
|
unit?: number,
|
|
): boolean {
|
|
const sprite = gameObject as Phaser.GameObjects.Sprite;
|
|
|
|
this.set1f("vCutoff", v1);
|
|
|
|
const hasShadow = sprite.pipelineData["hasShadow"] as boolean;
|
|
const yShadowOffset = (sprite.pipelineData["yShadowOffset"] as number) ?? 0;
|
|
if (hasShadow) {
|
|
const isEntityObj =
|
|
sprite.parentContainer instanceof Pokemon ||
|
|
sprite.parentContainer instanceof Trainer ||
|
|
sprite.parentContainer instanceof MysteryEncounterIntroVisuals;
|
|
const field = isEntityObj ? sprite.parentContainer.parentContainer : sprite.parentContainer;
|
|
const fieldScaleRatio = field.scale / 6;
|
|
const baseY = ((isEntityObj ? sprite.parentContainer.y : sprite.y + sprite.height) * 6) / fieldScaleRatio;
|
|
const bottomPadding = (Math.ceil(sprite.height * 0.05 + Math.max(yShadowOffset, 0)) * 6) / fieldScaleRatio;
|
|
const yDelta = (baseY - y1) / field.scale;
|
|
y2 = y1 = baseY + bottomPadding;
|
|
const pixelHeight =
|
|
(v1 - v0) / (sprite.frame.height * (isEntityObj ? sprite.parentContainer.scale : sprite.scale));
|
|
v1 += (yDelta + bottomPadding / field.scale) * pixelHeight;
|
|
}
|
|
|
|
return super.batchQuad(
|
|
gameObject,
|
|
x0,
|
|
y0,
|
|
x1,
|
|
y1,
|
|
x2,
|
|
y2,
|
|
x3,
|
|
y3,
|
|
u0,
|
|
v0,
|
|
u1,
|
|
v1,
|
|
tintTL,
|
|
tintTR,
|
|
tintBL,
|
|
tintBR,
|
|
tintEffect,
|
|
texture,
|
|
unit,
|
|
);
|
|
}
|
|
|
|
get tone(): number[] {
|
|
return this._tone;
|
|
}
|
|
|
|
set tone(value: number[]) {
|
|
this._tone = value;
|
|
}
|
|
}
|