mirror of
https://github.com/smogon/sprites.git
synced 2026-09-27 11:47:45 -05:00
The dex serves /dex/dp/pokemon/embirch/ and the sprite lookup logs a miss for it, which is not a dex bug: Embirch is an NFE from a gen 4 CAP process, so it belongs on a gen 4 page. It was drawn in BW's day, like the other twelve prevos the gen 4 CAPs were given after the fact. That is what GEN4_CAPS is already for. dp/ has no CAP art of its own -- gen 4 never drew any of it, and nothing in a gen 5 filename says a sprite is a CAP -- so the set names the eleven by hand and lifts them out of the gen 5 stills. Name the prevos there too, and the same rule draws them: fifteen files, the thirteen species plus the female slots on Flarelm and Protowatt, each trimmed the way its evolution is. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
80 lines
3.8 KiB
TypeScript
80 lines
3.8 KiB
TypeScript
|
|
import * as spritedata from '@smogon/sprite-data/index.ts';
|
|
|
|
import {type Artifact, type CmdSpec, rule} from '../tools/build/artifact.ts';
|
|
import {base, glob} from '../tools/build/helpers.ts';
|
|
|
|
// A source picked for an older-gen collection, and what the sprite built from
|
|
// it is called. The two differ because the game is spent on choosing the
|
|
// collection: `rb` and `y` are the same Zubat under two palettes, and neither
|
|
// output has a game left in its name. Dropping it is not cosmetic. `-g` is
|
|
// Gigantamax everywhere the grammar isn't naming a gen 1-4 game, so a name
|
|
// that kept it would reach publishedName() as `zubat-gmax`.
|
|
export type Front = {
|
|
file: string,
|
|
name: string,
|
|
};
|
|
|
|
// The gen 1-4 sets are each named for one game and sourced from several. `-g`
|
|
// spells the games a picture is the copy for, a letter apiece, and a
|
|
// collection takes them in preference order: the game it is named for first,
|
|
// then whatever drew the formes that game never did. That is how rs/ comes to
|
|
// hold Deoxys-Attack, which only FireRed drew, and dp/ the Rotom appliances
|
|
// and Giratina-Origin, which only Platinum did. Which layer wins a name is
|
|
// settled at copy time, by whoever claims it first.
|
|
//
|
|
// Gen 5 has no such axis -- there its `-g` really is Gigantamax -- so its sets
|
|
// pass no order, and keep every flag they came with.
|
|
export function fronts(pats: string | string[], games?: string): Front[] {
|
|
let ranked = [];
|
|
for (let file of glob(pats)) {
|
|
let sn = spritedata.parseFilename(base(file));
|
|
// Backs and shinies go unpublished: the legacy tree kept them in
|
|
// subdirectories of their own, under national dex numbers, and
|
|
// nothing on the site has ever read one.
|
|
if (sn.extra.has('b') || sn.extra.has('s')) {
|
|
continue;
|
|
}
|
|
let rank = 0;
|
|
if (games !== undefined) {
|
|
let code = sn.extra.get('g') ?? '';
|
|
rank = [...games].findIndex(g => code.includes(g));
|
|
// Another generation's game, or no game at all: not this set's.
|
|
if (rank < 0) {
|
|
continue;
|
|
}
|
|
sn.extra.delete('g');
|
|
}
|
|
ranked.push({file, name: spritedata.formatFilename(sn), rank});
|
|
}
|
|
// Stable, so within one game the glob's own order survives.
|
|
return ranked.sort((a, b) => a.rank - b.rank).map(({file, name}) => ({file, name}));
|
|
}
|
|
|
|
// One rule per front, its output named for what it publishes. Several sources
|
|
// can land on one name -- Abra is the same drawing in Ruby and in Emerald --
|
|
// which is fine, since a nominal name is provenance and not identity.
|
|
export function forEachFront(files: Front[], spec: CmdSpec, ext: string): Artifact[] {
|
|
return files.map(f => rule(f.file, spec, `${f.name}.${ext}`));
|
|
}
|
|
|
|
// The gen 4 CAP families: the eleven CAPs a gen 4 process produced, and the
|
|
// prevos later processes gave them. None of it was drawn in gen 4's style --
|
|
// the CAPs were only ever drawn in gen 5's, and the prevos did not exist until
|
|
// BW -- so dp/ carries the lot from the gen 5 sources, as the legacy set did
|
|
// for the eleven. A prevo lands on a gen 4 dex page like its evolution does,
|
|
// which is why it is here too. The list is by hand, since nothing in a
|
|
// filename says a sprite is a CAP.
|
|
export let GEN4_CAPS = [
|
|
'arghonaut', 'breezi', 'colossoil', 'cyclohm', 'dorsoil', 'duohm',
|
|
'embirch', 'fidgit', 'flarelm', 'kitsunoh', 'krilowatt', 'monohm',
|
|
'nohface', 'privatyke', 'protowatt', 'pyroak', 'rebble', 'revenankh',
|
|
'stratagem', 'syclant', 'syclar', 'tactite', 'voodoll', 'voodoom',
|
|
];
|
|
|
|
// Every front of the given species, formes and female slots included.
|
|
export function named(files: Front[], names: readonly string[]): Front[] {
|
|
let want = new Set(names);
|
|
return files.filter(f => want.has(spritedata.parseFilename(f.name).name));
|
|
}
|