- Add new `wallArt` level data array with per-cell decal frames
- Integrate wall art rendering into WolfensteinView using same texture sampling as walls
- Add Wall Art tool to WolfensteinEditor with dynamic dropdown from JSON registry
- Create wolfenstein-wallart.json frame registry for easy decal management
- Add validation ensuring wall art sits on actual wall cells
- Support wall art in save/load system with backward compatibility
- Alert idle enemies when shot, even outside vision cone
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.
- Implement 90° field-of-view check for idle/patrolling guards (only alerts when player is within cone, in range, and has clear line of sight)
- Change patrol behavior: 0-1 waypoints ping-pong, 2+ waypoints form a one-way loop (home → nodes → home → ...)
- Reduce patrol speed to 50% of chase speed for natural movement
- Update editor to display loop closing line when 2+ patrol nodes exist
- Add new weapon sprite images (gattling, machinegun, plasma, rocket, shotgun)
- Extend map parser to support patrol route definitions via `opts.patrols`
- Add patrol routes to e1m1 (guard at 2.5,18.5) and e1m2 (guard at 9.5,8.5)
- Add comprehensive tests for vision cone (inside/outside edge cases) and patrol loop/ping-pong behavior
Editor (WolfensteinEditor.js):
- Decouple the board from grid size: fixed 900px viewport with independent
pan (right-drag / WASD / arrows) and zoom (wheel / +/- / F to fit)
instead of squeezing the whole grid in; add a whole-level map overview
minimap with click-to-jump.
- Grids up to 1000 cells/side (was 48); painting past the edge auto-grows
the grid (preserving content, re-sealing borders) instead of being refused.
- Rebuild the toolbar as a categorized DOM radio + dropdown panel (Wall /
Door / Pickup / Enemy / Patrol / Zone / Erase) instead of a flat list.
- Add a Patrol tool: select a guard, then click tiles to add/remove
waypoints; routes are drawn (dim for all, highlighted for the selection).
- Throttle the reachability validate during paint-drag; flush it before
Test Play / Export; queue game assets in preload() like ZumaEditor.
Doors (WolfensteinLogic.js, WolfensteinRaycaster.js, WolfensteinView.js):
- Player now opens doors by pressing Space (HUD "[SPACE] Open" prompt when
one is in range); enemies still shove them open. Doors animate open/closed
via a slide value (400ms) instead of popping, and stay solid for
gameplay until fully open.
- Render doors as recessed mid-cell geometry (real depth, producing the "H"
doorway shape) via a door-aware render-only raycast — collision/LOS are
unchanged; the door visibly slides sideways into a dark socket as it opens.
Enemy AI (WolfensteinLogic.js):
- Idle enemies with an authored patrol route ping-pong along
[home, ...nodes] until they spot the player; validate patrol nodes.
Rendering (WolfensteinView.js, assets, data):
- Add textured wall rendering: per-column 1px source-texel sampling from
the new walls.png spritesheet, darkened with a 'multiply' grey to match
the existing side/fog shading, with per-wall-type flat-color fallback.
- Wire in assets/images/wolfenstein/walls.png and point the art manifest at it.
Misc:
- level-e1m1.json: reworked to a taller (20-row) map exercising the new
wall/door types; playerRadius 0.25 -> 0.35.
- sprites.md: document exact wall-sheet size, the sliding/recessed door
behavior, guard sheet usage, and standalone image sizes/proportions.