// ─── Crafting Store ───────────────────────────────────────────────────── // Handles equipment crafting, enchantment design, and crafting progress // This is a modular store that manages all crafting-related state import { create } from 'zustand'; import { persist } from 'zustand/middleware'; import type { DesignProgress, PreparationProgress, ApplicationProgress, EquipmentCraftingProgress, EnchantmentDesign, EquipmentInstance, DesignEffect } from '../types'; // Import crafting modules for action logic import * as CraftingUtils from '../crafting-utils'; import * as CraftingDesign from '../crafting-design'; import { computeEffects } from '../upgrade-effects'; import { hasSpecial, SPECIAL_EFFECTS } from '../special-effects'; // Import other stores to access required state import { useSkillStore } from './skillStore'; import { useGameStore } from './gameStore'; import { useManaStore } from './manaStore'; import { useCombatStore } from './combatStore'; import { createStartingEquipment } from '../store/crafting-modules/starting-equipment'; import { useUIStore } from './uiStore'; // Import action modules import * as ApplicationActions from '../crafting-actions/application-actions'; import * as CraftingApply from '../crafting-apply'; import * as PreparationActions from '../crafting-actions/preparation-actions'; import * as CraftingEquipment from '../crafting-equipment'; export interface CraftingState { // Crafting progress designProgress: DesignProgress | null; designProgress2: DesignProgress | null; // For ENCHANT_MASTERY (2 concurrent designs) preparationProgress: PreparationProgress | null; applicationProgress: ApplicationProgress | null; equipmentCraftingProgress: EquipmentCraftingProgress | null; // Enchantment designs enchantmentDesigns: EnchantmentDesign[]; // Unlocked enchantment effects unlockedEffects: string[]; // Equipment instances (instanceId -> instance) equipmentInstances: Record; // Equipped instances (slot -> instanceId or null) equippedInstances: Record; // Loot inventory lootInventory: { materials: Record; blueprints: string[]; }; } export interface CraftingActions { // Actions for design progress setDesignProgress: (progress: DesignProgress | null) => void; setDesignProgress2: (progress: DesignProgress | null) => void; // Actions for preparation progress setPreparationProgress: (progress: PreparationProgress | null) => void; // Actions for application progress setApplicationProgress: (progress: ApplicationProgress | null) => void; // Actions for equipment crafting progress setEquipmentCraftingProgress: (progress: EquipmentCraftingProgress | null) => void; // Enchantment design actions startDesigningEnchantment: (name: string, equipmentTypeId: string, effects: DesignEffect[]) => boolean; cancelDesign: () => void; saveDesign: (design: EnchantmentDesign) => void; deleteDesign: (designId: string) => void; // Enchantment application actions startApplying: (equipmentInstanceId: string, designId: string) => boolean; pauseApplication: () => void; resumeApplication: () => void; cancelApplication: () => void; // Enchantment preparation actions startPreparing: (equipmentInstanceId: string) => boolean; cancelPreparation: () => void; // Loot inventory actions deleteMaterial: (materialId: string, amount: number) => void; deleteEquipmentInstance: (instanceId: string) => void; // Equipment crafting actions startCraftingEquipment: (blueprintId: string) => boolean; cancelEquipmentCrafting: () => void; } export type CraftingStore = CraftingState & CraftingActions; export const useCraftingStore = create()( persist( (set, get) => { const startingEquipment = createStartingEquipment(); return { // Initial state designProgress: null, designProgress2: null, preparationProgress: null, applicationProgress: null, equipmentCraftingProgress: null, enchantmentDesigns: [], unlockedEffects: [], ...startingEquipment, lootInventory: { materials: {}, blueprints: [], }, // 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) => { // Get state from other stores const skillState = useSkillStore.getState(); const state = get(); // crafting state const enchantingLevel = skillState.skills?.enchanting || 0; const validation = CraftingDesign.validateDesignEffects(effects, equipmentTypeId, enchantingLevel); if (!validation.valid) return false; const equipType = CraftingUtils.getEquipmentType(equipmentTypeId); if (!equipType) return false; const efficiencyBonus = (skillState.skillUpgrades?.['efficientEnchant'] || []).length * 0.05 || 0; const totalCapacityCost = CraftingDesign.calculateDesignCapacityCost(effects, efficiencyBonus); if (totalCapacityCost > equipType.baseCapacity) return false; const computedEffects = computeEffects(skillState.skillUpgrades || {}, skillState.skillTiers || {}); const hasEnchantMastery = hasSpecial(computedEffects, SPECIAL_EFFECTS.ENCHANT_MASTERY); 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 (hasEnchantMastery && !state.designProgress2) { updates = { designProgress2: { designId: CraftingUtils.generateDesignId(), progress: 0, required: CraftingDesign.calculateDesignTime(effects), name, equipmentType: equipmentTypeId, effects, }, }; } else { return false; } set(updates); return true; }, cancelDesign: () => { const state = get(); if (state.designProgress2 && !state.designProgress) { set({ designProgress2: null }); } else { set({ designProgress: null }); useCombatStore.setState({ currentAction: 'meditate' }); } }, 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) => { return ApplicationActions.startApplying( equipmentInstanceId, designId, get, set ); }, pauseApplication: () => { ApplicationActions.pauseApplication(get, set); }, resumeApplication: () => { ApplicationActions.resumeApplication(get, set); }, cancelApplication: () => { ApplicationActions.cancelApplication(set); useCombatStore.setState({ currentAction: 'meditate' }); }, // Preparation actions startPreparing: (equipmentInstanceId) => { // Get rawMana from manaStore const rawMana = useManaStore.getState().rawMana; // Temporary state to pass to preparation action const tempState = { ...get(), rawMana } as any; return PreparationActions.startPreparing( equipmentInstanceId, () => tempState, set ); }, 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); }, // 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 any] = 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, }), } ) );