fix: BUG 4 - Add starting equipment to craftingStore initial state
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 2m9s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 2m9s
This commit is contained in:
@@ -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) => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user