fix: BUG 4 - Add starting equipment to craftingStore initial state
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 2m9s

This commit is contained in:
2026-05-07 14:07:23 +02:00
parent be918d1bab
commit 58aa74486e
+243 -241
View File
@@ -92,265 +92,267 @@ export type CraftingStore = CraftingState & CraftingActions;
export const useCraftingStore = create<CraftingStore>()( export const useCraftingStore = create<CraftingStore>()(
persist( persist(
(set, get) => ({ (set, get) => {
// Initial state const startingEquipment = createStartingEquipment();
designProgress: null, return {
designProgress2: null, // Initial state
preparationProgress: null, designProgress: null,
applicationProgress: null, designProgress2: null,
equipmentCraftingProgress: null, preparationProgress: null,
enchantmentDesigns: [], applicationProgress: null,
unlockedEffects: [], equipmentCraftingProgress: null,
equipmentInstances: {}, enchantmentDesigns: [],
equippedInstances: {}, unlockedEffects: [],
lootInventory: { ...startingEquipment,
materials: {}, lootInventory: {
blueprints: [], materials: {},
}, blueprints: [],
},
// Actions // Actions
setDesignProgress: (progress) => set({ designProgress: progress }), setDesignProgress: (progress) => set({ designProgress: progress }),
setDesignProgress2: (progress) => set({ designProgress2: progress }), setDesignProgress2: (progress) => set({ designProgress2: progress }),
setPreparationProgress: (progress) => set({ preparationProgress: progress }), setPreparationProgress: (progress) => set({ preparationProgress: progress }),
setApplicationProgress: (progress) => set({ applicationProgress: progress }), setApplicationProgress: (progress) => set({ applicationProgress: progress }),
setEquipmentCraftingProgress: (progress) => set({ equipmentCraftingProgress: progress }), setEquipmentCraftingProgress: (progress) => set({ equipmentCraftingProgress: progress }),
// Enchantment design actions // Enchantment design actions
startDesigningEnchantment: (name, equipmentTypeId, effects) => { startDesigningEnchantment: (name, equipmentTypeId, effects) => {
// Get state from other stores // Get state from other stores
const skillState = useSkillStore.getState(); const skillState = useSkillStore.getState();
const state = get(); // crafting state const state = get(); // crafting state
const enchantingLevel = skillState.skills?.enchanting || 0; const enchantingLevel = skillState.skills?.enchanting || 0;
const validation = CraftingDesign.validateDesignEffects(effects, equipmentTypeId, enchantingLevel); const validation = CraftingDesign.validateDesignEffects(effects, equipmentTypeId, enchantingLevel);
if (!validation.valid) return false; if (!validation.valid) return false;
const equipType = CraftingUtils.getEquipmentType(equipmentTypeId); const equipType = CraftingUtils.getEquipmentType(equipmentTypeId);
if (!equipType) return false; if (!equipType) return false;
const efficiencyBonus = (skillState.skillUpgrades?.['efficientEnchant'] || []).length * 0.05 || 0; const efficiencyBonus = (skillState.skillUpgrades?.['efficientEnchant'] || []).length * 0.05 || 0;
const totalCapacityCost = CraftingDesign.calculateDesignCapacityCost(effects, efficiencyBonus); const totalCapacityCost = CraftingDesign.calculateDesignCapacityCost(effects, efficiencyBonus);
if (totalCapacityCost > equipType.baseCapacity) return false; if (totalCapacityCost > equipType.baseCapacity) return false;
const computedEffects = computeEffects(skillState.skillUpgrades || {}, skillState.skillTiers || {}); const computedEffects = computeEffects(skillState.skillUpgrades || {}, skillState.skillTiers || {});
const hasEnchantMastery = hasSpecial(computedEffects, SPECIAL_EFFECTS.ENCHANT_MASTERY); const hasEnchantMastery = hasSpecial(computedEffects, SPECIAL_EFFECTS.ENCHANT_MASTERY);
let updates: Partial<CraftingState> = {}; let updates: Partial<CraftingState> = {};
if (!state.designProgress) { if (!state.designProgress) {
updates = { updates = {
designProgress: { designProgress: {
designId: CraftingUtils.generateDesignId(), designId: CraftingUtils.generateDesignId(),
progress: 0, progress: 0,
required: CraftingDesign.calculateDesignTime(effects), required: CraftingDesign.calculateDesignTime(effects),
name, name,
equipmentType: equipmentTypeId, equipmentType: equipmentTypeId,
effects, effects,
}, },
}; };
// Update currentAction in combatStore // Update currentAction in combatStore
useCombatStore.setState({ currentAction: 'design' }); useCombatStore.setState({ currentAction: 'design' });
} else if (hasEnchantMastery && !state.designProgress2) { } else if (hasEnchantMastery && !state.designProgress2) {
updates = { updates = {
designProgress2: { designProgress2: {
designId: CraftingUtils.generateDesignId(), designId: CraftingUtils.generateDesignId(),
progress: 0, progress: 0,
required: CraftingDesign.calculateDesignTime(effects), required: CraftingDesign.calculateDesignTime(effects),
name, name,
equipmentType: equipmentTypeId, equipmentType: equipmentTypeId,
effects, 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 { } else {
newMaterials[materialId] = newAmount; return false;
} }
return { 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: { lootInventory: {
...state.lootInventory, ...s.lootInventory,
materials: newMaterials, materials: result.newMaterials,
}, },
}; equipmentCraftingProgress: result.progress,
}); }));
},
deleteEquipmentInstance: (instanceId: string) => { // Update mana store (deduct mana)
set((state) => { useManaStore.setState((s) => ({ rawMana: s.rawMana - result.manaCost }));
let newEquipped = { ...state.equippedInstances };
for (const [slot, id] of Object.entries(newEquipped)) { // Update combat store (set current action)
if (id === instanceId) { useCombatStore.setState({ currentAction: 'craft' });
newEquipped[slot as any] = null;
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;
} }
}
const newInstances = { ...state.equipmentInstances }; return {
delete newInstances[instanceId]; lootInventory: {
...state.lootInventory,
materials: newMaterials,
},
};
});
},
return { deleteEquipmentInstance: (instanceId: string) => {
equippedInstances: newEquipped, set((state) => {
equipmentInstances: newInstances, 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', name: 'mana-loop-crafting',
partialize: (state) => ({ partialize: (state) => ({