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,159 @@
|
||||
// ─── Crafting Helper Utilities ─────────────────────────────────────────────────
|
||||
// Instance/ID generation and helper functions extracted from crafting-slice.ts
|
||||
|
||||
import type { EquipmentInstance, EnchantmentDesign, DesignEffect } from './types';
|
||||
import { EQUIPMENT_TYPES, type EquipmentCategory, type EquipmentSlot } from './data/equipment';
|
||||
import { ENCHANTMENT_EFFECTS, calculateEffectCapacityCost } from './data/enchantment-effects';
|
||||
import { CRAFTING_RECIPES, canCraftRecipe, type CraftingRecipe } from './data/crafting-recipes';
|
||||
|
||||
// ─── Instance/ID Generation ──────────────────────────────────────────────────
|
||||
|
||||
export function generateInstanceId(): string {
|
||||
return `equip_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||
}
|
||||
|
||||
export function generateDesignId(): string {
|
||||
return `design_${Date.now()}`;
|
||||
}
|
||||
|
||||
// ─── Equipment Category & Type Helpers ───────────────────────────────────────
|
||||
|
||||
export function getEquipmentCategory(typeId: string): EquipmentCategory | null {
|
||||
const type = EQUIPMENT_TYPES[typeId];
|
||||
return type?.category || null;
|
||||
}
|
||||
|
||||
export function getEquipmentType(typeId: string) {
|
||||
return EQUIPMENT_TYPES[typeId] || null;
|
||||
}
|
||||
|
||||
// ─── Capacity Calculation Helpers ────────────────────────────────────────────
|
||||
|
||||
export function calculateDesignCapacityCost(effects: DesignEffect[], efficiencyBonus: number = 0): number {
|
||||
return effects.reduce((total, eff) => total + calculateEffectCapacityCost(eff.effectId, eff.stacks, efficiencyBonus), 0);
|
||||
}
|
||||
|
||||
export function getAvailableCapacity(instance: EquipmentInstance): number {
|
||||
return instance.totalCapacity - instance.usedCapacity;
|
||||
}
|
||||
|
||||
export function designFitsInEquipment(design: EnchantmentDesign, instance: EquipmentInstance): boolean {
|
||||
return instance.usedCapacity + design.totalCapacityUsed <= instance.totalCapacity;
|
||||
}
|
||||
|
||||
// ─── Time Calculation Helpers ────────────────────────────────────────────────
|
||||
|
||||
export function calculateDesignTime(effects: DesignEffect[]): number {
|
||||
let time = 1;
|
||||
for (const eff of effects) {
|
||||
const effectDef = ENCHANTMENT_EFFECTS[eff.effectId];
|
||||
if (effectDef) {
|
||||
time += 0.5 * eff.stacks;
|
||||
}
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
export function calculatePrepTime(equipmentCapacity: number): number {
|
||||
return 2 + Math.floor(equipmentCapacity / 50);
|
||||
}
|
||||
|
||||
export function calculateApplicationTime(design: EnchantmentDesign): number {
|
||||
return 2 + design.effects.reduce((total, eff) => total + eff.stacks, 0);
|
||||
}
|
||||
|
||||
// ─── Mana Cost Calculation Helpers ───────────────────────────────────────────
|
||||
|
||||
export function calculatePrepManaCost(equipmentCapacity: number): number {
|
||||
return equipmentCapacity * 10;
|
||||
}
|
||||
|
||||
export function calculateApplicationManaPerHour(design: EnchantmentDesign): number {
|
||||
return 20 + design.effects.reduce((total, eff) => total + eff.stacks * 5, 0);
|
||||
}
|
||||
|
||||
export function calculateManaPerHourForPrep(equipmentCapacity: number, prepTime: number): number {
|
||||
return calculatePrepManaCost(equipmentCapacity) / prepTime;
|
||||
}
|
||||
|
||||
// ─── Recipe & Crafting Helpers ───────────────────────────────────────────────
|
||||
|
||||
export function checkRecipeMaterials(
|
||||
recipe: CraftingRecipe,
|
||||
materials: Record<string, number>
|
||||
): { canCraft: boolean; missingMaterials: Record<string, number> } {
|
||||
const missingMaterials: Record<string, number> = {};
|
||||
let canCraft = true;
|
||||
|
||||
for (const [matId, amount] of Object.entries(recipe.materials)) {
|
||||
const have = materials[matId] || 0;
|
||||
if (have < amount) {
|
||||
missingMaterials[matId] = amount - have;
|
||||
canCraft = false;
|
||||
}
|
||||
}
|
||||
|
||||
return { canCraft, missingMaterials };
|
||||
}
|
||||
|
||||
export function deductRecipeMaterials(
|
||||
recipe: CraftingRecipe,
|
||||
materials: Record<string, number>
|
||||
): Record<string, number> {
|
||||
const newMaterials = { ...materials };
|
||||
for (const [matId, amount] of Object.entries(recipe.materials)) {
|
||||
newMaterials[matId] = (newMaterials[matId] || 0) - amount;
|
||||
if (newMaterials[matId] <= 0) {
|
||||
delete newMaterials[matId];
|
||||
}
|
||||
}
|
||||
return newMaterials;
|
||||
}
|
||||
|
||||
export function refundCraftMaterials(recipe: CraftingRecipe, refundRate: number = 0.5): Record<string, number> {
|
||||
const refunds: Record<string, number> = {};
|
||||
for (const [matId, amount] of Object.entries(recipe.materials)) {
|
||||
refunds[matId] = Math.floor(amount * refundRate);
|
||||
}
|
||||
return refunds;
|
||||
}
|
||||
|
||||
// ─── Validation Helpers ──────────────────────────────────────────────────────
|
||||
|
||||
export function canEquipInSlot(
|
||||
instance: EquipmentInstance,
|
||||
slot: EquipmentSlot,
|
||||
currentlyEquipped: Record<EquipmentSlot, string | null>
|
||||
): boolean {
|
||||
const type = EQUIPMENT_TYPES[instance.typeId];
|
||||
if (!type) return false;
|
||||
|
||||
const validSlots = type.category === 'accessory'
|
||||
? ['accessory1', 'accessory2']
|
||||
: [type.slot];
|
||||
|
||||
if (!validSlots.includes(slot)) return false;
|
||||
if (currentlyEquipped[slot] === instance.instanceId) return true;
|
||||
|
||||
const isTwoHanded = type.twoHanded === true;
|
||||
|
||||
if (isTwoHanded) {
|
||||
if (currentlyEquipped.mainHand || currentlyEquipped.offHand) {
|
||||
return false;
|
||||
}
|
||||
if (slot !== 'mainHand') return false;
|
||||
}
|
||||
|
||||
if (slot === 'offHand' && currentlyEquipped.mainHand) {
|
||||
const mainHandType = EQUIPMENT_TYPES[currentlyEquipped.mainHand];
|
||||
if (mainHandType?.twoHanded) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isTwoHanded(typeId: string): boolean {
|
||||
return EQUIPMENT_TYPES[typeId]?.twoHanded === true;
|
||||
}
|
||||
Reference in New Issue
Block a user