diff --git a/assets.build.ts b/assets.build.ts index 135f8854..40767972 100644 --- a/assets.build.ts +++ b/assets.build.ts @@ -69,7 +69,7 @@ deploy(async ctx => { await itemspritecopy(manifest, f, {dir: `${ASSETS}/forumsprites`}); } for (let f of forumG6) { - await spritecopy(manifest, f, {dir: `${ASSETS}/forumsprites`}, true); + await spritecopy(manifest, f, {dir: `${ASSETS}/forumsprites`}, {allowUnknown: true, icons: true}); } manifest.write('__meta/forumsprites/manifest.json'); }); diff --git a/data/lib/index.ts b/data/lib/index.ts index e3104089..95a262da 100644 --- a/data/lib/index.ts +++ b/data/lib/index.ts @@ -84,16 +84,54 @@ export const ITEM_ALIASES: Record = { // The second name a sprite answers to, where one picture publishes twice. // Meowstic is a disagreement: PS's is the male, baseForme M with Meowstic-F the // alt forme, while the dex splits the pair evenly and calls that entry -// Meowstic-M. Toxtricity is a shortage: the games drew one Gigantamax -// Toxtricity and not two, which is why PS's own icon sheet gives Amped and -// Low-Key a single slot and its animations no low-key gmax at all. Keyed and -// valued in published smogon form, because only that side asks; PS wants -// `meowstic` and `toxtricitygmax`, which is what the filenames already say. +// Meowstic-M. The other two are one picture wearing two names. The games drew +// one Gigantamax Toxtricity and not two, which is why PS's own icon sheet gives +// Amped and Low-Key a single slot and its animations no low-key gmax at all. +// Greninja-Bond is Battle Bond's form and looks like any other Greninja, unlike +// Greninja-Ash, which is drawn: the gen 5 renditions of the two are byte for +// byte the base sprite, and nothing ever drew a model. Keyed and valued in +// published smogon form, because only that side asks; PS wants `meowstic`, +// `toxtricitygmax` and `greninja`, which is what the filenames already say. export const SPECIES_ALIASES: Record = { + greninja: ['greninja-bond'], meowstic: ['meowstic-m'], 'toxtricity-gmax': ['toxtricity-low-key-gmax'], }; +// Formes the gen 6 icon set has no art for, because the games drew them none. +// PS's client says the same thing in its own sheet, where each of these sits at +// the slot of the forme it shares, under "alt forms with duplicate icons". +// Keyed by the name that has the icon, in published smogon form. +// +// The icon sets alone borrow this way. src/models has a real animation for +// every one of these, so smogonNames() must not know about them: in xy/ the +// borrowing name would be claimed by the base sprite and shadow the forme's +// own art. +export const ICON_ALIASES: Record = { + araquanid: ['araquanid-totem'], + gourgeist: ['gourgeist-large', 'gourgeist-small', 'gourgeist-super'], + gumshoos: ['gumshoos-totem'], + 'kommo-o': ['kommo-o-totem'], + lurantis: ['lurantis-totem'], + 'marowak-alola': ['marowak-alola-totem'], + mimikyu: ['mimikyu-busted', 'mimikyu-busted-totem', 'mimikyu-totem'], + pichu: ['pichu-spiky-eared'], + pumpkaboo: ['pumpkaboo-large', 'pumpkaboo-small', 'pumpkaboo-super'], + 'raticate-alola': ['raticate-alola-totem'], + ribombee: ['ribombee-totem'], + rockruff: ['rockruff-dusk'], + salazzle: ['salazzle-totem'], + togedemaru: ['togedemaru-totem'], + vikavolt: ['vikavolt-totem'], +}; + +// Every name a gen 6 icon answers to: its own, and any forme with no icon of +// its own that borrows it. +export function iconNames(sn: SpriteFilename): string[] { + let names = smogonNames(sn); + return [...names, ...names.flatMap(n => ICON_ALIASES[n] ?? [])]; +} + // Every name a sprite answers to on the smogon side: its own, and any alias. export function smogonNames(sn: SpriteFilename): string[] { let name = publishedName(sn, smogon); diff --git a/rules/publish.ts b/rules/publish.ts index 984b92dd..d16030f2 100644 --- a/rules/publish.ts +++ b/rules/publish.ts @@ -69,7 +69,15 @@ function extOf(f: Sprite, ext?: string): string { // copies, since the mapping isn't one name per filename in either direction: // Meowstic answers to two, and the forme slots the games gave one sprite (the // six Minior meteors, Zygarde's Power Construct pair) answer to the same one. -export function publishedNames(f: Sprite, allowUnknown = false): string[] { +export type NameOpts = { + // forumsprites publishes Unknown; no other set does. + allowUnknown?: boolean, + // The gen 6 icon sets publish the formes they have no icon for under a + // borrowed one. See ICON_ALIASES. + icons?: boolean, +}; + +export function publishedNames(f: Sprite, opts: NameOpts = {}): string[] { let sn = spritedata.parseFilename(f.name); // Skip asymmetrical for now @@ -79,19 +87,19 @@ export function publishedNames(f: Sprite, allowUnknown = false): string[] { if (sn.kind === 'x') { // Skip these, we don't use Unknown/Substitute - if (!allowUnknown || sn.name !== 'unknown') { + if (!opts.allowUnknown || sn.name !== 'unknown') { return []; } } else if (sn.kind !== 's') { throw new Error(`Not a specie sprite: ${f.name}`); } - return spritedata.smogonNames(sn); + return opts.icons ? spritedata.iconNames(sn) : spritedata.smogonNames(sn); } export async function spritecopy(manifest: Manifest, f: Sprite, dest: Dest, - allowUnknown = false): Promise { - for (let name of publishedNames(f, allowUnknown)) { + opts: NameOpts = {}): Promise { + for (let name of publishedNames(f, opts)) { await manifest.copy(f, dest, name); } } diff --git a/smogon.build.ts b/smogon.build.ts index ec6ce4ff..d6cb0649 100644 --- a/smogon.build.ts +++ b/smogon.build.ts @@ -74,53 +74,18 @@ let xyIcons = forEachRule('src/minisprites/pokemon/gen6/*.png', { cmds: [trimimg(), compresspng({config: 'MINISPRITE'})], }, '%b'); -// The games drew these formes no icon of their own, so gen 6 has none and -// nothing upstream does either: PS ships icons as one dexnum-indexed sheet, and -// its own copy of this list sits commented out in ps-pokemon.sheet.mjs under -// "alt forms with duplicate icons". Serve each the icon it shares. Only this -// set needs them; xy/ has real art for all 22. -let xyIconAliases: Record = { - 'araquanid-totem': 'araquanid', - 'gourgeist-large': 'gourgeist', - 'gourgeist-small': 'gourgeist', - 'gourgeist-super': 'gourgeist', - 'greninja-bond': 'greninja', - 'gumshoos-totem': 'gumshoos', - 'kommo-o-totem': 'kommo-o', - 'lurantis-totem': 'lurantis', - 'marowak-alola-totem': 'marowak-alola', - 'mimikyu-busted': 'mimikyu', - 'mimikyu-busted-totem': 'mimikyu', - 'mimikyu-totem': 'mimikyu', - 'pichu-spiky-eared': 'pichu', - 'pumpkaboo-large': 'pumpkaboo', - 'pumpkaboo-small': 'pumpkaboo', - 'pumpkaboo-super': 'pumpkaboo', - 'raticate-alola-totem': 'raticate-alola', - 'ribombee-totem': 'ribombee', - 'rockruff-dusk': 'rockruff', - 'salazzle-totem': 'salazzle', - 'togedemaru-totem': 'togedemaru', - 'vikavolt-totem': 'vikavolt', -}; - deploy(ctx => { + // icons: the gen 6 set has no art for some formes and lends them another's, + // which the smogdex sheet and forumsprites do off the same directory. let byName = new Map(); for (let f of xyIcons) { - for (let name of publishedNames(f)) { + for (let name of publishedNames(f, {icons: true})) { + if (byName.has(name)) { + throw new Error(`Two icons published as ${name}`); + } byName.set(name, f); } } - for (let [name, from] of Object.entries(xyIconAliases)) { - let f = byName.get(from); - if (f === undefined) { - throw new Error(`No ${from} icon to publish as ${name}`); - } - if (byName.has(name)) { - throw new Error(`${name} has an icon of its own now; drop the alias`); - } - byName.set(name, f); - } for (let [name, f] of byName) { smogonSpritecopy(ctx, f, 'xyicons', [name]); } diff --git a/src/pmd/sgreninja-obond.png b/src/pmd/sgreninja-obond.png deleted file mode 100644 index b5b28fcf..00000000 Binary files a/src/pmd/sgreninja-obond.png and /dev/null differ diff --git a/src/previews/gen9/sgreninja-obond-s.png b/src/previews/gen9/sgreninja-obond-s.png deleted file mode 100644 index 0355f195..00000000 Binary files a/src/previews/gen9/sgreninja-obond-s.png and /dev/null differ diff --git a/src/previews/gen9/sgreninja-obond.png b/src/previews/gen9/sgreninja-obond.png deleted file mode 100644 index 8d4dc558..00000000 Binary files a/src/previews/gen9/sgreninja-obond.png and /dev/null differ diff --git a/src/sprites/gen5/sgreninja-obond-b-s.png b/src/sprites/gen5/sgreninja-obond-b-s.png deleted file mode 100644 index 4c743422..00000000 Binary files a/src/sprites/gen5/sgreninja-obond-b-s.png and /dev/null differ diff --git a/src/sprites/gen5/sgreninja-obond-b.png b/src/sprites/gen5/sgreninja-obond-b.png deleted file mode 100644 index 50102532..00000000 Binary files a/src/sprites/gen5/sgreninja-obond-b.png and /dev/null differ diff --git a/src/sprites/gen5/sgreninja-obond-s.png b/src/sprites/gen5/sgreninja-obond-s.png deleted file mode 100644 index cc928498..00000000 Binary files a/src/sprites/gen5/sgreninja-obond-s.png and /dev/null differ diff --git a/src/sprites/gen5/sgreninja-obond.png b/src/sprites/gen5/sgreninja-obond.png deleted file mode 100644 index bdf7bd94..00000000 Binary files a/src/sprites/gen5/sgreninja-obond.png and /dev/null differ diff --git a/tools/smogdexspritesheet/index.ts b/tools/smogdexspritesheet/index.ts index fb3de739..8d64a6c7 100755 --- a/tools/smogdexspritesheet/index.ts +++ b/tools/smogdexspritesheet/index.ts @@ -33,7 +33,7 @@ for (let [filename, sprite] of Object.entries(result.coordinates)) { continue; } // TODO would like to use psid here, mess with it later. - for (let name of spritedata.smogonNames(parsed)) { + for (let name of spritedata.iconNames(parsed)) { sprites.set(name, sprite); } }