[High] [Bug] Enemy defenses (armor/barrier/dodge) partially bypassed for melee attacks #285

Closed
opened 2026-06-05 13:53:01 +02:00 by Anexim · 2 comments
Owner

Type: Bug / Incomplete feature
Priority: High

Investigation findings:

The applyEnemyDefenses function in combat-tick.ts is fully implemented with the correct dodge → barrier → armor pipeline per spec §5.2. However, there is a critical gap:

  • Spell damage: Goes through applyEnemyDefenses correctly
  • DoT effects: Goes through applyEnemyDefenses correctly
  • Melee sword attacks: Bypasses all enemy defenses — called with enemy: null, which causes the defense function to short-circuit and return damage unchanged
  • Golem attacks: Unknown — delegated to processGolemAttacks, needs separate investigation

Root cause: In combat-actions.ts, the melee attack loop calls onDamageDealt(damage) which eventually calls applyEnemyDefenses(dmg, null, ...) — passing null as the enemy. The applyEnemyDefenses function checks if (!enemy) return dmg at the top, skipping all defense calculations.

Fix needed: Pass the actual target enemy to applyEnemyDefenses for melee attacks, just like spells do.

Files:

  • src/lib/game/stores/combat-actions.ts — melee attack loop
  • src/lib/game/stores/pipelines/combat-tick.tsapplyEnemyDefenses function
**Type:** Bug / Incomplete feature **Priority:** High **Investigation findings:** The `applyEnemyDefenses` function in `combat-tick.ts` is fully implemented with the correct dodge → barrier → armor pipeline per spec §5.2. However, there is a critical gap: - **Spell damage**: ✅ Goes through `applyEnemyDefenses` correctly - **DoT effects**: ✅ Goes through `applyEnemyDefenses` correctly - **Melee sword attacks**: ❌ **Bypasses all enemy defenses** — called with `enemy: null`, which causes the defense function to short-circuit and return damage unchanged - **Golem attacks**: Unknown — delegated to `processGolemAttacks`, needs separate investigation **Root cause:** In `combat-actions.ts`, the melee attack loop calls `onDamageDealt(damage)` which eventually calls `applyEnemyDefenses(dmg, null, ...)` — passing `null` as the enemy. The `applyEnemyDefenses` function checks `if (!enemy) return dmg` at the top, skipping all defense calculations. **Fix needed:** Pass the actual target enemy to `applyEnemyDefenses` for melee attacks, just like spells do. **Files:** - `src/lib/game/stores/combat-actions.ts` — melee attack loop - `src/lib/game/stores/pipelines/combat-tick.ts` — `applyEnemyDefenses` function
Anexim added the ai:todo label 2026-06-05 13:53:01 +02:00
n8n-gitea was assigned by Anexim 2026-06-05 13:53:01 +02:00
Anexim added ai:in-progress and removed ai:todo labels 2026-06-06 17:21:25 +02:00
Author
Owner

Starting work on the melee defense bypass bug. Root cause is clear: in combat-actions.ts, the melee attack loop passes null as the enemy to applyEnemyDefenses, causing it to short-circuit. Will investigate the exact code path and fix it.

Starting work on the melee defense bypass bug. Root cause is clear: in combat-actions.ts, the melee attack loop passes `null` as the enemy to `applyEnemyDefenses`, causing it to short-circuit. Will investigate the exact code path and fix it.
Anexim added ai:done and removed ai:in-progress labels 2026-06-06 17:35:10 +02:00
Author
Owner

Fix Complete: Melee attacks now apply enemy defenses

Root Cause

In combat-actions.ts, the melee sword attack loop called applyEnemyDefenses(meleeDamage, null, 'combat', ...) — passing null as the enemy. The applyEnemyDefenses function in combat-tick.ts checks if (!enemy) return dmg; at the top, so all enemy defenses (armor, barrier, dodge) were completely bypassed for melee attacks.

Spell damage and DoT effects correctly went through defenses via the onDamageDealt callback which used the proper defCtx.enemy.

Fix Applied

File: src/lib/game/stores/combat-actions.ts (melee loop, ~line 267)

Changed the melee loop to:

  1. Read get().currentRoom to get the current room state
  2. Filter living enemies and find the lowest HP one (matching focus-fire targeting in applyDamageToRoom)
  3. Pass the actual target enemy and room type to applyEnemyDefenses instead of null

Regression Tests Added

File: src/lib/game/__tests__/melee-defense-bypass.test.ts (390 lines, 7 tests)

Tests verify:

  • Melee damage is reduced by armor
  • Melee damage is reduced by barrier
  • Unarmored enemies take more damage than armored ones
  • Full damage dealt when no defenses
  • Focus-fire targeting (lowest HP enemy)
  • Graceful handling of empty enemy list
  • Comparison proving defense application works

Verification

  • All 948 tests pass (49 test files)
  • All files under 400 lines (combat-actions.ts: 385, test file: 390)
  • Pre-commit hooks pass (file size, tests, circular deps, project structure)
  • Committed and pushed (commit 325949c)
## Fix Complete: Melee attacks now apply enemy defenses ### Root Cause In `combat-actions.ts`, the melee sword attack loop called `applyEnemyDefenses(meleeDamage, null, 'combat', ...)` — passing `null` as the enemy. The `applyEnemyDefenses` function in `combat-tick.ts` checks `if (!enemy) return dmg;` at the top, so all enemy defenses (armor, barrier, dodge) were completely bypassed for melee attacks. Spell damage and DoT effects correctly went through defenses via the `onDamageDealt` callback which used the proper `defCtx.enemy`. ### Fix Applied **File:** `src/lib/game/stores/combat-actions.ts` (melee loop, ~line 267) Changed the melee loop to: 1. Read `get().currentRoom` to get the current room state 2. Filter living enemies and find the lowest HP one (matching focus-fire targeting in `applyDamageToRoom`) 3. Pass the actual target enemy and room type to `applyEnemyDefenses` instead of `null` ### Regression Tests Added **File:** `src/lib/game/__tests__/melee-defense-bypass.test.ts` (390 lines, 7 tests) Tests verify: - Melee damage is reduced by armor - Melee damage is reduced by barrier - Unarmored enemies take more damage than armored ones - Full damage dealt when no defenses - Focus-fire targeting (lowest HP enemy) - Graceful handling of empty enemy list - Comparison proving defense application works ### Verification - ✅ All 948 tests pass (49 test files) - ✅ All files under 400 lines (combat-actions.ts: 385, test file: 390) - ✅ Pre-commit hooks pass (file size, tests, circular deps, project structure) - ✅ Committed and pushed (commit 325949c)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Anexim/Mana-Loop#285