feat: implement per-enemy damage application (spec §3.2)
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m6s

- Add applyDamageToRoom() function targeting individual enemies
- Add lowestHPEnemy() helper for focus-fire targeting
- AoE spells distribute damage across all enemies
- Single-target attacks hit lowest HP enemy first
- Refactor processCombatTick spell/equipment/melee/DoT damage to use per-enemy system
- Update golemApplyDamageToRoom in golem-combat pipeline for per-enemy targeting
- Add currentRoom to CombatTickResult and sync through gameStore
- Update combat-actions tests with proper enemy setup for per-enemy tests
- Extract combat-damage.ts module to stay under 400-line limit
This commit is contained in:
2026-06-04 11:37:21 +02:00
parent 8dde423526
commit 23e629f37e
10 changed files with 182 additions and 85 deletions
@@ -24,7 +24,7 @@ function resetStores() {
currentAction: 'climb',
castProgress: 0,
spireMode: false,
currentRoom: { roomType: 'combat', enemies: [] },
currentRoom: { roomType: 'combat', enemies: [{ id: 'enemy', name: 'Test Enemy', hp: getFloorMaxHP(1), maxHP: getFloorMaxHP(1), armor: 0, dodgeChance: 0, barrier: 0, element: 'fire', activeEffects: [], effectiveArmor: 0 }] },
clearedFloors: {},
climbDirection: 'up',
isDescending: false,
@@ -143,7 +143,7 @@ describe('processCombatTick', () => {
it('should advance room when HP reaches 0 (not last room)', () => {
// Set floor HP very low so it's cleared in one cast
// currentRoomIndex=0, roomsPerFloor=5 → clears room 0, advances to room 1
useCombatStore.setState({ floorHP: 1, castProgress: 0.99, climbDirection: 'up', currentRoomIndex: 0, roomsPerFloor: 5 });
useCombatStore.setState({ castProgress: 0.99, climbDirection: 'up', currentRoomIndex: 0, roomsPerFloor: 5, currentRoom: { roomType: 'combat', enemies: [{ id: 'enemy', name: 'Test Enemy', hp: 1, maxHP: 100, armor: 0, dodgeChance: 0, barrier: 0, element: 'fire', activeEffects: [], effectiveArmor: 0 }] } });
const elements = makeInitialElements(500, {});
const result = runCombatTick(1000, elements);
// Room advanced, floor stays the same
@@ -154,7 +154,7 @@ describe('processCombatTick', () => {
it('should advance floor when last room on floor is cleared', () => {
// Set currentRoomIndex to last room so clearing it advances the floor
useCombatStore.setState({ floorHP: 1, castProgress: 0.99, climbDirection: 'up', currentRoomIndex: 4, roomsPerFloor: 5 });
useCombatStore.setState({ castProgress: 0.99, climbDirection: 'up', currentRoomIndex: 4, roomsPerFloor: 5, currentRoom: { roomType: 'combat', enemies: [{ id: 'enemy', name: 'Test Enemy', hp: 1, maxHP: 100, armor: 0, dodgeChance: 0, barrier: 0, element: 'fire', activeEffects: [], effectiveArmor: 0 }] } });
const elements = makeInitialElements(500, {});
const result = runCombatTick(1000, elements);
expect(result.currentFloor).toBe(2);