fix: 6 priority-3 bug fixes with regression tests
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m24s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m24s
- Issue 83: Mana Tide pulse factor now ranges 0.5x-1.5x (was 0.5x-1.0x) - Issue 82: SteadyStream no longer returns early like EternalFlow; only skips incursion penalty - Issue 81: Prestige store partialize now includes defeatedGuardians, signedPacts, signedPactDetails, pactRitualFloor, pactRitualProgress, loopInsight, pactSlots - Issue 80: Combat store partialize now includes floorHP, floorMaxHP, castProgress, spireMode, clearedFloors, golemancy, equipmentSpellStates, activityLog, achievements - Issue 78: cancelDesign now always cancels designProgress first, then designProgress2 - Issue 79: startDesigningEnchantment now uses designProgress2 when designProgress is occupied Added 13 regression tests in src/lib/game/__tests__/regression-fixes.test.ts Refactored craftingStore types to craftingStore.types.ts to stay under 400-line limit
This commit is contained in:
@@ -275,6 +275,15 @@ export const useCombatStore = create<CombatState>()(
|
||||
maxFloorReached: state.maxFloorReached,
|
||||
spells: state.spells,
|
||||
activeSpell: state.activeSpell,
|
||||
floorHP: state.floorHP,
|
||||
floorMaxHP: state.floorMaxHP,
|
||||
castProgress: state.castProgress,
|
||||
spireMode: state.spireMode,
|
||||
clearedFloors: state.clearedFloors,
|
||||
golemancy: state.golemancy,
|
||||
equipmentSpellStates: state.equipmentSpellStates,
|
||||
activityLog: state.activityLog,
|
||||
achievements: state.achievements,
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// ─── Crafting Store ─────────────────────────────────────────────────────
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
import type { DesignProgress, PreparationProgress, ApplicationProgress, EquipmentCraftingProgress, EnchantmentDesign, EquipmentInstance, DesignEffect } from '../types';
|
||||
import type { DesignProgress, EnchantmentDesign, DesignEffect } from '../types';
|
||||
import type { CraftingStore, CraftingState } from './craftingStore.types';
|
||||
import * as CraftingUtils from '../crafting-utils';
|
||||
import * as CraftingDesign from '../crafting-design';
|
||||
import { useManaStore } from './manaStore';
|
||||
@@ -12,87 +13,6 @@ import * as ApplicationActions from '../crafting-actions/application-actions';
|
||||
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<string, EquipmentInstance>;
|
||||
// Equipped instances (slot -> instanceId or null)
|
||||
equippedInstances: Record<string, string | null>;
|
||||
// Loot inventory
|
||||
lootInventory: {
|
||||
materials: Record<string, number>;
|
||||
blueprints: string[];
|
||||
};
|
||||
|
||||
// Enchantment selection state (single source of truth for enchanting UI)
|
||||
enchantmentSelection: {
|
||||
selectedEquipmentType: string | null;
|
||||
selectedEffects: DesignEffect[];
|
||||
designName: string;
|
||||
selectedDesign: string | null;
|
||||
selectedEquipmentInstance: string | null;
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// Enchantment selection actions (store as source of truth)
|
||||
setSelectedEquipmentType: (type: string | null) => void;
|
||||
setSelectedEffects: (effects: DesignEffect[]) => void;
|
||||
setDesignName: (name: string) => void;
|
||||
setSelectedDesign: (id: string | null) => void;
|
||||
setSelectedEquipmentInstance: (id: string | null) => void;
|
||||
resetEnchantmentSelection: () => void;
|
||||
}
|
||||
|
||||
export type CraftingStore = CraftingState & CraftingActions;
|
||||
|
||||
export const useCraftingStore = create<CraftingStore>()(
|
||||
persist(
|
||||
(set, get) => {
|
||||
@@ -155,6 +75,18 @@ export const useCraftingStore = create<CraftingStore>()(
|
||||
};
|
||||
// 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;
|
||||
}
|
||||
@@ -165,11 +97,11 @@ export const useCraftingStore = create<CraftingStore>()(
|
||||
|
||||
cancelDesign: () => {
|
||||
const state = get();
|
||||
if (state.designProgress2 && !state.designProgress) {
|
||||
set({ designProgress2: null });
|
||||
} else {
|
||||
if (state.designProgress) {
|
||||
set({ designProgress: null });
|
||||
useCombatStore.setState({ currentAction: 'meditate' });
|
||||
} else if (state.designProgress2) {
|
||||
set({ designProgress2: null });
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// ─── Crafting Store Types ────────────────────────────────────────────────────
|
||||
import type {
|
||||
DesignProgress,
|
||||
PreparationProgress,
|
||||
ApplicationProgress,
|
||||
EquipmentCraftingProgress,
|
||||
EnchantmentDesign,
|
||||
EquipmentInstance,
|
||||
DesignEffect,
|
||||
} from '../types';
|
||||
|
||||
export interface CraftingState {
|
||||
designProgress: DesignProgress | null;
|
||||
designProgress2: DesignProgress | null;
|
||||
preparationProgress: PreparationProgress | null;
|
||||
applicationProgress: ApplicationProgress | null;
|
||||
equipmentCraftingProgress: EquipmentCraftingProgress | null;
|
||||
enchantmentDesigns: EnchantmentDesign[];
|
||||
unlockedEffects: string[];
|
||||
equipmentInstances: Record<string, EquipmentInstance>;
|
||||
equippedInstances: Record<string, string | null>;
|
||||
lootInventory: {
|
||||
materials: Record<string, number>;
|
||||
blueprints: string[];
|
||||
};
|
||||
enchantmentSelection: {
|
||||
selectedEquipmentType: string | null;
|
||||
selectedEffects: DesignEffect[];
|
||||
designName: string;
|
||||
selectedDesign: string | null;
|
||||
selectedEquipmentInstance: string | null;
|
||||
};
|
||||
}
|
||||
|
||||
export interface CraftingActions {
|
||||
setDesignProgress: (progress: DesignProgress | null) => void;
|
||||
setDesignProgress2: (progress: DesignProgress | null) => void;
|
||||
setPreparationProgress: (progress: PreparationProgress | null) => void;
|
||||
setApplicationProgress: (progress: ApplicationProgress | null) => void;
|
||||
setEquipmentCraftingProgress: (progress: EquipmentCraftingProgress | null) => void;
|
||||
startDesigningEnchantment: (name: string, equipmentTypeId: string, effects: DesignEffect[]) => boolean;
|
||||
cancelDesign: () => void;
|
||||
saveDesign: (design: EnchantmentDesign) => void;
|
||||
deleteDesign: (designId: string) => void;
|
||||
startApplying: (equipmentInstanceId: string, designId: string) => boolean;
|
||||
pauseApplication: () => void;
|
||||
resumeApplication: () => void;
|
||||
cancelApplication: () => void;
|
||||
startPreparing: (equipmentInstanceId: string) => boolean;
|
||||
cancelPreparation: () => void;
|
||||
deleteMaterial: (materialId: string, amount: number) => void;
|
||||
deleteEquipmentInstance: (instanceId: string) => void;
|
||||
startCraftingEquipment: (blueprintId: string) => boolean;
|
||||
cancelEquipmentCrafting: () => void;
|
||||
setSelectedEquipmentType: (type: string | null) => void;
|
||||
setSelectedEffects: (effects: DesignEffect[]) => void;
|
||||
setDesignName: (name: string) => void;
|
||||
setSelectedDesign: (id: string | null) => void;
|
||||
setSelectedEquipmentInstance: (id: string | null) => void;
|
||||
resetEnchantmentSelection: () => void;
|
||||
}
|
||||
|
||||
export type CraftingStore = CraftingState & CraftingActions;
|
||||
@@ -290,10 +290,16 @@ export const usePrestigeStore = create<PrestigeState>()(
|
||||
loopCount: state.loopCount,
|
||||
insight: state.insight,
|
||||
totalInsight: state.totalInsight,
|
||||
loopInsight: state.loopInsight,
|
||||
prestigeUpgrades: state.prestigeUpgrades,
|
||||
memorySlots: state.memorySlots,
|
||||
pactSlots: state.pactSlots,
|
||||
memories: state.memories,
|
||||
defeatedGuardians: state.defeatedGuardians,
|
||||
signedPacts: state.signedPacts,
|
||||
signedPactDetails: state.signedPactDetails,
|
||||
pactRitualFloor: state.pactRitualFloor,
|
||||
pactRitualProgress: state.pactRitualProgress,
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user