This refactors weapon/enemy combat systems to support per-weapon cooldowns,
fire modes (auto/semi), and data-driven damage rolls via ammo types. Guards
now use the pistol's stats for ranged attacks and can be stunned by non-lethal
hits. The level editor now includes a directional facing picker for newly placed
enemies and displays enemy orientation as arrows instead of dots.
Key changes:
- Logic: Replaced single weaponCooldownMs with per-weapon cooldowns map; added
prevFireHeld for semi-auto trigger-edge detection; guards now reference real
weapon definitions via rangedWeapon; projectiles carry ammoType and resolve
damage at hit time using rollDamage(); non-lethal ranged hits apply stunMs to
enemies, freezing their AI until it expires.
- Rules: Added ammoTypes array with damageMin/damageMax; weapons now specify
fireMode and ammoType (projectiles) or damage (melee); enemy definitions
include stunMs and reference weapon IDs instead of hardcoded projectile stats.
- Editor: Added FACING_DIRS constants and drawFacingPicker() overlay that lets
users click N/S/E/W neighbor cells to set a just-placed enemy's facing;
enemies now render as directional arrows showing their spawn orientation;
pendingFacingEnemy state tracks the in-progress pick across tool switches,
undo/redo, and level resets.
- View: Added GUARD_FRAME.stunned (frame 9) which takes visual priority over
all other states when e.stunMs > 0, ensuring the flinch pose displays even if
the enemy's internal state still reads 'attack' or 'chase'.
- Data: Expanded level-e1m1 to 19x21 grid with repositioned doors/enemies/exit;
bumped SAVE_VERSION to 2 since player.cooldowns and prevFireHeld are new
required fields absent from v1 saves.
- Tests: Added coverage for semi-auto trigger-edge behavior, stun application
and duration, melee non-stun behavior, damage roll range bounds, and guard
projectile ammo type/cooldown spacing; updated existing tests to use new
cooldowns/ammoType fields and toggle fireHeld for repeated shots.
- Add directional billboarding for guards: front/side/back idle & walk
frames selected by relative angle to camera, with flipX for left side
- Add shooting pose (always shown when guard is in attack state)
- Add 2-frame walk cycle (300ms) for moving guards (chase/alert/patrol)
- Add death sequence: fall (350ms) → ground (2s) → fade (800ms),
view-only state in WolfensteinView, pooled sprite destroyed on completion
- Wire guard sheet texture from artwork JSON (enemies.png, 9×7 grid,
frames 0-8 used)
- Add E key as alternate interact key for opening doors
- Update door hint text to show [SPACE/E]
- Update sprites.md with full animation/facing/death documentation