// ─── Fabricator Recipes ────────────────────────────────────────────────────── // Crafting recipes for the Fabricator attunement. // Each recipe is tied to a mana type the player has unlocked. import type { EquipmentSlot } from './equipment/types'; export interface FabricatorRecipe { id: string; name: string; description: string; /** Mana type required to craft this recipe (must be unlocked) */ manaType: string; /** Equipment type ID produced */ equipmentTypeId: string; /** Which slot the resulting equipment occupies */ slot: EquipmentSlot; /** Materials required: materialId -> count */ materials: Record; /** Mana cost in the recipe's mana type */ manaCost: number; /** Craft time in hours */ craftTime: number; /** Rarity tier */ rarity: 'common' | 'uncommon' | 'rare' | 'epic' | 'legendary'; /** Flavor text describing the gear's properties */ gearTrait: string; } export const FABRICATOR_RECIPES: FabricatorRecipe[] = [ // ─── Earth Gear (Compacted Earth — high defense) ────────────────────── { id: 'earthHelm', name: 'Earthen Helm', description: 'A sturdy helm carved from compacted stone.', manaType: 'earth', equipmentTypeId: 'wizardHat', slot: 'head', materials: { manaCrystalDust: 4, arcaneShard: 2 }, manaCost: 200, craftTime: 3, rarity: 'uncommon', gearTrait: '+15% physical resistance', }, { id: 'earthChest', name: 'Stoneguard Armor', description: 'Heavy stone plates layered over leather. Slow but nearly impenetrable.', manaType: 'earth', equipmentTypeId: 'scholarRobe', slot: 'body', materials: { manaCrystalDust: 8, arcaneShard: 4, elementalCore: 1 }, manaCost: 500, craftTime: 6, rarity: 'rare', gearTrait: '+25% physical resistance, -10% cast speed', }, { id: 'earthBoots', name: 'Stonegreaves', description: 'Boots reinforced with compacted earth. Firm footing in any battle.', manaType: 'earth', equipmentTypeId: 'travelerBoots', slot: 'feet', materials: { manaCrystalDust: 3, arcaneShard: 1 }, manaCost: 150, craftTime: 2, rarity: 'uncommon', gearTrait: '+10% physical resistance', }, // ─── Metal Gear (Fire+Earth — balanced offense/defense) ────────────── { id: 'metalBlade', name: 'Metal Blade', description: 'A blade forged from condensed metal mana. Sharp and durable.', manaType: 'metal', equipmentTypeId: 'steelBlade', slot: 'mainHand', materials: { manaCrystalDust: 6, arcaneShard: 3, elementalCore: 2 }, manaCost: 400, craftTime: 5, rarity: 'rare', gearTrait: '+20% damage, +10% durability', }, { id: 'metalShield', name: 'Metal Kite Shield', description: 'A polished metal shield. Reliable protection without excessive weight.', manaType: 'metal', equipmentTypeId: 'runicShield', slot: 'offHand', materials: { manaCrystalDust: 7, arcaneShard: 4, elementalCore: 1 }, manaCost: 450, craftTime: 5, rarity: 'rare', gearTrait: '+20% block chance', }, { id: 'metalGloves', name: 'Metalweave Gauntlets', description: 'Gauntlets woven with metal mana threads. Protective yet dexterous.', manaType: 'metal', equipmentTypeId: 'spellweaveGloves', slot: 'hands', materials: { manaCrystalDust: 4, arcaneShard: 2 }, manaCost: 250, craftTime: 3, rarity: 'uncommon', gearTrait: '+10% damage, +10% physical resistance', }, // ─── Crystal Gear (Sand+Sand+Light — high enchantment capacity) ────── { id: 'crystalWand', name: 'Crystal Focus Wand', description: 'A wand with a pure crystal core. Exceptional mana conductivity.', manaType: 'crystal', equipmentTypeId: 'crystalWand', slot: 'mainHand', materials: { manaCrystalDust: 10, arcaneShard: 5, elementalCore: 3 }, manaCost: 600, craftTime: 6, rarity: 'epic', gearTrait: '+40% enchantment capacity', }, { id: 'crystalRing', name: 'Crystal Ring', description: 'A ring set with a mana crystal. Amplifies enchantment effects.', manaType: 'crystal', equipmentTypeId: 'silverRing', slot: 'accessory1', materials: { manaCrystalDust: 5, arcaneShard: 3, elementalCore: 1 }, manaCost: 350, craftTime: 3, rarity: 'rare', gearTrait: '+15% enchantment capacity', }, { id: 'crystalAmulet', name: 'Crystal Pendant', description: 'An amulet housing a crystal shard. Enhances all enchantments worn.', manaType: 'crystal', equipmentTypeId: 'silverAmulet', slot: 'accessory2', materials: { manaCrystalDust: 6, arcaneShard: 3, elementalCore: 2 }, manaCost: 400, craftTime: 4, rarity: 'rare', gearTrait: '+10% all enchantment effects', }, // ─── Sand Gear (Earth+Water — lightweight, agile) ──────────────────── { id: 'sandBoots', name: 'Sandstrider Boots', description: 'Boots infused with sand mana. Light as air, silent as dust.', manaType: 'sand', equipmentTypeId: 'travelerBoots', slot: 'feet', materials: { manaCrystalDust: 3, arcaneShard: 1 }, manaCost: 120, craftTime: 2, rarity: 'uncommon', gearTrait: '+15% cast speed, +10% evasion', }, { id: 'sandGloves', name: 'Sandweave Gloves', description: 'Gloves woven from sand mana. Nimble fingers for delicate enchanting.', manaType: 'sand', equipmentTypeId: 'spellweaveGloves', slot: 'hands', materials: { manaCrystalDust: 3, arcaneShard: 2 }, manaCost: 140, craftTime: 2, rarity: 'uncommon', gearTrait: '+10% cast speed', }, { id: 'sandVest', name: 'Sandcloth Vest', description: 'A light vest woven from sand mana. Offers minimal protection but maximum mobility.', manaType: 'sand', equipmentTypeId: 'scholarRobe', slot: 'body', materials: { manaCrystalDust: 5, arcaneShard: 2, elementalCore: 1 }, manaCost: 300, craftTime: 4, rarity: 'rare', gearTrait: '+20% cast speed, +5% evasion', }, ]; // ─── Helpers ────────────────────────────────────────────────────────────────── export function getRecipesByManaType(manaType: string): FabricatorRecipe[] { return FABRICATOR_RECIPES.filter(r => r.manaType === manaType); } export function getRecipeById(id: string): FabricatorRecipe | undefined { return FABRICATOR_RECIPES.find(r => r.id === id); } export function canCraftRecipe( recipe: FabricatorRecipe, materials: Record, manaAmount: number, manaType?: string, ): { canCraft: boolean; missingMaterials: Record; missingMana: number } { const missingMaterials: Record = {}; let canCraft = true; for (const [matId, required] of Object.entries(recipe.materials)) { const available = materials[matId] || 0; if (available < required) { missingMaterials[matId] = required - available; canCraft = false; } } // If manaType is provided, manaAmount is already the correct pool value. // Otherwise fall back to treating manaAmount as raw mana (backward compat). const effectiveManaType = manaType ?? recipe.manaType; const missingMana = Math.max(0, recipe.manaCost - manaAmount); if (missingMana > 0) { canCraft = false; } return { canCraft, missingMaterials, missingMana }; }