mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-18 22:32:32 +02:00
Extract loadPokemonVariantAssets out of BattleScene
This commit is contained in:
parent
0717a37ee3
commit
7b98d1b78c
@ -106,8 +106,8 @@ import PokemonInfoContainer from "#app/ui/pokemon-info-container";
|
|||||||
import { biomeDepths, getBiomeName } from "#app/data/balance/biomes";
|
import { biomeDepths, getBiomeName } from "#app/data/balance/biomes";
|
||||||
import { SceneBase } from "#app/scene-base";
|
import { SceneBase } from "#app/scene-base";
|
||||||
import CandyBar from "#app/ui/candy-bar";
|
import CandyBar from "#app/ui/candy-bar";
|
||||||
import type { Variant, VariantSet } from "#app/data/variant";
|
import type { Variant } from "#app/data/variant";
|
||||||
import { variantColorCache, variantData, clearVariantData } from "#app/data/variant";
|
import { variantData, clearVariantData } from "#app/data/variant";
|
||||||
import type { Localizable } from "#app/interfaces/locales";
|
import type { Localizable } from "#app/interfaces/locales";
|
||||||
import Overrides from "#app/overrides";
|
import Overrides from "#app/overrides";
|
||||||
import { InputsController } from "#app/inputs-controller";
|
import { InputsController } from "#app/inputs-controller";
|
||||||
@ -421,35 +421,6 @@ export default class BattleScene extends SceneBase {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the variant assets for the given sprite and stores them in {@linkcode variantColorCache}
|
|
||||||
*/
|
|
||||||
public async loadPokemonVariantAssets(spriteKey: string, fileRoot: string, variant?: Variant): Promise<void> {
|
|
||||||
const useExpSprite = this.experimentalSprites && hasExpSprite(spriteKey);
|
|
||||||
if (useExpSprite) {
|
|
||||||
fileRoot = `exp/${fileRoot}`;
|
|
||||||
}
|
|
||||||
let variantConfig = variantData;
|
|
||||||
fileRoot.split("/").map(p => (variantConfig ? (variantConfig = variantConfig[p]) : null));
|
|
||||||
const variantSet = variantConfig as VariantSet;
|
|
||||||
|
|
||||||
return new Promise<void>(resolve => {
|
|
||||||
if (variantSet && variant !== undefined && variantSet[variant] === 1) {
|
|
||||||
if (variantColorCache.hasOwnProperty(spriteKey)) {
|
|
||||||
return resolve();
|
|
||||||
}
|
|
||||||
this.cachedFetch(`./images/pokemon/variant/${fileRoot}.json`)
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(c => {
|
|
||||||
variantColorCache[spriteKey] = c;
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async preload() {
|
async preload() {
|
||||||
if (DEBUG_RNG) {
|
if (DEBUG_RNG) {
|
||||||
const originalRealInRange = Phaser.Math.RND.realInRange;
|
const originalRealInRange = Phaser.Math.RND.realInRange;
|
||||||
@ -824,23 +795,15 @@ export default class BattleScene extends SceneBase {
|
|||||||
return fetch(url, init);
|
return fetch(url, init);
|
||||||
}
|
}
|
||||||
|
|
||||||
initStarterColors(): Promise<void> {
|
async initStarterColors() {
|
||||||
return new Promise(resolve => {
|
|
||||||
if (starterColors) {
|
if (starterColors) {
|
||||||
return resolve();
|
return;
|
||||||
}
|
}
|
||||||
|
const sc = await this.cachedFetch("./starter-colors.json").then(res => res.json());
|
||||||
this.cachedFetch("./starter-colors.json")
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(sc => {
|
|
||||||
starterColors = {};
|
starterColors = {};
|
||||||
for (const key of Object.keys(sc)) {
|
for (const key of Object.keys(sc)) {
|
||||||
starterColors[key] = sc[key];
|
starterColors[key] = sc[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPlayerParty(): PlayerPokemon[] {
|
public getPlayerParty(): PlayerPokemon[] {
|
||||||
|
@ -31,6 +31,7 @@ import { variantData } from "#app/data/variant";
|
|||||||
import { speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters";
|
import { speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters";
|
||||||
import { SpeciesFormKey } from "#enums/species-form-key";
|
import { SpeciesFormKey } from "#enums/species-form-key";
|
||||||
import { starterPassiveAbilities } from "#app/data/balance/passives";
|
import { starterPassiveAbilities } from "#app/data/balance/passives";
|
||||||
|
import { loadPokemonVariantAssets } from "#app/sprites/pokemon-sprite";
|
||||||
|
|
||||||
export enum Region {
|
export enum Region {
|
||||||
NORMAL,
|
NORMAL,
|
||||||
@ -387,6 +388,7 @@ export abstract class PokemonSpeciesForm {
|
|||||||
return `${/_[1-3]$/.test(spriteId) ? "variant/" : ""}${spriteId}`;
|
return `${/_[1-3]$/.test(spriteId) ? "variant/" : ""}${spriteId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Compute the sprite ID of the pokemon form. */
|
||||||
getSpriteId(female: boolean, formIndex?: number, shiny?: boolean, variant = 0, back?: boolean): string {
|
getSpriteId(female: boolean, formIndex?: number, shiny?: boolean, variant = 0, back?: boolean): string {
|
||||||
if (formIndex === undefined || this instanceof PokemonForm) {
|
if (formIndex === undefined || this instanceof PokemonForm) {
|
||||||
formIndex = this.formIndex;
|
formIndex = this.formIndex;
|
||||||
@ -394,7 +396,9 @@ export abstract class PokemonSpeciesForm {
|
|||||||
|
|
||||||
const formSpriteKey = this.getFormSpriteKey(formIndex);
|
const formSpriteKey = this.getFormSpriteKey(formIndex);
|
||||||
const showGenderDiffs =
|
const showGenderDiffs =
|
||||||
this.genderDiffs && female && ![SpeciesFormKey.MEGA, SpeciesFormKey.GIGANTAMAX].find(k => formSpriteKey === k);
|
this.genderDiffs &&
|
||||||
|
female &&
|
||||||
|
![SpeciesFormKey.MEGA, SpeciesFormKey.GIGANTAMAX].includes(formSpriteKey as SpeciesFormKey);
|
||||||
|
|
||||||
const baseSpriteKey = `${showGenderDiffs ? "female__" : ""}${this.speciesId}${formSpriteKey ? `-${formSpriteKey}` : ""}`;
|
const baseSpriteKey = `${showGenderDiffs ? "female__" : ""}${this.speciesId}${formSpriteKey ? `-${formSpriteKey}` : ""}`;
|
||||||
|
|
||||||
@ -621,7 +625,9 @@ export abstract class PokemonSpeciesForm {
|
|||||||
const spritePath = this.getSpriteAtlasPath(female, formIndex, shiny, variant, back)
|
const spritePath = this.getSpriteAtlasPath(female, formIndex, shiny, variant, back)
|
||||||
.replace("variant/", "")
|
.replace("variant/", "")
|
||||||
.replace(/_[1-3]$/, "");
|
.replace(/_[1-3]$/, "");
|
||||||
globalScene.loadPokemonVariantAssets(spriteKey, spritePath, variant).then(() => resolve());
|
if (!Utils.isNullOrUndefined(variant)) {
|
||||||
|
loadPokemonVariantAssets(spriteKey, spritePath, variant).then(() => resolve());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (startLoad) {
|
if (startLoad) {
|
||||||
if (!globalScene.load.isLoading()) {
|
if (!globalScene.load.isLoading()) {
|
||||||
|
@ -2236,12 +2236,7 @@ export const trainerConfigs: TrainerConfigs = {
|
|||||||
Species.PHANTUMP,
|
Species.PHANTUMP,
|
||||||
Species.PUMPKABOO,
|
Species.PUMPKABOO,
|
||||||
],
|
],
|
||||||
[TrainerPoolTier.RARE]: [
|
[TrainerPoolTier.RARE]: [Species.SNEASEL, Species.LITWICK, Species.PAWNIARD, Species.NOIBAT],
|
||||||
Species.SNEASEL,
|
|
||||||
Species.LITWICK,
|
|
||||||
Species.PAWNIARD,
|
|
||||||
Species.NOIBAT,
|
|
||||||
],
|
|
||||||
[TrainerPoolTier.SUPER_RARE]: [Species.SLIGGOO, Species.HISUI_SLIGGOO, Species.HISUI_AVALUGG],
|
[TrainerPoolTier.SUPER_RARE]: [Species.SLIGGOO, Species.HISUI_SLIGGOO, Species.HISUI_AVALUGG],
|
||||||
}),
|
}),
|
||||||
[TrainerType.BRYONY]: new TrainerConfig(++t)
|
[TrainerType.BRYONY]: new TrainerConfig(++t)
|
||||||
|
@ -7,6 +7,7 @@ import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/enc
|
|||||||
import type { Variant } from "#app/data/variant";
|
import type { Variant } from "#app/data/variant";
|
||||||
import { doShinySparkleAnim } from "#app/field/anims";
|
import { doShinySparkleAnim } from "#app/field/anims";
|
||||||
import PlayAnimationConfig = Phaser.Types.Animations.PlayAnimationConfig;
|
import PlayAnimationConfig = Phaser.Types.Animations.PlayAnimationConfig;
|
||||||
|
import { loadPokemonVariantAssets } from "#app/sprites/pokemon-sprite";
|
||||||
|
|
||||||
type KnownFileRoot =
|
type KnownFileRoot =
|
||||||
| "arenas"
|
| "arenas"
|
||||||
@ -233,8 +234,8 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
|
|||||||
this.spriteConfigs.forEach(config => {
|
this.spriteConfigs.forEach(config => {
|
||||||
if (config.isPokemon) {
|
if (config.isPokemon) {
|
||||||
globalScene.loadPokemonAtlas(config.spriteKey, config.fileRoot);
|
globalScene.loadPokemonAtlas(config.spriteKey, config.fileRoot);
|
||||||
if (config.isShiny) {
|
if (config.isShiny && !isNullOrUndefined(config.variant)) {
|
||||||
shinyPromises.push(globalScene.loadPokemonVariantAssets(config.spriteKey, config.fileRoot, config.variant));
|
shinyPromises.push(loadPokemonVariantAssets(config.spriteKey, config.fileRoot, config.variant));
|
||||||
}
|
}
|
||||||
} else if (config.isItem) {
|
} else if (config.isItem) {
|
||||||
globalScene.loadAtlas("items", "");
|
globalScene.loadAtlas("items", "");
|
||||||
|
11
src/sprites/pokemon-asset-loader.ts
Normal file
11
src/sprites/pokemon-asset-loader.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import type { Moves } from "#enums/moves";
|
||||||
|
import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronously load the animations and assets for the provided moves.
|
||||||
|
* @param moveIds An array of move IDs to load assets for.
|
||||||
|
*/
|
||||||
|
export async function loadMoveAnimations(moveIds: Moves[]) {
|
||||||
|
await Promise.allSettled(moveIds.map(m => initMoveAnim(m)));
|
||||||
|
await loadMoveAnimAssets(moveIds);
|
||||||
|
}
|
131
src/sprites/pokemon-sprite.ts
Normal file
131
src/sprites/pokemon-sprite.ts
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import { isNullOrUndefined } from "#app/utils";
|
||||||
|
import { variantColorCache, variantData } from "#app/data/variant";
|
||||||
|
import { Gender } from "#app/data/gender";
|
||||||
|
import { hasExpSprite } from "./sprite-utilts";
|
||||||
|
import type { Variant, VariantSet } from "#app/data/variant";
|
||||||
|
import type Pokemon from "#app/field/pokemon";
|
||||||
|
import type BattleScene from "#app/battle-scene";
|
||||||
|
|
||||||
|
// Regex patterns
|
||||||
|
|
||||||
|
/** Regex matching double underscores */
|
||||||
|
const DUNDER_REGEX = /\_{2}/g;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gracefully handle errors loading a variant sprite. Log if it fails and attempt to fall back on
|
||||||
|
* non-experimental sprites before giving up.
|
||||||
|
*
|
||||||
|
* @param cacheKey the cache key for the variant color sprite
|
||||||
|
* @param attemptedSpritePath the sprite path that failed to load
|
||||||
|
* @param useExpSprite was the attempted sprite experimental
|
||||||
|
* @param battleSpritePath the filename of the sprite
|
||||||
|
* @param optionalParams any additional params to log
|
||||||
|
*/
|
||||||
|
async function fallbackVariantColor(
|
||||||
|
cacheKey: string,
|
||||||
|
attemptedSpritePath: string,
|
||||||
|
useExpSprite: boolean,
|
||||||
|
battleSpritePath: string,
|
||||||
|
...optionalParams: any[]
|
||||||
|
) {
|
||||||
|
console.warn(`Could not load ${attemptedSpritePath}!`, ...optionalParams);
|
||||||
|
if (useExpSprite) {
|
||||||
|
await populateVariantColorCache(cacheKey, false, battleSpritePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to process variant sprite.
|
||||||
|
*
|
||||||
|
* @param cacheKey the cache key for the variant color sprite
|
||||||
|
* @param useExpSprite should the experimental sprite be used
|
||||||
|
* @param battleSpritePath the filename of the sprite
|
||||||
|
*/
|
||||||
|
export async function populateVariantColorCache(cacheKey: string, useExpSprite: boolean, battleSpritePath: string) {
|
||||||
|
const spritePath = `./images/pokemon/variant/${useExpSprite ? "exp/" : ""}${battleSpritePath}.json`;
|
||||||
|
return globalScene
|
||||||
|
.cachedFetch(spritePath)
|
||||||
|
.then(res => {
|
||||||
|
// Prevent the JSON from processing if it failed to load
|
||||||
|
if (!res.ok) {
|
||||||
|
return fallbackVariantColor(cacheKey, res.url, useExpSprite, battleSpritePath, res.status, res.statusText);
|
||||||
|
}
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
return fallbackVariantColor(cacheKey, spritePath, useExpSprite, battleSpritePath, error);
|
||||||
|
})
|
||||||
|
.then(c => {
|
||||||
|
if (!isNullOrUndefined(c)) {
|
||||||
|
variantColorCache[cacheKey] = c;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the sprite ID from a pokemon form.
|
||||||
|
*/
|
||||||
|
export function getSpriteId(pokemon: Pokemon, ignoreOverride?: boolean): string {
|
||||||
|
return pokemon
|
||||||
|
.getSpeciesForm(ignoreOverride)
|
||||||
|
.getSpriteId(
|
||||||
|
pokemon.getGender(ignoreOverride) === Gender.FEMALE,
|
||||||
|
pokemon.formIndex,
|
||||||
|
pokemon.shiny,
|
||||||
|
pokemon.variant,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBattleSpriteId(pokemon: Pokemon, back?: boolean, ignoreOverride = false): string {
|
||||||
|
if (back === undefined) {
|
||||||
|
back = pokemon.isPlayer();
|
||||||
|
}
|
||||||
|
return pokemon
|
||||||
|
.getSpeciesForm(ignoreOverride)
|
||||||
|
.getSpriteId(
|
||||||
|
pokemon.getGender(ignoreOverride) === Gender.FEMALE,
|
||||||
|
pokemon.formIndex,
|
||||||
|
pokemon.shiny,
|
||||||
|
pokemon.variant,
|
||||||
|
back,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compute the path to the sprite atlas by converting double underscores to path components (/)
|
||||||
|
*/
|
||||||
|
export function getSpriteAtlasPath(pokemon: Pokemon, ignoreOverride = false): string {
|
||||||
|
const spriteId = getSpriteId(pokemon, ignoreOverride).replace(DUNDER_REGEX, "/");
|
||||||
|
return `${/_[1-3]$/.test(spriteId) ? "variant/" : ""}${spriteId}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the variant assets for the given sprite and stores them in {@linkcode variantColorCache}.
|
||||||
|
* @param spriteKey the key of the sprite to load
|
||||||
|
* @param fileRoot the root path of the sprite file
|
||||||
|
* @param variant the variant to load
|
||||||
|
* @param scene the scene to load the assets in (defaults to the global scene)
|
||||||
|
*/
|
||||||
|
export async function loadPokemonVariantAssets(
|
||||||
|
spriteKey: string,
|
||||||
|
fileRoot: string,
|
||||||
|
variant: Variant,
|
||||||
|
scene: BattleScene = globalScene,
|
||||||
|
) {
|
||||||
|
if (variantColorCache.hasOwnProperty(spriteKey)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const useExpSprite = scene.experimentalSprites && hasExpSprite(spriteKey);
|
||||||
|
if (useExpSprite) {
|
||||||
|
fileRoot = `exp/${fileRoot}`;
|
||||||
|
}
|
||||||
|
let variantConfig = variantData;
|
||||||
|
fileRoot.split("/").map(p => (variantConfig ? (variantConfig = variantConfig[p]) : null));
|
||||||
|
const variantSet = variantConfig as VariantSet;
|
||||||
|
if (!variantConfig || variantSet[variant] !== 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
variantColorCache[spriteKey] = await scene
|
||||||
|
.cachedFetch(`./images/pokemon/variant/${fileRoot}.json`)
|
||||||
|
.then(res => res.json());
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user