// ─── Crafting Store ───────────────────────────────────────────────────── import { create } from 'zustand'; import { persist } from 'zustand/middleware'; import type { DesignProgress, EnchantmentDesign, DesignEffect } from '../types'; import type { EquipmentSlot } from '../types/equipmentSlot'; import type { CraftingStore, CraftingState } from './craftingStore.types'; import * as CraftingUtils from '../crafting-utils'; import * as CraftingDesign from '../crafting-design'; import { useManaStore } from './manaStore'; import { useCombatStore } from './combatStore'; import { useUIStore } from './uiStore'; import * as ApplicationActions from '../crafting-actions/application-actions'; import * as PreparationActions from '../crafting-actions/preparation-actions'; import * as CraftingEquipment from '../crafting-equipment'; export const useCraftingStore = create()( persist( (set, get) => { const staffId = CraftingUtils.generateInstanceId(); const staffInstance = { instanceId: staffId, typeId: 'basicStaff', name: 'Basic Staff', enchantments: [{ effectId: 'spell_manaBolt', stacks: 1, actualCost: 50 }], usedCapacity: 50, totalCapacity: 50, rarity: 'common', quality: 100, tags: [], }; const shirtId = CraftingUtils.generateInstanceId(); const shirtInstance = { instanceId: shirtId, typeId: 'civilianShirt', name: 'Civilian Shirt', enchantments: [], usedCapacity: 0, totalCapacity: 30, rarity: 'common', quality: 100, tags: [], }; const shoesId = CraftingUtils.generateInstanceId(); const shoesInstance = { instanceId: shoesId, typeId: 'civilianShoes', name: 'Civilian Shoes', enchantments: [], usedCapacity: 0, totalCapacity: 15, rarity: 'common', quality: 100, tags: [], }; return { // Initial state designProgress: null, designProgress2: null, preparationProgress: null, applicationProgress: null, equipmentCraftingProgress: null, enchantmentDesigns: [], unlockedEffects: [], equippedInstances: { mainHand: staffId, offHand: null, head: null, body: shirtId, hands: null, feet: shoesId, accessory1: null, accessory2: null, }, equipmentInstances: { [staffId]: staffInstance, [shirtId]: shirtInstance, [shoesId]: shoesInstance, }, lootInventory: { materials: {}, blueprints: [], }, enchantmentSelection: { selectedEquipmentType: null, selectedEffects: [], designName: '', selectedDesign: null, selectedEquipmentInstance: null, }, // Actions setDesignProgress: (progress) => set({ designProgress: progress }), setDesignProgress2: (progress) => set({ designProgress2: progress }), setPreparationProgress: (progress) => set({ preparationProgress: progress }), setApplicationProgress: (progress) => set({ applicationProgress: progress }), setEquipmentCraftingProgress: (progress) => set({ equipmentCraftingProgress: progress }), // Enchantment design actions startDesigningEnchantment: (name, equipmentTypeId, effects) => { const state = get(); // crafting state const validation = CraftingDesign.validateDesignEffects(effects, equipmentTypeId, 0); if (!validation.valid) return false; const equipType = CraftingUtils.getEquipmentType(equipmentTypeId); if (!equipType) return false; const totalCapacityCost = CraftingDesign.calculateDesignCapacityCost(effects, 0); if (totalCapacityCost > equipType.baseCapacity) return false; let updates: Partial = {}; if (!state.designProgress) { updates = { designProgress: { designId: CraftingUtils.generateDesignId(), progress: 0, required: CraftingDesign.calculateDesignTime(effects), name, equipmentType: equipmentTypeId, effects, }, }; // Update currentAction in combatStore useCombatStore.setState({ currentAction: 'design' }); } else if (!state.designProgress2) { updates = { designProgress2: { designId: CraftingUtils.generateDesignId(), progress: 0, required: CraftingDesign.calculateDesignTime(effects), name, equipmentType: equipmentTypeId, effects, }, }; useCombatStore.setState({ currentAction: 'design' }); } else { return false; } set(updates); return true; }, cancelDesign: () => { const state = get(); if (state.designProgress) { set({ designProgress: null }); useCombatStore.setState({ currentAction: 'meditate' }); } else if (state.designProgress2) { set({ designProgress2: null }); } }, deleteDesign: (designId) => { set((state) => ({ enchantmentDesigns: state.enchantmentDesigns.filter(d => d.id !== designId), })); }, // Enchantment design save saveDesign: (design) => { const state = get(); if (state.designProgress2 && state.designProgress2.designId === design.id) { set((s) => ({ enchantmentDesigns: [...s.enchantmentDesigns, design], designProgress2: null, })); } else { set((s) => ({ enchantmentDesigns: [...s.enchantmentDesigns, design], designProgress: null, })); useCombatStore.setState({ currentAction: 'meditate' }); } }, // Enchantment application actions startApplying: (equipmentInstanceId, designId) => { const currentAction = useCombatStore.getState().currentAction; return ApplicationActions.startApplying( equipmentInstanceId, designId, get, set as unknown as (partial: Partial) => void, currentAction ); }, pauseApplication: () => { ApplicationActions.pauseApplication(get, set as unknown as (partial: Partial) => void); }, resumeApplication: () => { ApplicationActions.resumeApplication(get, set as unknown as (partial: Partial) => void); }, cancelApplication: () => { ApplicationActions.cancelApplication(set as unknown as (partial: Partial) => void); useCombatStore.setState({ currentAction: 'meditate' }); }, // Preparation actions startPreparing: (equipmentInstanceId) => { const rawMana = useManaStore.getState().rawMana; const result = PreparationActions.startPreparing( equipmentInstanceId, rawMana, get, set ); if (result) { useCombatStore.setState({ currentAction: 'prepare' }); } return result; }, cancelPreparation: () => { PreparationActions.cancelPreparation(set); useCombatStore.setState({ currentAction: 'meditate' }); }, // Equipment crafting actions startCraftingEquipment: (blueprintId: string) => { const state = get(); const rawMana = useManaStore.getState().rawMana; const currentAction = useCombatStore.getState().currentAction; // Check if we can start crafting const check = CraftingEquipment.canStartEquipmentCrafting( blueprintId, state.lootInventory.blueprints.includes(blueprintId), state.lootInventory.materials, rawMana, currentAction ); if (!check.canCraft) return false; // Initialize crafting const result = CraftingEquipment.initializeEquipmentCrafting( blueprintId, state.lootInventory.materials, rawMana ); // Update crafting store state set((s) => ({ lootInventory: { ...s.lootInventory, materials: result.newMaterials, }, equipmentCraftingProgress: result.progress, })); // Update mana store (deduct mana) useManaStore.setState((s) => ({ rawMana: s.rawMana - result.manaCost })); // Update combat store (set current action) useCombatStore.setState({ currentAction: 'craft' }); return true; }, cancelEquipmentCrafting: () => { const state = get(); const progress = state.equipmentCraftingProgress; if (!progress) return; // Get cancel result (mana refund) const cancelResult = CraftingEquipment.cancelEquipmentCrafting( progress.blueprintId, progress.manaSpent ); // Update crafting store state set({ equipmentCraftingProgress: null }); // Refund mana to mana store useManaStore.setState((s) => ({ rawMana: s.rawMana + cancelResult.manaRefund })); // Update combat store (reset action) useCombatStore.setState({ currentAction: 'meditate' }); // Add log message to UI store useUIStore.getState().addLog(cancelResult.logMessage); }, // Enchantment selection actions setSelectedEquipmentType: (type) => { set((s) => ({ enchantmentSelection: { ...s.enchantmentSelection, selectedEquipmentType: type }})); }, setSelectedEffects: (effects) => { set((s) => ({ enchantmentSelection: { ...s.enchantmentSelection, selectedEffects: effects } })); }, setDesignName: (name) => { set((s) => ({ enchantmentSelection: { ...s.enchantmentSelection, designName: name } })); }, setSelectedDesign: (id) => { set((s) => ({ enchantmentSelection: { ...s.enchantmentSelection, selectedDesign: id } })); }, setSelectedEquipmentInstance: (id) => { set((s) => ({ enchantmentSelection: { ...s.enchantmentSelection, selectedEquipmentInstance: id } })); }, resetEnchantmentSelection: () => { set((s) => ({ enchantmentSelection: { selectedEquipmentType: null, selectedEffects: [], designName: '', selectedDesign: null, selectedEquipmentInstance: null, }, })); }, // Loot inventory actions deleteMaterial: (materialId: string, amount: number) => { set((state) => { const newMaterials = { ...state.lootInventory.materials }; const currentAmount = newMaterials[materialId] || 0; const newAmount = Math.max(0, currentAmount - amount); if (newAmount <= 0) { delete newMaterials[materialId]; } else { newMaterials[materialId] = newAmount; } return { lootInventory: { ...state.lootInventory, materials: newMaterials, }, }; }); }, deleteEquipmentInstance: (instanceId: string) => { set((state) => { let newEquipped = { ...state.equippedInstances }; for (const [slot, id] of Object.entries(newEquipped)) { if (id === instanceId) { newEquipped[slot as EquipmentSlot] = null; } } const newInstances = { ...state.equipmentInstances }; delete newInstances[instanceId]; return { equippedInstances: newEquipped, equipmentInstances: newInstances, }; }); }, }; }, { name: 'mana-loop-crafting', partialize: (state) => ({ designProgress: state.designProgress, designProgress2: state.designProgress2, preparationProgress: state.preparationProgress, applicationProgress: state.applicationProgress, equipmentCraftingProgress: state.equipmentCraftingProgress, enchantmentDesigns: state.enchantmentDesigns, unlockedEffects: state.unlockedEffects, equipmentInstances: state.equipmentInstances, equippedInstances: state.equippedInstances, lootInventory: state.lootInventory, enchantmentSelection: state.enchantmentSelection, }), } ) );