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

This commit is contained in:
Refactoring Agent
2026-05-02 10:59:36 +02:00
parent dc38445225
commit c9ae2576f4
14 changed files with 2213 additions and 942 deletions
+235
View File
@@ -0,0 +1,235 @@
// ─── Crafting Application System ────────────────────────────────────────────
// Application system functions extracted from crafting-slice.ts
import type { EquipmentInstance, AppliedEnchantment, EnchantmentDesign, ApplicationProgress } from './types';
import { calculateApplicationTime, calculateApplicationManaPerHour } from './crafting-utils';
import { hasSpecial, SPECIAL_EFFECTS } from './special-effects';
import { computeEffects } from './upgrade-effects';
import type { AttunementState } from './types';
import { calculateEnchantingXP } from './data/attunements';
import { ENCHANTMENT_EFFECTS } from './data/enchantment-effects';
// ─── Application Validation ─────────────────────────────────────────────────
// Check if enchantment application can start
export function canApplyEnchantment(
instance: EquipmentInstance | undefined,
design: EnchantmentDesign | undefined,
currentAction: string
): { canApply: boolean; reason?: string } {
if (!instance) {
return { canApply: false, reason: 'Equipment instance not found' };
}
if (!design) {
return { canApply: false, reason: 'Enchantment design not found' };
}
if (currentAction !== 'meditate') {
return { canApply: false, reason: 'Must be in meditate state' };
}
if (!instance.tags?.includes('Ready for Enchantment')) {
return { canApply: false, reason: 'Equipment must be prepared for enchanting' };
}
if (instance.usedCapacity + design.totalCapacityUsed > instance.totalCapacity) {
return { canApply: false, reason: 'Not enough capacity on equipment' };
}
return { canApply: true };
}
// ─── Application Resource Calculation ────────────────────────────────────────
export interface ApplicationCosts {
time: number;
manaPerHour: number;
manaPerTick: number;
}
export function calculateApplicationCosts(design: EnchantmentDesign): ApplicationCosts {
const time = calculateApplicationTime(design);
const manaPerHour = calculateApplicationManaPerHour(design);
const manaPerTick = manaPerHour * 0.04; // HOURS_PER_TICK
return { time, manaPerHour, manaPerTick };
}
// ─── Application Progress ───────────────────────────────────────────────────
// Initialize application progress
export function initializeApplicationProgress(
equipmentInstanceId: string,
designId: string,
design: EnchantmentDesign
): ApplicationProgress {
const costs = calculateApplicationCosts(design);
return {
equipmentInstanceId,
designId,
progress: 0,
required: costs.time,
manaPerHour: costs.manaPerHour,
paused: false,
manaSpent: 0,
};
}
// Calculate application progress after a tick
export interface ApplicationTickResult {
progress: number;
manaSpent: number;
manaConsumed: number;
isComplete: boolean;
triggeredFreeEnchant: boolean;
}
export function calculateApplicationTick(
currentProgress: number,
required: number,
currentManaSpent: number,
manaPerTick: number,
computedEffects: any
): ApplicationTickResult {
let progress = currentProgress + 0.04;
let manaSpent = currentManaSpent + manaPerTick;
let manaConsumed = manaPerTick;
let triggeredFreeEnchant = false;
let freeEnchantChance = 0;
if (hasSpecial(computedEffects, SPECIAL_EFFECTS.ENCHANT_PRESERVATION)) {
freeEnchantChance += 0.25;
}
if (hasSpecial(computedEffects, SPECIAL_EFFECTS.THRIFTY_ENCHANTER)) {
freeEnchantChance += 0.10;
}
if (hasSpecial(computedEffects, SPECIAL_EFFECTS.OPTIMIZED_ENCHANTING)) {
freeEnchantChance += 0.25;
}
if (freeEnchantChance > 0 && Math.random() < freeEnchantChance) {
progress = required;
manaConsumed = 0;
manaSpent = currentManaSpent;
triggeredFreeEnchant = true;
}
return {
progress,
manaSpent,
manaConsumed,
isComplete: progress >= required,
triggeredFreeEnchant,
};
}
// ─── Enchantment Application ────────────────────────────────────────────────
// Apply enchantments to equipment instance
export function applyEnchantments(
instance: EquipmentInstance,
design: EnchantmentDesign,
computedEffects: any
): {
updatedInstance: EquipmentInstance;
xpGained: number;
logMessage: string;
} {
const isPureEssenceActive = hasSpecial(computedEffects, SPECIAL_EFFECTS.PURE_ESSENCE);
const newEnchantments: AppliedEnchantment[] = design.effects.map(eff => {
let stacks = eff.stacks;
let actualCost = eff.capacityCost;
const effectDef = ENCHANTMENT_EFFECTS[eff.effectId];
if (isPureEssenceActive && effectDef && effectDef.baseCapacityCost < 100) {
stacks = Math.ceil(stacks * 1.25);
}
return {
effectId: eff.effectId,
stacks,
actualCost,
};
});
const xpGained = calculateEnchantingXP(design.totalCapacityUsed);
const updatedInstance: EquipmentInstance = {
...instance,
enchantments: [...instance.enchantments, ...newEnchantments],
usedCapacity: instance.usedCapacity + design.totalCapacityUsed,
};
return {
updatedInstance,
xpGained,
logMessage: `✨ Enchantment "${design.name}" applied to ${instance.name}! (+${xpGained} Enchanter XP)`,
};
}
// ─── Attunement XP Updates ──────────────────────────────────────────────────
export function updateEnchanterAttunement(
attunements: Record<string, AttunementState>,
xpGained: number
): Record<string, AttunementState> {
if (!attunements?.enchanter?.active || xpGained <= 0) {
return attunements;
}
const enchanterState = attunements.enchanter;
let newXP = enchanterState.experience + xpGained;
let newLevel = enchanterState.level;
const { getAttunementXPForLevel, MAX_ATTUNEMENT_LEVEL } = require('./data/attunements');
while (newLevel < MAX_ATTUNEMENT_LEVEL) {
const xpNeeded = getAttunementXPForLevel(newLevel + 1);
if (newXP >= xpNeeded) {
newXP -= xpNeeded;
newLevel++;
} else {
break;
}
}
return {
...attunements,
enchanter: {
...enchanterState,
level: newLevel,
experience: newXP,
},
};
}
// ─── Application Cancellation ────────────────────────────────────────────────
export function cancelApplication() {
return { logMessage: 'Enchantment application cancelled.' };
}
export function pauseApplication() {
return { logMessage: 'Enchantment application paused.' };
}
export function resumeApplication() {
return { logMessage: 'Enchantment application resumed.' };
}
// ─── Progress Calculations ──────────────────────────────────────────────────
export function getApplicationManaCostForTick(manaPerHour: number): number {
return manaPerHour * 0.04;
}
export function getApplicationRemainingTime(currentProgress: number, required: number): number {
return Math.max(0, required - currentProgress);
}
export function getApplicationCompletionPercent(currentProgress: number, required: number): number {
return Math.min(100, Math.floor((currentProgress / required) * 100));
}