// ─── Equipment Crafting System ────────────────────────────────────────────── // Equipment crafting functions extracted from crafting-slice.ts import type { EquipmentInstance, EquipmentCraftingProgress } from './types'; import { CRAFTING_RECIPES, canCraftRecipe, type CraftingRecipe } from './data/crafting-recipes'; import { EQUIPMENT_TYPES } from './data/equipment'; import { generateInstanceId } from './crafting-utils'; // ─── Equipment Crafting Validation ────────────────────────────────────────── // Check if equipment crafting can start export function canStartEquipmentCrafting( blueprintId: string, hasBlueprint: boolean, materials: Record, currentMana: number, currentAction: string ): { canCraft: boolean; reason?: string; recipe?: CraftingRecipe; missingMaterials?: Record; missingMana?: number } { if (currentAction !== 'meditate') { return { canCraft: false, reason: 'Must be in meditate state' }; } const recipe = CRAFTING_RECIPES[blueprintId]; if (!recipe) { return { canCraft: false, reason: 'Invalid blueprint' }; } if (!hasBlueprint) { return { canCraft: false, reason: 'Blueprint not acquired' }; } const { canCraft, missingMaterials } = canCraftRecipe(recipe, materials, currentMana); if (!canCraft) { const missingMana = Math.max(0, recipe.manaCost - currentMana); return { canCraft: false, reason: missingMana > 0 ? 'Insufficient mana' : 'Missing materials', recipe, missingMaterials, missingMana: missingMana > 0 ? missingMana : undefined, }; } return { canCraft: true, recipe }; } // ─── Equipment Crafting Execution ─────────────────────────────────────────── // Deduct crafting costs and initialize progress export interface CraftingInitResult { recipe: CraftingRecipe; newMaterials: Record; manaCost: number; progress: EquipmentCraftingProgress; } export function initializeEquipmentCrafting( blueprintId: string, materials: Record, currentMana: number ): CraftingInitResult { const recipe = CRAFTING_RECIPES[blueprintId]; // Deduct materials const newMaterials = { ...materials }; for (const [matId, amount] of Object.entries(recipe.materials)) { newMaterials[matId] = (newMaterials[matId] || 0) - amount; if (newMaterials[matId] <= 0) { delete newMaterials[matId]; } } // Create progress const progress: EquipmentCraftingProgress = { blueprintId, equipmentTypeId: recipe.equipmentTypeId, progress: 0, required: recipe.craftTime, manaSpent: recipe.manaCost, }; return { recipe, newMaterials, manaCost: recipe.manaCost, progress, }; } // ─── Crafting Progress ────────────────────────────────────────────────────── // Calculate crafting progress after a tick export interface CraftingTickResult { progress: number; isComplete: boolean; } export function calculateCraftingTick(currentProgress: number, required: number): CraftingTickResult { const progress = currentProgress + 0.04; // HOURS_PER_TICK return { progress, isComplete: progress >= required, }; } // ─── Crafting Completion ─────────────────────────────────────────────────── // Create equipment instance from completed crafting export function completeEquipmentCrafting( blueprintId: string, recipe: CraftingRecipe ): { instanceId: string; instance: EquipmentInstance; logMessage: string; } { const equipType = EQUIPMENT_TYPES[recipe.equipmentTypeId]; if (!equipType) { throw new Error(`Invalid equipment type: ${recipe.equipmentTypeId}`); } const instanceId = `equip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; const newInstance: EquipmentInstance = { instanceId, typeId: recipe.equipmentTypeId, name: recipe.name, enchantments: [], usedCapacity: 0, totalCapacity: equipType.baseCapacity, rarity: recipe.rarity, quality: 100, tags: [], }; return { instanceId, instance: newInstance, logMessage: `🔨 Crafted ${recipe.name}!`, }; } // ─── Crafting Cancellation ────────────────────────────────────────────────── // Cancel active crafting and refund partial resources export interface CraftingCancelResult { manaRefund: number; logMessage: string; } export function cancelEquipmentCrafting(blueprintId: string, manaSpent: number): CraftingCancelResult { const recipe = CRAFTING_RECIPES[blueprintId]; if (!recipe) { return { manaRefund: 0, logMessage: 'Invalid crafting recipe.', }; } // Refund 50% of mana const manaRefund = Math.floor(manaSpent * 0.5); return { manaRefund, logMessage: `🚫 Equipment crafting cancelled. Refunded ${manaRefund} mana.`, }; } // ─── Recipe Information ───────────────────────────────────────────────────── export function getRecipe(blueprintId: string): CraftingRecipe | null { return CRAFTING_RECIPES[blueprintId] || null; } export function getCraftableRecipes( blueprints: string[], materials: Record, currentMana: number ): CraftingRecipe[] { const craftable: CraftingRecipe[] = []; for (const blueprintId of blueprints) { const recipe = CRAFTING_RECIPES[blueprintId]; if (!recipe) continue; const { canCraft } = canCraftRecipe(recipe, materials, currentMana); if (canCraft) { craftable.push(recipe); } } return craftable; } // ─── Material Management ──────────────────────────────────────────────────── // Delete materials from inventory export function deleteMaterials(materialId: string, amount: number, materials: Record): { newMaterials: Record; deleted: number; } { const currentAmount = materials[materialId] || 0; const deleted = Math.min(amount, currentAmount); const remaining = Math.max(0, currentAmount - amount); const newMaterials = { ...materials }; if (remaining <= 0) { delete newMaterials[materialId]; } else { newMaterials[materialId] = remaining; } return { newMaterials, deleted, }; } // Get total material count export function getMaterialCount(materials: Record, materialId: string): number { return materials[materialId] || 0; } // Add materials to inventory export function addMaterials(materials: Record, materialId: string, amount: number): Record { const newMaterials = { ...materials }; newMaterials[materialId] = (newMaterials[materialId] || 0) + amount; return newMaterials; }