// ─── Pact Slice ─────────────────────────────────────────────────────────────── // Manages guardian pacts, signing, and mana unlocking import type { StateCreator } from 'zustand'; import type { GameState } from '../types'; import { GUARDIANS, ELEMENTS } from '../constants'; import { computePactMultiplier, computePactInsightMultiplier } from './computed'; export interface PactSlice { // State signedPacts: number[]; pendingPactOffer: number | null; maxPacts: number; pactSigningProgress: { floor: number; progress: number; required: number; manaCost: number; } | null; signedPactDetails: Record; }>; pactInterferenceMitigation: number; pactSynergyUnlocked: boolean; // Actions acceptPact: (floor: number) => void; declinePact: (floor: number) => void; // Computed getters getPactMultiplier: () => number; getPactInsightMultiplier: () => number; } export const createPactSlice = ( set: StateCreator['set'], get: () => GameState ): PactSlice => ({ signedPacts: [], pendingPactOffer: null, maxPacts: 1, pactSigningProgress: null, signedPactDetails: {}, pactInterferenceMitigation: 0, pactSynergyUnlocked: false, acceptPact: (floor: number) => { const state = get(); const guardian = GUARDIANS[floor]; if (!guardian || state.signedPacts.includes(floor)) return; const maxPacts = 1 + (state.prestigeUpgrades.pactCapacity || 0); if (state.signedPacts.length >= maxPacts) { set({ log: [`⚠️ Cannot sign more pacts! Maximum: ${maxPacts}.`, ...state.log.slice(0, 49)], }); return; } const baseCost = guardian.signingCost.mana; const discount = Math.min((state.prestigeUpgrades.pactDiscount || 0) * 0.1, 0.5); const manaCost = Math.floor(baseCost * (1 - discount)); if (state.rawMana < manaCost) { set({ log: [`⚠️ Need ${manaCost} mana to sign pact with ${guardian.name}!`, ...state.log.slice(0, 49)], }); return; } const baseTime = guardian.signingCost.time; const haste = Math.min((state.prestigeUpgrades.pactHaste || 0) * 0.1, 0.5); const signingTime = Math.max(1, baseTime * (1 - haste)); set({ rawMana: state.rawMana - manaCost, pactSigningProgress: { floor, progress: 0, required: signingTime, manaCost, }, pendingPactOffer: null, currentAction: 'study', log: [`📜 Beginning pact signing with ${guardian.name}... (${signingTime}h, ${manaCost} mana)`, ...state.log.slice(0, 49)], }); }, declinePact: (floor: number) => { const state = get(); const guardian = GUARDIANS[floor]; if (!guardian) return; set({ pendingPactOffer: null, log: [`🚫 Declined pact with ${guardian.name}.`, ...state.log.slice(0, 49)], }); }, getPactMultiplier: () => computePactMultiplier(get()), getPactInsightMultiplier: () => computePactInsightMultiplier(get()), }); // Process pact signing progress (called during tick) export function processPactSigning(state: GameState, deltaHours: number): Partial { if (!state.pactSigningProgress) return {}; const progress = state.pactSigningProgress.progress + deltaHours; const log = [...state.log]; if (progress >= state.pactSigningProgress.required) { const floor = state.pactSigningProgress.floor; const guardian = GUARDIANS[floor]; if (!guardian || state.signedPacts.includes(floor)) { return { pactSigningProgress: null }; } const signedPacts = [...state.signedPacts, floor]; const signedPactDetails = { ...state.signedPactDetails, [floor]: { floor, guardianId: guardian.element, signedAt: { day: state.day, hour: state.hour }, skillLevels: {}, }, }; // Unlock mana types let elements = { ...state.elements }; for (const elemId of guardian.unlocksMana) { if (elements[elemId]) { elements = { ...elements, [elemId]: { ...elements[elemId], unlocked: true }, }; } } // Check for compound element unlocks const unlockedSet = new Set( Object.entries(elements) .filter(([, e]) => e.unlocked) .map(([id]) => id) ); for (const [elemId, elemDef] of Object.entries(ELEMENTS)) { if (elemDef.recipe && !elements[elemId]?.unlocked) { const canUnlock = elemDef.recipe.every(comp => unlockedSet.has(comp)); if (canUnlock) { elements = { ...elements, [elemId]: { ...elements[elemId], unlocked: true }, }; log.unshift(`🔮 ${elemDef.name} mana unlocked through component synergy!`); } } } log.unshift(`📜 Pact with ${guardian.name} signed! ${guardian.unlocksMana.map(e => ELEMENTS[e]?.name || e).join(', ')} mana unlocked!`); return { signedPacts, signedPactDetails, elements, pactSigningProgress: null, log, }; } return { pactSigningProgress: { ...state.pactSigningProgress, progress, }, }; }