// ─── Attunement System ────────────────────────────────────────────────────── // Attunement system functions import type { AttunementState } from './types'; import { calculateEnchantingXP, getAttunementXPForLevel, MAX_ATTUNEMENT_LEVEL } from './data/attunements'; // ─── Enchanter Attunement ────────────────────────────────────────────────── export function initEnchanterAttunement(): AttunementState { return { id: 'enchanter', active: true, level: 1, experience: 0, title: 'Novice Enchanter', }; } export function isEnchanterActive(attunements: Record): boolean { return attunements.enchanter?.active === true; } // ─── XP Gain & Leveling ──────────────────────────────────────────────────── export function gainEnchantingXP( attunements: Record, xpAmount: number ): { attunements: Record; leveledUp: boolean; previousLevel: number; newLevel: number; } { if (!attunements?.enchanter?.active || xpAmount <= 0) { return { attunements, leveledUp: false, previousLevel: attunements.enchanter?.level || 0, newLevel: attunements.enchanter?.level || 0, }; } const previousLevel = attunements.enchanter.level; let newXP = attunements.enchanter.experience + xpAmount; let newLevel = attunements.enchanter.level; let leveledUp = false; while (newLevel < MAX_ATTUNEMENT_LEVEL) { const xpNeeded = getAttunementXPForLevel(newLevel + 1); if (newXP >= xpNeeded) { newXP -= xpNeeded; newLevel++; leveledUp = true; } else { break; } } const updatedAttunements: Record = { ...attunements, enchanter: { ...attunements.enchanter, level: newLevel, experience: newXP, }, }; return { attunements: updatedAttunements, leveledUp, previousLevel, newLevel, }; } export function getXpToNextLevel(currentLevel: number): number { if (currentLevel >= MAX_ATTUNEMENT_LEVEL) return 0; return getAttunementXPForLevel(currentLevel + 1); } export function getLevelProgress(attunements: Record): { currentLevel: number; currentXP: number; xpToNextLevel: number; progressPercent: number; maxLevel: number; } { const enchanter = attunements?.enchanter; if (!enchanter?.active) { return { currentLevel: 0, currentXP: 0, xpToNextLevel: 0, progressPercent: 0, maxLevel: MAX_ATTUNEMENT_LEVEL, }; } const xpToNext = getXpToNextLevel(enchanter.level); return { currentLevel: enchanter.level, currentXP: enchanter.experience, xpToNextLevel: xpToNext, progressPercent: xpToNext > 0 ? (enchanter.experience / xpToNext) * 100 : 100, maxLevel: MAX_ATTUNEMENT_LEVEL, }; } export function calculateEnchantingXpFromDesignCapacity(capacityCost: number): number { return calculateEnchantingXP(capacityCost); } export function calculateXpFromEquipmentInstance( instance: { enchantments: Array<{ effectId: string; stacks: number; actualCost: number }> } ): number { let totalXp = 0; for (const ench of instance.enchantments) { totalXp += calculateEnchantingXP(ench.actualCost); } return totalXp; } export function getEnchanterTitle(level: number): string { if (level >= 10) return 'Grandmaster Enchanter'; if (level >= 8) return 'Master Enchanter'; if (level >= 6) return 'Expert Enchanter'; if (level >= 4) return 'Journeyman Enchanter'; if (level >= 2) return 'Apprentice Enchanter'; return 'Novice Enchanter'; } export function updateEnchanterTitle(attunements: Record): Record { if (!attunements.enchanter?.active) return attunements; const title = getEnchanterTitle(attunements.enchanter.level); return { ...attunements, enchanter: { ...attunements.enchanter, title }, }; } export function resetEnchanterExperience(attunements: Record): Record { if (!attunements.enchanter) return attunements; return { ...attunements, enchanter: { ...attunements.enchanter, experience: 0, level: 1, title: 'Novice Enchanter' }, }; } export function initAttunements(): Record { return { enchanter: initEnchanterAttunement() }; } export function batchGainXP( attunements: Record, xpAmounts: number[] ): { attunements: Record; totalXP: number; totalLevelUps: number; finalLevel: number } { let result = { attunements, totalXP: 0, totalLevelUps: 0, finalLevel: attunements.enchanter?.level || 1, }; for (const xpAmount of xpAmounts) { const gain = gainEnchantingXP(result.attunements, xpAmount); result.attunements = gain.attunements; result.totalXP += xpAmount; if (gain.leveledUp) result.totalLevelUps++; result.finalLevel = gain.newLevel; } return result; }