// ─── Initial State Factory ──────────────────────────────────────────────────── // Extracted from store.ts (lines 690-904) import type { GameState, AttunementState, EnemyState } from '../types'; import { ELEMENTS, GUARDIANS, BASE_UNLOCKED_ELEMENTS, SPELLS_DEF, BASE_UNLOCKED_EFFECTS, PUZZLE_ROOMS } from '../constants'; import { computeElementMax } from './computed-stats'; import { computeEffects as computeUpgradeEffects } from '../upgrade-effects'; import { createStartingEquipment, getSpellsFromEquipment } from '../crafting-slice'; import { getFloorMaxHP, getFloorElement } from '../utils/floor-utils'; import { generateFloorState } from './room-utils'; export function makeInitial(overrides: Partial = {}): GameState { const pu = overrides.prestigeUpgrades || {}; const startFloor = 1 + (pu.spireKey || 0) * 2; const effects = overrides.skillUpgrades ? computeUpgradeEffects(overrides.skillUpgrades || {}, overrides.skillTiers || {}) : undefined; const manaHeartBonus = overrides.manaHeartBonus || 0; const unlockedManaTypeUpgrades = overrides.unlockedManaTypeUpgrades || []; const elements: Record = {}; Object.keys(ELEMENTS).forEach((k) => { const isUnlocked = BASE_UNLOCKED_ELEMENTS.includes(k); let startAmount = 0; // Start with some elemental mana if elemStart upgrade if (isUnlocked && pu.elemStart) { startAmount = pu.elemStart * 5; } // Calculate per-element max capacity including unlockedManaTypeCapacity upgrades const baseElemMax = computeElementMax({ skills: overrides.skills || {}, prestigeUpgrades: pu, skillUpgrades: overrides.skillUpgrades || {}, skillTiers: overrides.skillTiers || {}, unlockedManaTypeUpgrades }, effects, k); elements[k] = { current: overrides.elements?.[k]?.current ?? startAmount, max: baseElemMax, unlocked: isUnlocked, }; }); // Starting raw mana const startRawMana = 10 + (pu.manaWell || 0) * 500 + (pu.quickStart || 0) * 100; // Create starting equipment (staff with mana bolt, clothes) const startingEquipment = createStartingEquipment(); // Get spells from starting equipment const equipmentSpells = getSpellsFromEquipment( startingEquipment.equipmentInstances, Object.values(startingEquipment.equippedInstances) ); // Starting spells - now come from equipment instead of being learned directly const startSpells: Record = {}; // Add spells from equipment for (const spellId of equipmentSpells) { startSpells[spellId] = { learned: true, level: 1, studyProgress: 0 }; } // Add random starting spells from spell memory upgrade (pact spells) if (pu.spellMemory) { const availableSpells = Object.keys(SPELLS_DEF).filter(s => !startSpells[s]); const shuffled = availableSpells.sort(() => Math.random() - 0.5); for (let i = 0; i < Math.min(pu.spellMemory, shuffled.length); i++) { startSpells[shuffled[i]] = { learned: true, level: 1, studyProgress: 0 }; } } // Starting attunements - player begins with Enchanter const startingAttunements: Record = { enchanter: { id: 'enchanter', active: true, level: 1, experience: 0 }, }; // Add any attunements from previous loops (for persistence) if (overrides.attunements) { Object.entries(overrides.attunements).forEach(([id, state]) => { if (id !== 'enchanter') { startingAttunements[id] = state; } }); } // Unlock transference element for Enchanter attunement if (elements['transference']) { elements['transference'] = { ...elements['transference'], unlocked: true }; } return { day: 1, hour: 0, loopCount: overrides.loopCount || 0, gameOver: false, victory: false, paused: false, rawMana: startRawMana, meditateTicks: 0, totalManaGathered: overrides.totalManaGathered || 0, // Attunements (class-like system) attunements: startingAttunements, elements: elements as Record, currentFloor: startFloor, floorHP: getFloorMaxHP(startFloor), floorMaxHP: getFloorMaxHP(startFloor), maxFloorReached: startFloor, signedPacts: [], activeSpell: 'manaBolt', currentAction: 'meditate', castProgress: 0, // Initialize room state currentRoom: generateFloorState(startFloor), spells: startSpells, skills: overrides.skills || {}, skillProgress: {}, skillUpgrades: overrides.skillUpgrades || {}, skillTiers: overrides.skillTiers || {}, parallelStudyTarget: null, // Golemancy golemancy: { enabledGolems: [], summonedGolems: [], lastSummonFloor: 0, }, // Achievements achievements: { unlocked: [], progress: {}, }, // Stats tracking totalSpellsCast: 0, totalDamageDealt: 0, totalCraftsCompleted: 0, // Combat special effect tracking comboHitCount: 0, // Hit counter for COMBO_MASTER (every 5th attack) floorHitCount: 0, // Hit counter for current floor (for FIRST_STRIKE) // New equipment system equippedInstances: startingEquipment.equippedInstances, equipmentInstances: startingEquipment.equipmentInstances, enchantmentDesigns: [], designProgress: null, designProgress2: null, preparationProgress: null, applicationProgress: null, equipmentCraftingProgress: null, unlockedEffects: [...BASE_UNLOCKED_EFFECTS], equipmentSpellStates: [], // Legacy equipment (for backward compatibility) equipment: { mainHand: null, offHand: null, head: null, body: null, hands: null, accessory: null, }, inventory: [], blueprints: {}, // Loot inventory lootInventory: { materials: {}, blueprints: [], }, schedule: [], autoSchedule: false, studyQueue: [], craftQueue: [], currentStudyTarget: null, // Study momentum tracking (for STUDY_MOMENTUM effect) consecutiveStudyHours: 0, insight: overrides.insight || 0, totalInsight: overrides.totalInsight || 0, prestigeUpgrades: pu, memorySlots: 3 + (pu.deepMemory || 0), memories: overrides.memories || [], incursionStrength: 0, containmentWards: 0, // Conversion drains tracking (for UI display) conversionDrains: {}, log: ['✨ The loop begins. You start with a Basic Staff (Mana Bolt) and civilian clothes. Gather your strength, mage.'], loopInsight: 0, flowSurgeEndTime: 0, // Hour timestamp for FLOW_SURGE effect (0 = inactive) // Mana Well Effects (Phase 4) manaHeartBonus: manaHeartBonus, // Cumulative +10% max mana per loop from MANA_HEART // Spire Mode - simplified UI for climbing spireMode: false, clearedFloors: {}, climbDirection: null, isDescending: false, // Activity Log (for Spire Mode UI) activityLog: [], // Track selected mana types for unlockedManaTypeCapacity upgrade unlockedManaTypeUpgrades: unlockedManaTypeUpgrades, }; }