Commit Graph

626 Commits

Author SHA1 Message Date
Brian Fertig 97adfa642d Fix win-screen counter guard and add Playwright browser smoke test
- piecesBig counter guard used .parent (always undefined on container
  children in this Phaser build — they get .parentContainer), so the
  'PIECES' count-up never rendered; drop the dead guard.
- buttonHit() had the same .parent assumption; use .parentContainer.
- Add tools/smokeJigsaw.mjs: headless-Chromium smoke test driving
  menu -> play -> win showcase (camera settle, counter, confetti,
  frame/shine) -> Play Again -> Menu -> play again, asserting zero JS
  errors. Verified pass in browser.
2026-08-31 08:26:32 -06:00
Brian Fertig 18d89d4553 Redesign jigsaw win screen with zoomed board view and celebration effect
- Frame the completed puzzle large on the right while parking stats/actions in a left-hand panel, easing the camera into place
- Add staggered slide-in choreography for title, time, stats (with piece counter), and action buttons
- Fire confetti burst + falling curtain, a shine sweep, and a pulsing gold frame when the win camera lands
- Introduce exitWin() so restart/menu pull the camera back and slide the panel out before rebuilding state
- Simplify pinHUD() now that HUD/win overlay render through the fixed hudCam
2026-08-31 08:11:27 -06:00
Brian Fertig 243d2e143c Rework jigsaw UI with stitched mat playfield and two-column menu
- Replace the flat felt background with a canvas-generated beige fabric mat (border band, dashed stitching, subtle weave tile, vignette) plus a deeper "pocket" panel behind the board so pieces read as resting on a puzzle mat.
- Add soft drop shadows to jigsaw pieces via an extra shadow pass before the art fill, and pad the piece canvas so the shadow isn't clipped.
- Rebuild the menu into two columns (image picker left, difficulty + start right) with tighter vertical rhythm; make the thumbnail box size a `thumbBox` property so preview/border scale together.
- Consolidate panel background+frame pairs (menu, dropdown, win layer) into single graphics objects to simplify tweening and reduce node count.
- Use a separate invisible zone for table pointerdown so the mat image can be swapped without dropping input, and guard `onTableDown` against double-firing while a piece grab is in progress.
2026-08-30 23:11:58 -06:00
brianfertig c29f33e2a3 Merge pull request 'Puzzle' (#5) from Puzzle into main
Reviewed-on: #5
2026-08-31 03:25:35 +00:00
Brian Fertig a7ebb67413 Extend jigsaw initial-image test coverage
Test now also asserts the menu is back to its original shape (no random-start button), the initial preview and thumb name match the random pick, Start Puzzle begins exactly that image, and the original 🎲 Random button still randomises the menu preview.
2026-08-30 21:19:11 -06:00
Brian Fertig 25f5e05a96 Start the jigsaw puzzle picker on a random image
The menu always opened on the first artwork; now imageIndex is randomised right after loadArtwork(), so each visit to the picker shows a different initial puzzle. The existing Random/prev/next buttons are unchanged (previous random-start button reverted in 4f2d299). Test page + CDP driver verify 8 fresh page loads all land on a valid in-range image with its preview loaded, with variety across loads.
2026-08-30 21:14:37 -06:00
Brian Fertig 4f2d29942d Revert "Add one-click random start to the jigsaw menu"
This reverts commit 0740c12ffa.
2026-08-30 21:12:44 -06:00
Brian Fertig 0740c12ffa Add one-click random start to the jigsaw menu
New '🎲 Start Random' button picks a random picture (never the current one when there's a choice) and starts the puzzle immediately, keeping the selected difficulty. Menu panel grows 820→890 to fit it. Headless-chromium test page + CDP driver verify: button placement, 8/8 random starts reach playing state, image variety, single-image guard, and difficulty preservation.
2026-08-30 21:11:15 -06:00
Brian Fertig 19dff633ce Add jigsaw test harness and local phaser.esm.js bundle
- __jig_test.html boots a Phaser game that loads JigsawGame with stubbed artwork/music caches and exposes window.__* helpers for driving piece grab/drop, scene inspection, and coordinate conversion.
- phaser.esm.js is a vendored webpack build of Phaser used as the "phaser" import map target so the harness can run without a package manager.
2026-08-30 21:03:23 -06:00
Brian Fertig 8dee798ae2 Fix jigsaw piece grab when click lands inside custom hit area
- Add pointerdown handler on each piece to forward the event to the central onTableDown resolver; without it, Phaser's topOnly=true consumes the click and the background never sees it, leaving pieces un-grabbable.
- Anchor the hit-area rectangle to the image's displayOrigin instead of (0,0) so the custom hit box tracks the piece's actual rendered position.
2026-08-30 21:02:22 -06:00
Brian Fertig 85fc7c16bf Add piece joining, board locking, and site soundtrack to jigsaw game
- Introduce group-based table assembly: grid-adjacent pieces snap together on the table, drag as one rigid unit, and lock onto the board as a block
- Extract join/lock rules into pure `resolveDrop` in JigsawLogic.js with a headless verification suite (tools/verifyJigsaw.js) covering fit guarantee, joining, locking, and win counting
- Replace the flat top-bar buttons with a "Menu ▾" dropdown panel to free the top-right corner for the shared site music HUD
- Integrate MusicPlayer soundtrack via getGameSoundtrack() and pin it to the fixed HUD camera
2026-08-30 19:49:00 -06:00
Brian Fertig b6299234cf Fix jigsaw camera bounds and piece tray to avoid overlapping the HUD
- Offset main camera scroll/zoom bounds by HUD_H so the play field
  never slides beneath the fixed top bar
- Shift the scattered-piece tray down by HUD_H to keep pieces clear of
  the target image and HUD
- Assign board panel, frame, and reference image to the main camera only
  so the fixed HUD camera doesn't draw their corners into the screen
2026-08-30 19:03:28 -06:00
Brian Fertig dca1cbef4d Add difficulty-based reference image and ghost slot visibility to Jigsaw
- Hide the faint full-picture reference on Hard and Legendary levels
- Show the target-slot ghost preview only on Easy while dragging a piece
- Store the selected difficulty on the scene for these checks
2026-08-30 18:40:56 -06:00
Brian Fertig 22e6b68cef Add camera pan/zoom and fixed HUD for jigsaw puzzle
- Expand the play field to a 3840x2160 world so pieces can scatter widely and the player can explore
- Introduce MIN_ZOOM (0.5) so the entire field fits on screen, with zoom anchored to the cursor
- Add a second fixed HUD camera so the menu, stats bar, and win overlay stay in screen space while the board camera pans/zooms
- Route world objects and UI containers to their respective cameras via cameraFilter
- Update background, scatter tray, and camera clamping to use the new world dimensions
2026-08-30 18:24:36 -06:00
Brian Fertig a8b4d15e8c Add Jigsaw puzzle game with drag-and-drop pieces and pan/zoom
- New Phaser scene (JigsawGame) supporting 4 difficulty tiers (25–144 pieces),
  image selection, timer, hint overlay, and win screen.
- Pure geometry module (JigsawLogic) generates seeded tab/blank outlines so
  adjacent pieces mesh exactly; also provides deterministic scatter positions.
- Pieces are drawn to canvas textures with depth shading; drag-to-snap with a
  ghost target, camera pan on empty table, and wheel/button zoom (1x–4x).
- Registered in gamesRegistry, main.js scene list, and GameRoomScene slug map;
  game-icons.png updated for the new icon frame.
2026-08-30 17:33:31 -06:00
brianfertig cb4ac7bd85 Merge pull request 'Small update to tutorial' (#4) from Master-of-Vega-Tutorial into main
Reviewed-on: #4
2026-08-29 17:15:37 +00:00
Brian Fertig 26700acbab Small update to tutorial 2026-08-29 11:14:50 -06:00
brianfertig d19fd1681b Merge pull request 'Master-of-Vega-Tutorial' (#3) from Master-of-Vega-Tutorial into main
Reviewed-on: #3
2026-08-29 17:13:03 +00:00
Brian Fertig ce14631544 Expand Master of Vega tutorial to cover full gameplay loop
- Add ~25 new steps: nearby stars, pan/zoom lesson, star info, fleet movement, home star/system view, colony management (allocation, focus), end turn, and the full Empire menu tour (Research, Diplomacy, Leaders, Colonies)
- Introduce hotspotAction, starPick, advanceOn modes (starPick/fleetInFlight/external), and advanceAction fields in tutorial data schema with validation
- Add VegaStarMap.fitToWorldBounds and extend pickFitZoomIndex to support a narrowed viewport area so the reachable-stars frame avoids the docked panel
- Bypass openModal gating for System View, Colony View, and Empire screens by calling their open functions directly from VegaTutorial; wire onClose/onColonyOpen callbacks to advance()
- Add tutorialFreePan flag so pan/zoom work during the free-pan step while all other map interactions stay frozen
- Add multi-target resolution (nearbyStars returns an array), invisible-shape holes, and per-star click hotspots in the tutorial overlay
- Update verification script to allow buttonless modal steps that advance via external callbacks
2026-08-29 11:11:25 -06:00
Brian Fertig 4175da2e26 Add guided tutorial to Master of Vega
- New data-driven script (data/mastervega-tutorial.json) with intro modal and three callout steps over the fleet marker and side-panel ship rows/count controls.
- Split into Phaser-free VegaTutorialData.js (schema validation, interpolation, target-id registry) and Phaser VegaTutorial.js (darken overlay, accent rings, callouts, hotspot, skip confirm, state machine).
- Tutorial auto-opens on every brand-new game and is re-triggerable from the menu when the starting fleet is still in orbit; malformed JSON disables the feature with a warning instead of crashing.
- Add D.tutorial depth (just below detail) so an invited ship-detail window layers above the overlay, and expose VegaSidePanel.tutorialRegion() for screen-space panel regions.
- Register the tutorial asset in the manifest and add verifier section 12 covering schema, targets, voice clips, placeholders, and interpolation.
2026-08-28 22:27:04 -06:00
brianfertig 25d29c0f86 Merge pull request 'Add Tents sound effects and intro jingle' (#2) from Tents into main
Reviewed-on: #2
2026-08-29 03:12:30 +00:00
Brian Fertig 58902075e5 Add Tents sound effects and intro jingle
- Add dedicated place, remove, win, and puzzle-start intro audio assets
- Register the new cues in the asset manifest and SFX key map
- Replace generic UI sounds with Tents-specific cues for placement, removal, and win
- Play the intro jingle on startGame, ducking the soundtrack until it completes
- Update smoke tests to assert the new jingles and cues fire
2026-08-28 21:09:04 -06:00
brianfertig 9363fc3848 Merge pull request 'Add Tents & Trees logic puzzle game' (#1) from Tents into main
Reviewed-on: #1
2026-08-28 02:54:54 +00:00
Brian Fertig af6ea98528 Add Tents & Trees logic puzzle game
- Implement full Tents & Trees scene (TentsGame.js) with day-to-night
  sky transition, campfire/ember/firefly effects, hover hints, violation
  feedback, and a win panel
- Add pure board model (TentsLogic.js) with backtracking solver,
  unique-solution puzzle generation across four difficulties, toggle/
  diagnose/solved helpers — all unit-testable in Node
- Register the game in gamesRegistry, main scene list, and slug dispatch
- Update game-icons.png with a new icon frame for Tents & Trees
- Add tools/verifyTents.js (solver + play-state unit tests and generation
  soak) and tools/smokeTents.js (Phaser-stub smoke test driving the full
  select → play → solve → win → restart flow)
2026-08-27 20:51:26 -06:00
Brian Fertig 199bbc40fb Fix Gin Rummy stale-index drag bug and add Pipe Puzzle unhover regressio
- Resolve hand card index from the container at event time instead of
  capturing it when handlers are bound, preventing the "wrong card on
  second drag" bug after a reorder.
- Enable drag-to-arrange in both draw and discard phases; clicking a card
  during draw now shows guidance rather than discarding.
- Add discard-pile click target so a selected card can be discarded by
  clicking the pile, and extract shared `_setupPileClick` helper to reduce
  duplication.
- Add `tools/regressionPipePuzzleUnhover.cjs`, a Playwright regression
  test verifying that Phaser's `killTweensOf(target, 'prop')` no longer
  clobbers in-flight rotation tweens on pointerout/pointerover.
2026-08-26 22:38:46 -06:00
Brian Fertig 759b70733a Fixed issues with pipe rotation on mouse out 2026-08-25 18:36:46 -06:00
Brian Fertig a4efa5b68a Simplify pipe puzzle to pure spanning-tree boards
- Remove extra-edge generation and cross pieces; board is now a single random spanning tree (one unique route between every pair of cells, no loops)
- Update leak rendering to place droplets on exact open edges using DELTA/EDGE and render water/flash layers above tiles in the container
- Adjust mini preview tiles and difficulty config (drop `extra` param)
- Rework tutorial to explain tree structure, scattered dead ends, and branch-by-branch solving strategy
- Update verification tool: assert tree edge count, no 4-way cells, leaf distribution across rows, faucet row variety, and board randomness; replace cross-based fixture with a valid tree
2026-08-24 22:14:08 -06:00
Brian Fertig d27244ac60 Rework Pipe Puzzle to branching network with no-leak win condition
Replace the single Hamiltonian-path model with a spanning-tree + extra-edges
approach that produces boards full of T-pieces, crosses and dead ends. The
win condition is now simply "zero leaks" — every socket matched to a
neighbour that opens back — instead of requiring one continuous path from
faucet to drain.

Key changes:
- Logic: generate puzzles via randomized Kruskal spanning tree plus tunable
  extra edges per difficulty; add bitCount, countLeaks, and derived
  angleFor/canonical rotation table
- Art: new tile textures for stub (dead end), T-piece, and cross;
  tileKeyFor and angleFor now handle all five piece types
- Game: faucet and drain are fixed anchors (not rotatable); removed the
  CONNECTED counter in favour of a simpler LEAKS stat; updated difficulty
  tiers (6×6 through 10×10) with extra-edge counts; improved water
  rendering contrast
- Tests: rewrite verify script for the new generation model (spanning tree,
  connectivity, piece mix, no-leak solution); update smoke test to skip
  anchor tiles
- Tutorial: updated rules, board reading guide, and tips for the branching
  network variant
2026-08-24 21:04:27 -06:00
Brian Fertig 518818dc1b Add Pipe Puzzle game with Hamiltonian path generation and procedural tile art 2026-08-24 19:42:16 -06:00
Brian Fertig 3bc8b69f1f # Commit Message
## Wolfenstein: Expand E1M2 level and persist per-mission weapon loadouts

### Level Data (assets/gamedata/wolfenstein/level-e1m2.json)
- Increase map dimensions from 33×24 to 39×29 cells, adding new corridors, rooms, and wall structures
- Add tile type `5` (likely a new floor or decorative element) throughout the expanded areas
- Reposition existing doors, guards, items, objects, and wall art to match the new layout
- Add new entities: additional guards with patrol routes, machine gun pickups, ammo, health kits, yellow key, and secret door in the expanded sections
- Update player start position and exit location for the larger map

### Game Logic (src/games/wolfenstein/WolfensteinGame.js)
- Introduce `LOADOUTS_KEY` localStorage persistence to record which weapons the player owned when each mission was unlocked
- Replace `_freshCampaignCarry()` with `_carryForUnlockedStart()`, which loads the recorded weapon loadout for a given mission (falling back to fists-only for mission 0 or unrecorded missions) and tops up ammo to full
- Add `_fullAmmoFor()` helper that computes max ammo reserves for all ammo-consuming weapons in a loadout
- Update `_recordMissionCleared()` to capture the player's current weapon list at clear-time and store it as the unlock loadout for the next mission (only advancing monotonically)
- Change "Next Mission" flow to rely on the recorded loadout rather than extracting live state, ensuring consistent full-ammo/full-health starts
- Update `_retry()` to restore the original attempt's weapons but top up ammo to full per the "die → come back with full ammo" spec
2026-08-23 19:28:07 -06:00
Brian Fertig 9fa3896b5b feat(wolfenstein): add level-new map, improve HUD weapon icon contrast, and update e1m1 items
- Added new "level-new" level data (33x24 grid) with doors, enemies, items, and objects
- Removed one ammo-clip from e1m1 and added two health-large pickups
- Introduced shared HUD row anchor constants for consistent positioning
- Updated HUD to display level name alongside episode/mission info
- Added gray rounded-rect background behind weapon icon in HUD for better contrast against steel-blue bar
- Repositioned weapon icon to dynamically sit left of ammo text based on rendered width
- Updated WolfensteinArt to generate the new HUD icon background texture
2026-08-22 21:08:45 -06:00
Brian Fertig 8b213ea887 feat(wolfenstein): add blue steel plate HUD bar with portrait and inventory
Replace the flat dark rectangle status bar with a baked riveted-metal "blue steel plate" background styled after Wolfenstein 3D's original HUD:

- Add `paintHudBar` to WolfensteinArt.js generating a 1920x140 texture with vertical steel gradient, bevel edges, recessed readout panels, divider strips with rivets, and a centered portrait socket sized around the new `HUD_PORTRAIT_SIZE` constant
- Add `paintProfile` fallback face and wire up `profile.png` (128x128, 3 health frames) in wolfenstein-artwork.json
- Rebuild `_buildHud` in WolfensteinGame.js: left panel shows episode/mission label + HEALTH value, center shows health-reactive portrait (frame swaps at 66/33 HP thresholds), right panel shows INVENTORY key icons + AMMO count with equipped weapon icon
- Derive weapon/key icon frames from `rules.items` data instead of hardcoded values so HUD stays in sync with wolfenstein-rules.json
- Add `_hudEpisodeMissionText()` helper for static per-level label text (campaign episode/mission or test level name)
- Apply subdued CRT overlay (`applyArcadeCRTOverlay`) tuned for a tactical-display feel, destroyed on teardown
- Switch HUD fonts to shared `m6x11` pixel font with white/ice-blue lettering; remove old KEY_COLORS constant and rectangular key indicators
2026-08-22 20:45:39 -06:00
Brian Fertig 0940cd7255 feat(wolfenstein): add fists viewmodel, weapon cycling, ammo drops, and campaign carry-over
- Add fists weapon viewmodel with idle/hit animation states (220ms hit pose)
- Implement mouse-wheel weapon cycling that skips unowned weapons
- Add 33% chance for killed guards to drop ammo-clip pickups at death location
- Introduce campaign carry-over system preserving weapons/ammo/health between missions
- Fix stale 'attack' state clearing when enemies lose sight of player
- Extend save/load serialization to persist nextPickupId counter
- Update level-e1m1 with pistol pickup at spawn point
- Add comprehensive test coverage for all new features in verifyWolfenstein.js
2026-08-22 19:07:37 -06:00
Brian Fertig 5d8f51ae49 Bunch of edits 2026-08-22 17:50:40 -06:00
Brian Fertig eab08eede3 Add multiple weapons, pooled ammo, and pickup system to Wolfenstein
- Add shotgun, machine gun, gatling gun, and plasma rifle weapons with
  distinct fire modes (semi-auto, auto, burst) and damage profiles
- Refactor ammo from per-weapon pools to shared pools keyed by ammo type
  (9mm, shells, plasma), allowing multiple weapons to share the same pool
- Add pickup system with 11 item types: 5 weapons, 4 ammo variants, and
  2 health packs, all with spritesheet frames for rendering
- Update level editor with dynamic pickup dropdown populated from rules.json
- Generalize weapon viewmodel rendering to support multiple weapon images
  with per-weapon bob/sway animation
- Add cosmetic pickup animations: vertical bobbing and orbiting sparkle
  effects drawn in screen space around each pickup billboard
- Bump save version to v3 to invalidate old saves with incompatible ammo
  structure
- Update keyboard bindings for weapon switching (keys 1-6)
- Add comprehensive test coverage for new weapons, burst fire mechanics,
  ammo pooling, and pickup behavior
- Rename weapon_gattling.png to weapon_gatling.png to fix spelling
2026-08-22 14:13:03 -06:00
Brian Fertig a5b37038d2 Add object props (solid obstacles) to Wolfenstein E1M1
Introduces a new "Object" entity type that blocks movement but not sight/bullets, distinct from walls and pickups:

- **Data**: New `objects` array in level JSON (`{x, y, frame}`), with `data/wolfenstein-objects.json` as the frame registry (Tall Bush, Gold Eagle)
- **Artwork**: New `objects.png` spritesheet registered in `wolfenstein-artwork.json`; placeholder texture via `paintObject()` in WolfensteinArt.js
- **Logic**: Objects stored in `state.objects`, with a derived `map.objectBlocked` Set checked only by movement collision (`isWallCell`) — raycaster/sight/bullets never read it, so objects are see-through and shoot-through by construction
- **View**: Rendered as billboard sprites in `_drawSprites` with ground-anchored positioning (bottom edge on floor) and asymptotic depth sorting that stays below the weapon viewmodel
- **Editor**: New "Object" tool category with dynamic dropdown; click open floor to place/remove (toggle), click wall is a no-op; teal square indicator on board
- **Validation**: `validateLevel` checks objects sit on open floor; save/load round-trips with graceful degradation for pre-existing saves
- **Tests**: Verifies object blocks player movement but bullets pass through
2026-08-22 12:29:55 -06:00
Brian Fertig aa685dc505 The user wants a git commit message based on the provided diff.
**Analysis of the Diff:**
1.  **Binary Files:** `walls.png` and `walls.psd` are updated. This suggests an asset update, likely related to the "wolfenstein" theme mentioned in the paths.
2.  **JavaScript File:** `tools/verifyWolfenstein.js` is modified.
    *   A new test case is added under `section('4. Enemy AI');`.
    *   The test verifies that an enemy (guard) alerts when hit by a projectile, specifically in a scenario where:
        *   Visual detection (LOS+FOV) is blocked/blind (guard facing away).
        *   "Heard gunfire" alert path is blocked (different room/door logic).
    *   The test sets up a specific level layout, forces a door open, fires a pistol, and checks if the enemy's state changes from 'idle' to something else (alerted) and health drops.
    *   It explicitly mentions fixing an issue with `stepDoors` auto-close countdown underflow by setting `timer`.

**Synthesis:**
The primary functional change is adding a test case to ensure that direct hits alert enemies even when other alert mechanisms (vision, sound through doors) fail. The asset changes are likely incidental or part of the same feature branch (Wolfenstein theme).

**Drafting the Commit Message:**
*   **Subject:** Add test for enemy alert on direct hit bypassing vision/sound checks
*   **Body:**
    *   Update Wolfenstein wall assets (PNG/PSD).
    *   Add verification test in `verifyWolfenstein.js` ensuring enemies alert when shot, even if they cannot see the player or hear gunfire through doors.
    *   Fix door timer initialization in the test to prevent auto-close interference during projectile flight.

**Refining for Conciseness:**
Subject: Add enemy hit-alert test and update Wolfenstein assets

Body:
- Update `walls.png` and `walls.psd`.
- Add a test case in `verifyWolfenstein.js` verifying that direct hits alert enemies unconditionally, independent of vision cone or room-based sound alerts.
- Ensure door state is correctly initialized in the test to prevent auto-close interference with projectile simulation.

Let's make it standard conventional commit style if possible, or just clear and descriptive.

**Final Polish:**
Subject: Add test for unconditional enemy alert on direct hit

Body:
Update Wolfenstein wall assets (`walls.png`, `walls.psd`).

Add a new test case in `verifyWolfenstein.js` to verify that enemies alert when directly hit by a projectile, even when visual detection (LOS/FOV) and sound-based alerts (through doors) are inactive. This ensures the direct-hit alert path works independently.

Also fixes door timer initialization in the test setup to prevent auto-close logic from interfering with the projectile simulation.

This looks good. I will provide just the message as requested.
2026-08-22 10:51:42 -06:00
Brian Fertig c0ab9155a3 Add wall art decals to Wolfenstein levels
- 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
2026-08-22 10:32:59 -06:00
Brian Fertig 7d9729e594 Improve sprite occlusion handling in Wolfenstein view
Replace all-or-nothing per-sprite depth checks with per-column occlusion
testing. This allows walls to correctly hide only the parts of sprites
(like dead guards) that are behind them, rather than hiding the entire
sprite if any part is occluded.

Implementation details:
- Walk outward from the sprite's center column to determine the visible
  span based on the wall depth buffer.
- Use Phaser's `setCrop` to clip the sprite to the visible columns, which
  is more performant than redrawing per-column like walls.
- Add `OCCLUSION_EPS` tolerance to prevent flickering when sprites are
  positioned exactly against walls due to float precision issues.
2026-08-22 09:58:21 -06:00
Brian Fertig a6f6b647da Wolfenstein: Add semi-auto fire modes, ammo types, enemy stun, and editor facing picker
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.
2026-08-22 09:39:09 -06:00
Brian Fertig 74f8d0c926 wolfenstein: alert room-mates on gunfire, fix guard side-sprite flip
Add computeRooms + alertEnemiesInPlayerRoom: a gunshot now alerts every
idle guard sharing the player's room regardless of range/LOS/cone. A
door cell is always treated as a room boundary for this purpose, even
when fully open — two rooms joined only by a doorway stay distinct
("gunfire carries through the room, not through doorways").

Fix _guardFacing side-walk/side-idle flip: was `rel > 0`, read
backwards in-game, now `rel < 0`.

Cover with three verifyWolfenstein cases: same-room alert fires,
behind-closed-door does not, through-open-door does not (door forced
slide=1 / wall zeroed to exercise the slide-independent path).
2026-08-21 20:31:39 -06:00
Brian Fertig 9b3dccf4b5 feat(wolfenstein): add enemy vision cone, patrol loop behavior, and weapon sprites
- 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
2026-08-21 20:23:02 -06:00
Brian Fertig 2cc075e8be Improve bullet sprite appearance and reduce its render scale
- Replaced the single-circle bullet texture with a three-circle design
  (brass/copper body, bright tracer core, and off-center highlight) for
  better readability against various backgrounds
- Reduced bullet texture size from 16×16 to 12×12 to match the more detailed
  design
- Decreased bullet render scale from 0.18 to 0.1 in the view to make bullets
  appear as small rounds rather than floating dots
- Updated documentation in sprites.md to reflect the new bullet design, size,
  and scale changes
2026-08-21 19:40:45 -06:00
Brian Fertig c86ccb9d1f feat(wolfenstein): add POV pistol viewmodel with procedural fallback
Introduce a first-person weapon viewmodel for the pistol that peeks up
from behind the HUD, completing the classic FPS look. The viewmodel
features a subtle, smoothed bob and sway animation that responds to
player movement (forward/strafe), ramping in and out to avoid
snapping.

- Add `paintWeaponPistol` to `WolfensteinArt` as a small procedural
  placeholder (360x260) for when real art is absent.
- Update `WolfensteinView` to handle both real and procedural weapon art
  with appropriate origins and base positions.
- Implement `_drawWeapon` with bob/sway logic and smooth strength
  transitions.
- Register the new sprite key in `wolfenstein-artwork.json`.
- Document the new `wolfenstein-weapon-pistol` asset in `sprites.md`,
  including its size, depth, and behavior.
2026-08-21 19:32:48 -06:00
Brian Fertig 965e4308c9 feat(wolfenstein): guard sprite animation, death sequence, and E-key door interact
- 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
2026-08-21 19:22:22 -06:00
Brian Fertig f6081de0a8 Add real door textures with sliding-see-through rendering
The raycaster's door geometry now takes the live `doors[]` state instead of a boolean flag, so partially-open door cells let render rays pass through the already-slid portion to show what's genuinely beyond, rather than painting a flat "socket" fill. `intersectDoorMidplane` returns a slide-shifted `textureX` so the door texture visibly translates into the wall as it opens.

`WolfensteinView` samples the new `wolfenstein-doors` sheet the same way it does walls (source-texel column, vertical crop, multiply shading), falling back to the flat tan placeholder. Added the doors.png/.psd assets and a `sheets.doors` entry in the art manifest. Updated sprites.md to document the new sheet, the see-through behavior, and that this stays render-only (gameplay raycasts are unaffected).
2026-08-21 17:54:36 -06:00
Brian Fertig a336376a93 wolfenstein: pan/zoom editor with minimap, sliding recessed doors, enemy patrol
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.
2026-08-21 17:34:07 -06:00
Brian Fertig 103bc235a7 Added Wolfenstein 2026-08-18 19:10:44 -06:00
Brian Fertig 625ced5649 TA AI Updates 2026-08-17 21:15:32 -06:00
Brian Fertig 73de46e0f1 Updated with new unit and better AI 2026-08-17 20:27:48 -06:00