diff --git a/docs/project-structure.txt b/docs/project-structure.txt index 4effc46..cec187f 100644 --- a/docs/project-structure.txt +++ b/docs/project-structure.txt @@ -190,22 +190,19 @@ Mana-Loop/ │ │ │ ├── store-method-tests/ │ │ │ ├── achievements.test.ts │ │ │ ├── bug-fixes.test.ts -│ │ │ ├── combat-store.test.ts │ │ │ ├── combat-utils.test.ts │ │ │ ├── computed-stats.test.ts │ │ │ ├── discipline-math.test.ts -│ │ │ ├── discipline-store.test.ts │ │ │ ├── enemy-generator.test.ts │ │ │ ├── floor-utils.test.ts │ │ │ ├── formatting.test.ts -│ │ │ ├── mana-store.test.ts │ │ │ ├── mana-utils.test.ts -│ │ │ ├── prestige-store.test.ts │ │ │ ├── regression-fixes.test.ts │ │ │ ├── spire-utils.test.ts -│ │ │ ├── test-setup.ts -│ │ │ ├── tick-debug.test.ts -│ │ │ ├── tick-integration-pact.test.ts +│ │ │ ├── store-actions-combat-prestige.test.ts +│ │ │ ├── store-actions-discipline.test.ts +│ │ │ ├── store-actions-mana.test.ts +│ │ │ ├── store-actions.test.ts │ │ │ └── tick-integration.test.ts │ │ ├── constants/ │ │ │ ├── spells-modules/ diff --git a/src/components/game/crafting/EnchantmentDesigner/utils.ts b/src/components/game/crafting/EnchantmentDesigner/utils.ts index 9699733..3a0573c 100644 --- a/src/components/game/crafting/EnchantmentDesigner/utils.ts +++ b/src/components/game/crafting/EnchantmentDesigner/utils.ts @@ -1,6 +1,7 @@ import { EQUIPMENT_TYPES } from '@/lib/game/data/equipment'; import { ENCHANTMENT_EFFECTS, calculateEffectCapacityCost } from '@/lib/game/data/enchantment-effects'; import type { DesignEffect, EquipmentInstance, EquipmentCategory } from '@/lib/game/types'; +import { calculateDesignCapacityCost as calcCapacityCost, calculateDesignTime as calcDesignTime } from '@/lib/game/crafting-design'; /** * Get available effects for selected equipment type (only unlocked ones) @@ -85,15 +86,13 @@ export function getIncompatibilityReason( /** * Calculate total capacity cost for current design + * Delegates to canonical calculateDesignCapacityCost from crafting-design */ export function calculateDesignCapacityCost( selectedEffects: DesignEffect[], efficiencyBonus: number ): number { - return selectedEffects.reduce( - (total, eff) => total + calculateEffectCapacityCost(eff.effectId, eff.stacks, efficiencyBonus), - 0 - ); + return calcCapacityCost(selectedEffects, efficiencyBonus); } /** @@ -105,9 +104,10 @@ export function getEquipmentCapacity(selectedEquipmentType: string | null): numb /** * Calculate design time + * Delegates to canonical calculateDesignTime from crafting-design */ export function calculateDesignTime(selectedEffects: DesignEffect[]): number { - return selectedEffects.reduce((total, eff) => total + 0.5 * eff.stacks, 1); + return calcDesignTime(selectedEffects); } /** diff --git a/src/lib/game/crafting-utils.ts b/src/lib/game/crafting-utils.ts index a1b76c9..4815673 100644 --- a/src/lib/game/crafting-utils.ts +++ b/src/lib/game/crafting-utils.ts @@ -1,9 +1,8 @@ // ─── Crafting Helper Utilities ───────────────────────────────────────────────── // Instance/ID generation and helper functions -import type { EquipmentInstance, EnchantmentDesign, DesignEffect } from './types'; +import type { EquipmentInstance, EnchantmentDesign } 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 ────────────────────────────────────────────────── @@ -29,10 +28,6 @@ export function getEquipmentType(typeId: string) { // ─── 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; } @@ -43,17 +38,6 @@ export function designFitsInEquipment(design: EnchantmentDesign, instance: Equip // ─── 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); } diff --git a/src/lib/game/utils/enemy-utils.ts b/src/lib/game/utils/enemy-utils.ts index 3cc0a98..ea5e459 100644 --- a/src/lib/game/utils/enemy-utils.ts +++ b/src/lib/game/utils/enemy-utils.ts @@ -1,10 +1,24 @@ -// ─── Enemy Naming System ─────────────────────────────────────────────── +// ─── Enemy Naming & Swarm Generation ────────────────────────────────── // Moved from store-modules/enemy-utils.ts to eliminate legacy dependencies import type { EnemyState } from '../types'; import { SWARM_CONFIG } from '../constants'; import { getFloorMaxHP, getFloorElement } from './floor-utils'; +// Barrier elements more likely to have barrier +const BARRIER_ELEMENTS = ['light', 'water', 'earth']; + +// Get barrier for an enemy (0-1 as percentage of max HP) +function getEnemyBarrier(floor: number, element: string): number { + if (floor < 20) return 0; + const baseChance = BARRIER_ELEMENTS.includes(element) ? 0.15 : 0.08; + const floorBonus = Math.min(0.25, (floor - 20) * 0.003); + const barrierChance = Math.min(0.4, baseChance + floorBonus); + if (Math.random() > barrierChance) return 0; + const floorProgress = Math.min(1, (floor - 20) / 80); + return 0.1 + floorProgress * 0.2; +} + // Enemy names by element and floor tier const ENEMY_NAMES_BY_ELEMENT: Record = { fire: ['Fire Imp', 'Flame Sprite', 'Emberling', 'Scorchling', 'Inferno Whelp'], @@ -49,8 +63,7 @@ export function generateSwarmEnemies(floor: number): EnemyState[] { maxHP: Math.floor(baseHP * SWARM_CONFIG.hpMultiplier), armor: SWARM_CONFIG.armorBase + Math.floor(floor / 10) * SWARM_CONFIG.armorPerFloor, dodgeChance: 0, - healthRegen: 0, // Will be set by caller if needed - barrier: 0, // Will be set by caller if needed + barrier: getEnemyBarrier(floor, element), element, }); } diff --git a/src/lib/game/utils/room-utils.ts b/src/lib/game/utils/room-utils.ts index 5609510..9038d1e 100644 --- a/src/lib/game/utils/room-utils.ts +++ b/src/lib/game/utils/room-utils.ts @@ -5,7 +5,7 @@ import type { RoomType, FloorState, EnemyState } from '../types'; import { GUARDIANS, FLOOR_ELEM_CYCLE, PUZZLE_ROOMS, PUZZLE_ROOM_INTERVAL, PUZZLE_ROOM_CHANCE, SWARM_ROOM_CHANCE, SPEED_ROOM_CHANCE, FLOOR_ARMOR_CONFIG, SWARM_CONFIG, SPEED_ROOM_CONFIG } from '../constants'; import { getFloorMaxHP } from './floor-utils'; import { getFloorElement } from './floor-utils'; -import { getEnemyName } from './enemy-utils'; +import { getEnemyName, generateSwarmEnemies } from './enemy-utils'; // Generate room type for a floor export function generateRoomType(floor: number): RoomType { @@ -79,30 +79,6 @@ export function getEnemyBarrier(floor: number, element: string): number { return 0.1 + floorProgress * 0.2; } -// Generate enemies for a swarm room -export function generateSwarmEnemies(floor: number): EnemyState[] { - const baseHP = getFloorMaxHP(floor); - const element = getFloorElement(floor); - const numEnemies = SWARM_CONFIG.minEnemies + - Math.floor(Math.random() * (SWARM_CONFIG.maxEnemies - SWARM_CONFIG.minEnemies + 1)); - - const enemies: EnemyState[] = []; - for (let i = 0; i < numEnemies; i++) { - const enemyName = getEnemyName(element, floor); - enemies.push({ - id: `enemy_${i}`, - name: enemyName, - hp: Math.floor(baseHP * SWARM_CONFIG.hpMultiplier), - maxHP: Math.floor(baseHP * SWARM_CONFIG.hpMultiplier), - armor: SWARM_CONFIG.armorBase + Math.floor(floor / 10) * SWARM_CONFIG.armorPerFloor, - dodgeChance: 0, - barrier: getEnemyBarrier(floor, element), - element, - }); - } - return enemies; -} - // Generate initial floor state export function generateFloorState(floor: number): FloorState { const roomType = generateRoomType(floor);