import { isShopOnlyStyleVariant } from "@/lib/character/variant-access"; import type { CharacterLayerId } from "@/lib/character/presets"; import { CHARACTER_LAYERS, getVariantDisplayName, NONE_VARIANT_ID, } from "@/lib/character/presets"; import { getRoomBackground, getShopRoomBackgrounds } from "@/lib/room-backgrounds"; export type ShopLayerId = Exclude; export type ShopItemType = ShopLayerId | "room"; export type ShopItemRecord = { id: string; name: string; type: ShopItemType; price: number; image_path: string; }; export type ShopStyleItem = { layerId: ShopLayerId; variantId: string; }; const SHOP_LAYER_IDS = new Set([ "pants", "shoes", "torso", "eyes", "head", ]); export function isShopLayerId(value: string): value is ShopLayerId { return SHOP_LAYER_IDS.has(value as ShopLayerId); } /** Parse a character variant id (e.g. head-1) into layer + variant. */ export function parseVariantId(variantId: string): ShopStyleItem | null { for (const layerId of SHOP_LAYER_IDS) { if (variantId.startsWith(`${layerId}-`)) { return { layerId, variantId }; } } return null; } export function parseShopStyleItem( itemId: string, itemType: string, ): ShopStyleItem | null { if (!isShopLayerId(itemType) || !itemId.startsWith(`${itemType}-`)) { return null; } return { layerId: itemType, variantId: itemId }; } export function getShopCatalogFromPresets(): ShopItemRecord[] { const styleItems = CHARACTER_LAYERS.flatMap((layer) => { if (layer.id === "skin") { return []; } return layer.variants .filter( (variant) => variant.id !== NONE_VARIANT_ID && isShopOnlyStyleVariant(variant.id), ) .map((variant) => ({ id: variant.id, name: variant.label, type: layer.id as ShopLayerId, price: getDefaultPriceForLayer(layer.id as ShopLayerId, variant.id), image_path: variant.src, })); }); return [...styleItems, ...getShopRoomBackgrounds()]; } function getDefaultPriceForLayer(layerId: ShopLayerId, variantId: string) { const number = Number.parseInt(variantId.split("-").pop() ?? "1", 10); const baseByLayer: Record = { pants: 20, shoes: 20, torso: 25, eyes: 15, head: 30, }; return baseByLayer[layerId] + (number - 1) * 5; } export function getLayerLabel(layerId: ShopLayerId) { return CHARACTER_LAYERS.find((layer) => layer.id === layerId)?.label ?? layerId; } export function getShopItemDisplayName(item: ShopItemRecord): string { if (item.type === "room") { return getRoomBackground(item.id).name; } return getVariantDisplayName(item.id, item.name); } export function findShopItemById( items: readonly ShopItemRecord[], itemId: string, ): ShopItemRecord | undefined { return items.find((item) => item.id === itemId); }