fix: SLOT_NAMES export and refactor: split crafting-slice.ts into modules
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m51s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m51s
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
// ─── Attunement System ──────────────────────────────────────────────────────
|
||||
// Attunement system functions extracted from crafting-slice.ts
|
||||
|
||||
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<string, AttunementState>): boolean {
|
||||
return attunements.enchanter?.active === true;
|
||||
}
|
||||
|
||||
// ─── XP Gain & Leveling ────────────────────────────────────────────────────
|
||||
|
||||
export function gainEnchantingXP(
|
||||
attunements: Record<string, AttunementState>,
|
||||
xpAmount: number
|
||||
): {
|
||||
attunements: Record<string, AttunementState>;
|
||||
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<string, AttunementState> = {
|
||||
...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<string, AttunementState>): {
|
||||
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<string, AttunementState>): Record<string, AttunementState> {
|
||||
if (!attunements.enchanter?.active) return attunements;
|
||||
const title = getEnchanterTitle(attunements.enchanter.level);
|
||||
return {
|
||||
...attunements,
|
||||
enchanter: { ...attunements.enchanter, title },
|
||||
};
|
||||
}
|
||||
|
||||
export function resetEnchanterExperience(attunements: Record<string, AttunementState>): Record<string, AttunementState> {
|
||||
if (!attunements.enchanter) return attunements;
|
||||
return {
|
||||
...attunements,
|
||||
enchanter: { ...attunements.enchanter, experience: 0, level: 1, title: 'Novice Enchanter' },
|
||||
};
|
||||
}
|
||||
|
||||
export function initAttunements(): Record<string, AttunementState> {
|
||||
return { enchanter: initEnchanterAttunement() };
|
||||
}
|
||||
|
||||
export function batchGainXP(
|
||||
attunements: Record<string, AttunementState>,
|
||||
xpAmounts: number[]
|
||||
): { attunements: Record<string, AttunementState>; 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;
|
||||
}
|
||||
Reference in New Issue
Block a user