pokerogue/src/utils/ribbon-utils.ts
Wlowscha a55b2b18e8
[UI/UX][Beta] Adjustments to display of ribbons (#6709)
* Introduce custom ordering of ribbons

* Displaying classic ribbon for mons that have at least one classic win

---------

Co-authored-by: damocleas <damocleas25@gmail.com>
2025-10-29 18:27:03 -04:00

217 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { pokemonEvolutions } from "#balance/pokemon-evolutions";
import type { PokemonSpecies } from "#data/pokemon-species";
import { PokemonType } from "#enums/pokemon-type";
import { RibbonData, type RibbonFlag } from "#system/ribbons/ribbon-data";
import { getPokemonSpecies } from "./pokemon-utils";
export function getRibbonForType(type: PokemonType): RibbonFlag {
// Valid types: 017, excluding UNKNOWN (-1) and STELLAR (19)
if (type < PokemonType.NORMAL || type > PokemonType.FAIRY) {
return 0n;
}
return (1n << BigInt(type)) as RibbonFlag;
}
export function getRibbonForGeneration(gen: number): RibbonFlag {
// Valid generations: 19
if (gen < 1 || gen > 9) {
return 0n;
}
return (1n << BigInt(17 + gen)) as RibbonFlag;
}
export function extractRibbons(data: bigint): RibbonFlag[] {
const ribbons: RibbonFlag[] = [];
let bit = 1n;
while (bit <= data) {
if ((data & bit) !== 0n) {
ribbons.push(bit as RibbonFlag);
}
bit <<= 1n; // move to the next bit
}
return ribbons;
}
export function getAvailableRibbons(species: PokemonSpecies): RibbonFlag[] {
const ribbons: RibbonFlag[] = [
RibbonData.CLASSIC,
RibbonData.NUZLOCKE,
RibbonData.FRIENDSHIP,
RibbonData.FLIP_STATS,
RibbonData.INVERSE,
RibbonData.FRESH_START,
RibbonData.HARDCORE,
RibbonData.LIMITED_CATCH,
RibbonData.NO_HEAL,
RibbonData.NO_SHOP,
RibbonData.NO_SUPPORT,
];
let data = 0n;
const speciesToCheck = [species.speciesId];
while (speciesToCheck.length > 0) {
const checking = speciesToCheck.pop();
if (checking == null) {
continue;
}
const checkingSpecies = getPokemonSpecies(checking);
data |= getRibbonForGeneration(checkingSpecies.generation);
data |= getRibbonForType(checkingSpecies.type1);
if (checkingSpecies.type2 != null) {
data |= getRibbonForType(checkingSpecies.type2);
}
for (const form of checkingSpecies.forms) {
data |= getRibbonForType(form.type1);
if (form.type2 != null) {
data |= getRibbonForType(form.type2);
}
}
if (checking && pokemonEvolutions.hasOwnProperty(checking)) {
pokemonEvolutions[checking].forEach(e => {
speciesToCheck.push(e.speciesId);
});
}
}
const extraRibbons = extractRibbons(data);
return ribbons.concat(extraRibbons);
}
/**
* Get the locale key for the given ribbon flag
* @param flag - The ribbon flag to get the key for
*/
export function getRibbonKey(flag: RibbonFlag): string {
switch (flag) {
case RibbonData.CLASSIC:
return "classic";
case RibbonData.NUZLOCKE:
return "nuzlocke";
case RibbonData.FRIENDSHIP:
return "friendship";
case RibbonData.FLIP_STATS:
return "flipStats";
case RibbonData.INVERSE:
return "inverse";
case RibbonData.FRESH_START:
return "freshStart";
case RibbonData.HARDCORE:
return "hardcore";
case RibbonData.LIMITED_CATCH:
return "limitedCatch";
case RibbonData.NO_HEAL:
return "noHeal";
case RibbonData.NO_SHOP:
return "noShop";
case RibbonData.NO_SUPPORT:
return "noSupport";
case RibbonData.MONO_NORMAL:
return "monoNormal";
case RibbonData.MONO_FIGHTING:
return "monoFighting";
case RibbonData.MONO_FLYING:
return "monoFlying";
case RibbonData.MONO_POISON:
return "monoPoison";
case RibbonData.MONO_GROUND:
return "monoGround";
case RibbonData.MONO_ROCK:
return "monoRock";
case RibbonData.MONO_BUG:
return "monoBug";
case RibbonData.MONO_GHOST:
return "monoGhost";
case RibbonData.MONO_STEEL:
return "monoSteel";
case RibbonData.MONO_FIRE:
return "monoFire";
case RibbonData.MONO_WATER:
return "monoWater";
case RibbonData.MONO_GRASS:
return "monoGrass";
case RibbonData.MONO_ELECTRIC:
return "monoElectric";
case RibbonData.MONO_PSYCHIC:
return "monoPsychic";
case RibbonData.MONO_ICE:
return "monoIce";
case RibbonData.MONO_DRAGON:
return "monoDragon";
case RibbonData.MONO_DARK:
return "monoDark";
case RibbonData.MONO_FAIRY:
return "monoFairy";
case RibbonData.MONO_GEN_1:
return "monoGen1";
case RibbonData.MONO_GEN_2:
return "monoGen2";
case RibbonData.MONO_GEN_3:
return "monoGen3";
case RibbonData.MONO_GEN_4:
return "monoGen4";
case RibbonData.MONO_GEN_5:
return "monoGen5";
case RibbonData.MONO_GEN_6:
return "monoGen6";
case RibbonData.MONO_GEN_7:
return "monoGen7";
case RibbonData.MONO_GEN_8:
return "monoGen8";
case RibbonData.MONO_GEN_9:
return "monoGen9";
default:
return "";
}
}
/**
* This list is used to determined the display order of ribbons in the Pokédex.
*/
export const orderedRibbons: RibbonFlag[] = [
RibbonData.CLASSIC,
RibbonData.FRIENDSHIP,
RibbonData.FRESH_START,
RibbonData.HARDCORE,
RibbonData.LIMITED_CATCH,
RibbonData.NUZLOCKE,
RibbonData.NO_HEAL,
RibbonData.NO_SHOP,
RibbonData.NO_SUPPORT,
RibbonData.MONO_GEN_1,
RibbonData.MONO_GEN_2,
RibbonData.MONO_GEN_3,
RibbonData.MONO_GEN_4,
RibbonData.MONO_GEN_5,
RibbonData.MONO_GEN_6,
RibbonData.MONO_GEN_7,
RibbonData.MONO_GEN_8,
RibbonData.MONO_GEN_9,
RibbonData.MONO_NORMAL,
RibbonData.MONO_FIGHTING,
RibbonData.MONO_FLYING,
RibbonData.MONO_POISON,
RibbonData.MONO_GROUND,
RibbonData.MONO_ROCK,
RibbonData.MONO_BUG,
RibbonData.MONO_GHOST,
RibbonData.MONO_STEEL,
RibbonData.MONO_FIRE,
RibbonData.MONO_WATER,
RibbonData.MONO_GRASS,
RibbonData.MONO_ELECTRIC,
RibbonData.MONO_PSYCHIC,
RibbonData.MONO_ICE,
RibbonData.MONO_DRAGON,
RibbonData.MONO_DARK,
RibbonData.MONO_FAIRY,
RibbonData.INVERSE,
RibbonData.FLIP_STATS,
];