## 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
- 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
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
- 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
- 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
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
**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.
- 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
- 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
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).
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.
- Introduce Megatank: medium commander with Twin 150mm Cannon and Side Rocket Pods
- Implement multi-barrel weapon system (barrels + barrelSpacing) in TALogic and TARules
- Lower DEFENCE_MIN_SKILL from 4 to 3; make first Laser Tower proactive, not reactive
- Rebalance unit triangle: Tank now counters Rocket Tank; rockets weak vs vehicle armour
- Re-seed campaign missions m05 (67890) and m06 (80808) with updated maps and briefings
- Skirmish default theme uses rules default (tropics) instead of hardcoded grasslands
- Add intro video before main menu
- Update sprite docs and verification tests for new balance
- Introduce Megatank: medium commander with Twin 150mm Cannon and Side Rocket Pods
- Implement multi-barrel weapon system (barrels + barrelSpacing) in TALogic and TARules
- Lower DEFENCE_MIN_SKILL from 4 to 3; make first Laser Tower proactive, not reactive
- Rebalance unit triangle: Tank now counters Rocket Tank; rockets weak vs vehicle armour
- Re-seed campaign missions m05 (67890) and m06 (80808) with updated maps and briefings
- Skirmish default theme uses rules default (tropics) instead of hardcoded grasslands
- Add intro video before main menu
- Update sprite docs and verification tests for new balance
- **Visual Feedback**: Introduce VegaBombardScreen.js — a two-stage popup for
bombard/invasion results featuring JIT-loaded videos (per planet type or
invading species) and animated stat bars showing population, factory, and
building losses.
- **Expanded Consequences**: Factory and building destruction now scale with
the population kill ratio. On colony wipeout, weapon Mark gates planetary
ruin/ruination (toxic/radiated/dead/asteroids) via a weighted probability table.
- **AI & Tactics**: Ursaal now queue troop transports alongside warships for
invasion fleets. Added `bombardHoldFireChance` trait (0–1) to let species
defer bombing when invasion troops are staged, preserving intact colonies
without creating fortress-world stalemates.
- **Battle Logic Fixes**: Correct `prepareBattleAt` and `pendingBattlesFor` to
properly handle stars with multiple colonies, ignore transport-only fleets,
and suppress pending battles when planetary defenses are depleted.
- **UI/Reporting**: Wire player-initiated and AI-initiated attacks into the
new popup queue. Add `bombard` and `invasionFailed` to notable turn report
events with detailed outcome descriptions.
- **Testing & Tooling**: Add comprehensive verification tests for planet
destruction distribution, building damage rates, hold-fire chances, and
battle edge cases. Expose `window.game` for devtools debugging.
- Replace flat planetDefenseBase (20) with proportional planetDefenseScale
(0.06), so colony defense damage scales purely with current defenseHp.
A near-depleted colony now barely scratches attackers, while a fully
tech'd one still tops out ~110 damage — fixing "attacked with the
strength of a much-better-defended planet" (Brian, 2026-08-14).
- Add AI war memory: track consecutive losses per enemy and escalate
attackMultiplier up to 3x so repeated losing attacks stop dribbling
small fleets. A win resets the streak. Prevents permanent phoney wars
where both sides build to equal strength and nothing moves.
- Show "Under Attack" notice (one-button, no formation picker) when AI
attacks the player, since formation choice is meaningless for defense.
- Add planetary beam fire SFX for combat view.
- Add event `seq` cursor for war memory to survive event list trimming.
- Full test coverage for planet damage formula and AI escalation behavior.
- Replace □/■ glyphs with channel-specific icons inside the lock toggle boxes
- Introduce `allocation.png` (5 frames) and register it in the artwork config
- Add hover tooltips explaining each channel's production role and MOO1-style
overflow behavior
- Expose slider `zone` for tooltip attachment and adjust icon/layout positioning
- Update sprite documentation and include minor audio asset update
- Add leader detail pop-over (VegaLeaderDetail.js) with portrait, bio, and
current posting bonuses displayed in fleet and colony views
- Add leader portrait click-to-zoom in the Leaders screen
- Add leader skill summary formatting (leaderSkillSummary) for readable
bonus descriptions across UI components
- Integrate leader skills into espionage power/defense and invasion attack
calculations in VegaLogic.js
- Cap bombard() at once per (attacker, colony) per turn via lastBombardTurn
tracking; fixes UI double-click and AI double-bombard bugs
- Contact-gate GNN breakthrough stories and ranking charts on first contact,
matching existing rankingRows behavior
- Round population displays throughout the UI (toFixed(1) → Math.round)
for cleaner presentation
- Bump colony ship and transport base costs in rules data
- Add leaders.png artwork reference to mastervega-artwork.json
- Add tests for bombard cap and GNN contact-gating in verifyMasterOfVega.js
Introduce a full-screen, click-advanced ceremony (VegaCouncilSession.js)
that replays runCouncil()'s result delegate-by-delegate instead of hiding
the tally behind the turn-report. Three fixed stages — Roster, Voting,
and Verdict — with a persistent 2:3 portrait anchor video, green-screen
ticker, live scoreboard with animated bars, and sting-then-loop audio.
Key changes:
- VegaLogic.js: expose per-voter `voters` breakdown and `pendingSession`
flag so the UI can replay the session before the victory check.
- MasterOfVegaGame.js: consume `pendingSession` in `runToHumanTurn()`
before `state.over`, ensuring a decisive council still gets its ceremony.
- VegaTurnReport.js: remove `council` from NOTABLE_TYPES (ceremony handles
it); keep `councilRefused` as a distinct war-declaration row.
- assetManifest.js / Sounds.js: register video + sting/loop audio cues.
- VegaScreens.js: add `D.council` depth value.
- verifyMasterOfVega.js: assert voter breakdown consistency and pending
session lifecycle.
Introduce a full-screen, click-advanced ceremony (VegaCouncilSession.js)
that replays runCouncil()'s result delegate-by-delegate instead of hiding
the tally behind the turn-report. Three fixed stages — Roster, Voting,
and Verdict — with a persistent 2:3 portrait anchor video, green-screen
ticker, live scoreboard with animated bars, and sting-then-loop audio.
Key changes:
- VegaLogic.js: expose per-voter `voters` breakdown and `pendingSession`
flag so the UI can replay the session before the victory check.
- MasterOfVegaGame.js: consume `pendingSession` in `runToHumanTurn()`
before `state.over`, ensuring a decisive council still gets its ceremony.
- VegaTurnReport.js: remove `council` from NOTABLE_TYPES (ceremony handles
it); keep `councilRefused` as a distinct war-declaration row.
- assetManifest.js / Sounds.js: register video + sting/loop audio cues.
- VegaScreens.js: add `D.council` depth value.
- verifyMasterOfVega.js: assert voter breakdown consistency and pending
session lifecycle.
Introduce GNN, a galaxy-wide news broadcast feature that reports major
events to the player via a full-screen takeover UI with anchor desk
video, story pages, MOO1-style animated rankings, and a diplomatic
relations reference.
Key changes:
- VegaGnn.js: headless event classification, anchor copywriting, and
ranking logic (Phaser-free, testable in Node)
- VegaGnnScreen.js: full-screen UI with looping anchor video,
green-screen ticker terminal, story renderers (diplomacy/tech/
territory/espionage), animated bar-chart rankings, and relations page
- HUD: new GNN button with unread bullet cue; auto-opens after turns
when stories are pending, on-demand via button
- VegaLogic.js: new `lastColony` event (reduced to single world),
`attacker` field on elimination events, `gnn` state with history
buffer, export empireFleetPower for multi-empire rankings
- VegaColoniesScreen.js: export and generalize createAdvisorTerminal
for reuse by GNN's ticker
- mastervega-rules.json: flag ~16 headline-worthy techs with
gnnHeadline (research-sourced only, not espionage-stolen)
- Assets: eager-load GNN anchor video, sting/loop audio, and populate
all 10 species colony advisor videos in mastervega-artwork.json
- verifyMasterOfVega.js: comprehensive 7b test section covering
classification, consumption, describeGnnStory, anchorLine, attacker
threading, ranking metrics, relationsRows, serialization, and AI soak
- Add full-screen intro video (mov-intro.mp4) that plays once on fresh game
entry, with skip prompt on first keypress and immediate skip on second
- Include intro soundtrack (intro-theme.mp3) and updated menu title image
- Skip video on Load-slot resume to avoid interrupting returning players
- Add orange highlight to Colony/Allocation Focus pills when their setting
disagrees with the advisor's recommendation (recommendColonyFocus/
recommendAllocationFocus)
Introduce `VegaCombatV2.js`, a parallel headless combat engine that simulates
individual ships (not stack aggregates) in continuous time rather than discrete
rounds. Ships have per-hull `sizeScale`, `sizeSpeedMult`, and `turnRateBase`
fields; every entity tracks its own cooldown, position, facing, and angular
momentum. Damage and movement are banked per-tick to preserve fairness.
Accompanying files:
- `VegaCombatViewV2.js` — zoomable/pannable Phaser view with parallax starfield
- `VegaCombatCamera.js` — cursor-anchored zoom + drag-to-pan (listener cleanup
on destroy to avoid stacking across battles)
- `VegaFormations.js` — formation strategy plumbing (chosen per side, not yet
read by movement/targeting)
- Hull-specific destroy audio cues and vega buildings art
Wired behind `?movsim`'s Live/V2 toggle in `VegaCombatSim.js` — the live engine
and all real player battles are untouched.
Also fixes several latent bugs discovered during the rewrite:
- Trap 26: simultaneous wipe-out now checks draw before single-side wins
- Trap 27: movement is banked (two-phase) like damage
- Trap 28: weighted-random targeting tames chaotic nearest-neighbour sensitivity
- Trap 29: fleet gap clamped to 85% world width to prevent starvation
- Trap 30: `RANGE_EPS` tolerance prevents steering-induced standoffs
See `docs/mastervega-build-plan.md` for full design notes.
Move vega audio files into assets/fx/vega/ subdirectory and register them via
assetManifest.js. Add weapon and missile sound cues banded by ship Mark, with
staggered playback in VegaCombatView to prevent audio clipping during barrages.
Wire up two previously inert tech effects in combat:
- Stealth Field (cloaked): applies a flat accuracy malus via cloakEvasion rule.
- Black Hole Generator (singularity): adds passive shield pierce via
singularityShieldPierce rule on every weapon fired by the design.
Update tech descriptions, ship detail display, and designFor() to reflect
these effects. Fix a bug where singularity was never copied into the design
object.
Add vega-endturn cue to End Turn / Next Round buttons (no-op when busy),
remove hardcoded audio loads from PreloadScene, and add verification tests
that isolate each flag with A/B battle comparisons.
- Introduce Colony Focus: a per-colony autopilot that auto-queues one
building/ship per turn when the queue is empty. Supports seven modes
(manual, improvement, research, fleet, growth, trade, defense) with
cost-aware affordability checks matching AI behaviour.
- Add Allocation Focus: one-time slider presets (default, research,
growth, production, military) that bulk-overwrite channel allocations.
- Refactor colony view flyout into a shared drawer supporting queue,
colony focus, and allocation focus modes with in-place swapping.
- Replace "Built here" text with hoverable building icon row and
tooltips on the colony screen.
- Add per-species audience music tracks and diplomacy music ducking when
seeking/planning an audience.
- Add sound effects for star selection, zoom in/out, and colony view
opening.
- Back-fill `focus: 'manual'` on old saves for forwards compatibility.
- Add verification tests exercising each focus mode in isolation.
- Implement 10 manual save slots with metadata (turn, year, empire, species, date)
- Add ☰ game menu button with Save, Load, Return to Main Menu, and Quit to Arcade
- Replace generic sounds with 7 custom Vega sound effects (select, build, close,
newturn, unit, view, warp)
- Introduce uiClick() helper to standardize click sound across all modal screens
- Update research video paths for umbrix and rrashaa species
- Refactor button handlers in all Vega screens to use uiClick() pattern
- Save/load uses scene restart via pendingSavedState for clean HUD/map teardown
- Add scaling leader hire costs based on number of leaders already owned (costScalePerOwned: 0.5), making it progressively more expensive to hire multiple leaders and preventing cheap roster stockpiling
- Add leaderHireCost() function in VegaLogic.js to calculate scaled hire costs
- Add unassignLeader() function to allow removing leader assignments
- Update AI in VegaLeaders.js to use dynamic pricing when deciding to hire leaders
- Add research videos for ursaal, kkrix, and mekhan factions
- Enhance leader screen UI with:
- Dynamic cost display reflecting current scaling
- Fleet labeling showing ship composition and location
- Assign/Reassign buttons with list picker for colonies (admins) and fleets (captains)
- Unassign button for posted leaders
- Better location display for assigned leaders
- Add full diplomacy subsystem: tiered gifts (BC payments with diminishing returns), trade agreements (passive BC income, coexists with treaties, cancelled on war), and espionage mission toggles (Off/Steal/Sabotage) in the Audience screen.
- Implement whole-galaxy diplomacy passes: border and fleet proximity tension, fleet intrusion tracking with escalating penalties and force-opened Audience complaints, and "enemy of my enemy" attitude triangulation.
- Update Audience screen UI with new action buttons, gift picker, intelligence toggle, and species-specific chat dialogue for all diplomacy events.
- Add research choice prompts for ambiguous tech frontier picks, surfaced before the turn report.
- Improve star map: Delaunay triangulation for controlled-space range darkness, staggered docked fleet markers, expanded pan slack to clear UI chrome, and zoom-aware colony info labels.
- Backward-compatible save serialization for new diplomacy fields.
- Add comprehensive test coverage for all new logic, chat completeness, and AI soak validation.
- Introduce VegaResearchChoiceScreen for ambiguous tech selections: when
a player completes research that opens a 2+ way choice rung, they're
prompted before the turn report to pick their next technology.
- Add VegaDelaunay.js (Bowyer-Watson Delaunay triangulation) and use it
in VegaStarMap to draw "controlled space" corridors/fills between the
player's own colonized stars instead of a blanket radius.
- Improve star map UX: stagger docked fleet markers per-star, add
PAN_SLACK so edge stars can be dragged out from under the side panel,
and show colony info bars at mid-zooms with text only at near-zoom.
- Add `closable` option to modalShell so forced-choice screens can
suppress the ✕ button.
- Export buildVideoPanel from VegaResearchScreen for reuse by the new
choice screen.
- Update artwork JSON: rrashaa and cerebrai audience videos now use
species-specific clips; add intro-human.mp3 and new video assets.
- Add tests for openResearchChoices and pendingResearchChoices filtering
logic in verifyMasterOfVega.js.
- Add 21 new alternate techs across all 6 fields (computers, construction,
forcefields, planetology, propulsion, weapons), using icon frames 78-96
- Set research video paths for human and kestrelli species
- Expand tech sprite sheet from 8 to 10 rows to accommodate new frames
- Add fieldTechLevel() to VegaLogic: displays per-field level as highest
known tier × 5 plus extra known techs below the frontier
- Display field level in research screen headers
- Add verification tests for 3-way branching rungs, fieldTechLevel calculations,
and refine availability roll tests to measure unbranched rungs only
- Replace vertical "research ladder" list with a visual tech tree rendered as
connected node badges showing prerequisites and branch structure
- Add `initialField` parameter to `openResearchScreen` to open on a specific
category instead of always defaulting to the first one
- Add "View Research" shortcut button on turn report when a tech completes,
jumping directly to that field
- Add Cerebrai species research video (research-cerebrai.mp4)
Introduce colony naming with a 50-name bank per species, shuffled
per-empire and displayed as defaults in naming prompts. Colony names
now appear across all UI layers (star map, side panel, colony view,
system view) with the astronomical designation as fallback.
Add three pure-flavor conversation topics to diplomacy: "Their People"
(neutral+), "Their Homeworld" (friendly), and "A Story" (friendly).
Each diplomacy-capable species receives unique lore-rich responses
(3 variants each) reflecting their culture, homeworld, and history.
Other changes:
- Switch ursaal videos from generic "human" assets to species-specific
- Widen diplomacy buttons to 200px; add auto-shrink for long labels
- Add ±5 population transport buttons to colony view
- Validate colonyNames (50+ entries, no duplicates)
- Enforce minimum lore variant counts in verification
- Add colony info layer showing per-empire colony rosters (name, orbit, pop)
stacked up-left of colonized stars with colored bars and connector lines
- Change "Range as light" to "Explored as light": reveal only actually
explored stars (not fuel-reachable) with smaller 1.1pc radius
- Extract VegaTechEffects.js with human-readable descriptions for all
tech effects, replacing raw key/value dumps in turn report
- Expand building unlock rows to include building descriptions
- Reorganize ship completion rows: hull icon and commander portrait now
display below the full-width synopsis instead of beside it
- Bump zuma level 8 config to level 21 "Sun Cove" with new path and params
Replace the eager `ensureAudienceVideos()` warm-up (which loaded all three
mood clips per species upfront) with on-demand JIT loading — only the mood
about to be shown is fetched. This saves several megabytes per species since
most conversations never cycle through all moods.
- Remove `ensureAudienceVideos()` and its call in `openAudienceScreen()`
- Load each mood clip only when `show()` is first called for that mood
- Show a letterboxed placeholder for the very first clip until the fetch lands
- Keep whatever is already on screen while a new mood loads in the background
- Add `destroy()` guard to prevent in-flight fetches from mutating a torn-down
container when the audience screen is closed
Also ship the dedicated Kestrelli audience clips (angry, neutral, happy) to
replace the previous human fallback videos for that species.
- Add Colony Transport ('poptransport') hull, dispatched directly in transit
from a Send Population order rather than built from the queue. Shares the
Troop Transport's hull art and uses the colony ship's commander clip.
- Implement VegaLogic sendPopulation/deliverPopulation flow: clamped to
maxSendablePopulation (leaves 0.5 floor), creates poptransport fleet
immediately, auto-delivers on arrival capped at destination max pop.
- Add Send Population button and overlay picker in colony view with
destination list, ETA display, amount dial, and MAX button.
- Log populationSent/populationDelivered events in the turn report.
- Refactor VegaAudience mood visuals to play-once-and-hold-last-frame with
a clickable replay badge, mirroring VegaColonyIntro's video contract.
- Seed human audience mood clips (angry/neutral/happy) into artwork config
as placeholders for all diplomacy-capable species.
- Add verification tests for poptransport mechanics and video aliasing.
- Rewrite contact detection from proximity-based (parsec-range) to
star-scoped: empires now meet by sharing a system (colonies or fleets),
making first-contact a visible event rather than a silent background
check.
- Add full-screen Audience interface (VegaAudience.js) with species-specific
mood videos (or letterboxed portrait fallbacks), a typewriter chat log,
and contextual action buttons. Auto-opens on first contact via a queue
system in MasterOfVegaGame.
- Add VegaChat.js with unique dialogue pools for all 9 diplomacy-capable
species across 18+ situations (first contact, peace/alliance offers,
war declarations, tech trades, accept/reject responses, etc.).
- Introduce held diplomacy offers: AI proposals to the human are queued
(pendingOffers) instead of auto-resolved, with player Accept/Reject
buttons in the Audience screen and automatic expiry after 6 turns.
- Add audienceVideos config and JIT-loading infrastructure in VegaArt.js.
- Add ship videos for kkrix and mekhan species.
- Simplify openDiplomacyScreen to a single "Seek Audience" button.
- Fix colony view to filter out 'starbase' from building display list.
- Add comprehensive verification in tools/verifyMasterOfVega.js for
contact system, held offers, chat completeness, audience videos,
and serialization of new state fields.
- Remove obsolete contactRange rule from mastervega-rules.json.
Replace the turn-report "New Turn" popup row with a cinematic vignette that
plays the moment the player plants a colony: the soundtrack ducks, the world's
1920×1080 backdrop fills the screen, a 960×544 clip of this world being settled
plays in a framed window, and the founding numbers are read out underneath.
Key changes:
- Add `colonyVideos` block (15 clips, one per colonisable planet type) to
artwork JSON; clips are fetched just-in-time via ensureColonyVideo() when a
colony ship reaches a settleable world, keeping the set (~19 MB) out of the
eager manifest
- Add `vega-colony-cue` audio to the eager manifest for the founding soundtrack
- Remove `colonised` from NOTABLE_TYPES and TYPE_LABEL so the event is no longer
announced twice (once in the vignette, once in the turn report)
- Add `sourceWidth()` guard in VegaArt.js to fix a Phaser Video placeholder
width bug exposed by the non-square 960×544 colony clips (2.5× scale issue)
- Apply `sourceWidth()` to portrait and commander video scaling paths as well
- Add depth entry `intro: 78` to VegaScreens.js for the vignette overlay
- Add section 6b to the verifier: checks manifest exclusion, key conventions,
sourceWidth() behavior, turn-report classification, and colony stats
See build-plan trap #23 for the full sourceWidth() explanation.
- Add human ship spritesheet (ships.png) and increase frame size to 192x192
- Add jungle world background texture (world-jungle-01.png)
- Add human ship animation videos (scout, frigate, destroyer, cruiser,
battleship, transport, colony)
- Enable species card selection with required choice before starting game
- Disable "Begin" button until a species is selected
- Add title logo breathing animation and light sweep effect on landing screen
- Reposition title and start button on landing layout