d2d28887b1
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m9s
- Refactored page.tsx (613→252 lines) with GameOverScreen and LeftPanel extracted - Refactored StatsTab.tsx (584→92 lines) with section components - Refactored SkillsTab.tsx (434→54 lines) with sub-components - Created modular structure for GameContext, LootInventory, and other components - All extracted components organized into feature directories
224 lines
7.2 KiB
TypeScript
224 lines
7.2 KiB
TypeScript
// ─── 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> = {}): 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<string, { current: number; max: number; unlocked: boolean }> = {};
|
|
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<string, { learned: boolean; level: number; studyProgress: number }> = {};
|
|
|
|
// 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<string, AttunementState> = {
|
|
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<string, { current: number; max: number; unlocked: boolean }>,
|
|
|
|
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,
|
|
};
|
|
}
|