Commit Graph

596 Commits

Author SHA1 Message Date
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
Brian Fertig 347957bd84 TAL: smooth obstacle collision push + in-place building upgrades (upgradesFrom)
Movement & collision:
- stepSeparation (TALogic) replaces the hard "snap unit to nearest clear
  tile centre" correction with a circle-vs-blocked-tile push proportional
  to overlap, damped by separationStiffness — no more teleport-yank,
  corner-bouncing, or stalling in exact-width corridors (caught as an
  AI-vs-AI win-rate regression in testing).
- servicePathQueue now routes at a unit's exact required clearance instead
  of padding +1, so traffic spreads across all passable tiles rather than
  funneling into a few wide chokepoint corridors.
- TAArt's structure painter falls back to a generic spinning glyph for
  topperFrame buildings.

Upgrades (new rule: upgradesFrom):
- A building may be placed directly on top of a friendly building it
  names at the same tile/footprint, consuming it for a 50% refund of the
  replaced building's OWN cost (not a price discount) — implemented via
  TALogic.findUpgradeTarget and an army-aware canPlaceAt.
- New definitions: nuclearplant (upgrades energygen, frame 22) and
  advancedmassgen (upgrades massgen, frame 24).
- compileRules (TARules) validates upgradesFrom references and topperFrame;
  sprites.md documents the semantics.
- New map m06 "Annihilation" (medium, snowfields, Klaxon skill 5, seed
  90123 — pre-vetted from the original sweep for early-economy balance).

Tests (tools/verifyTotalAnnihilation.js):
- Section 4d: pathfinding routes around obstacles and a unit threads a
  corridor exactly its own width.
- Section 5b: obstacle push is a bounded per-tick nudge (not a
  teleport), settles clear without oscillation, a unit ordered past an
  obstacle arrives, and no stuck-give-up flagging.
- Upgrade suite: exact 50% refund credited in place, fresh-ground builds
  still work, enemy-owned and mismatched-type targets rejected, reverse
  nuclearplant/energygen pairing, and canPlaceAt without an army never
  grants upgrade placements.
2026-08-16 18:59:30 -06:00
Brian Fertig 3c7184564a totalannihilation: add building upgrades and spinning toppers
- New `upgradesFrom` rule: a building def (Nuclear Power Plant on the
  Energy Generator, Advanced Metal Generator on the Mass Generator) may
  be placed exactly on a friendly, finished building of the named type,
  consuming it for a 50% refund of its build cost instead of needing
  clear ground (TALogic findUpgradeTarget / consumeUpgrade / buildCommand)
- New `topperFrame`: a second sprite stacked on the finished structure
  that spins continuously (the Advanced Metal Generator's centrifuge,
  frame 26), hidden while under construction; TAArt sizes the sheet for
  it and paints a generic spinner-glyph fallback
- New rules: Nuclear Power Plant (frames 22-23) and Advanced Metal
  Generator (frames 24-26) in totalannihilation-rules.json
- TARules: validate topperFrame and upgradesFrom (real building with a
  cost); TAWorldView renders/spins the topper; verifyTotalAnnihilation
  checks topper frames fit and were painted
- Test section covering upgrade placement (ownership, type match, exact
  footprint, refund amount, army-less fallback) and sprites.md updated
  for frames 22-26
2026-08-16 15:35:31 -06:00
Brian Fertig c690d80e68 feat(totalannihilation): add Megatank unit with multi-barrel weapons and rebalance combat
- 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
2026-08-16 14:30:04 -06:00
Brian Fertig 045327d38a feat(totalannihilation): add Megatank unit with multi-barrel weapons and rebalance combat
- 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
2026-08-16 13:42:54 -06:00
Brian Fertig 09a62f12cc feat(mastervega): add morale bonus system and espionage restraint diplomacy
- Add morale bonus from buildings (e.g., Holo Simulator): flat +N% to total
  colony production, uniformly boosting construction, defense, industry,
  ecology, and research
- Add espionage restraint (offDrift): setting Intelligence to 'off' toward
  an empire with neutral-or-better opinion drifts their attitude upward by
  1/turn, giving a way to improve relations without gifting (gated on not
  being at war and their opinion of you being >= 0)
- Display morale bonus in colony view when applicable
- Reduce planetShotDamageMult from 10 to 6
- Add verification tests for both new mechanics
2026-08-16 08:12:16 -06:00
Brian Fertig 46a2979555 fix: starbases cannot attack alone; AI targets correct colony at contested stars
- Starbases no longer count toward attacker power in holdsOrbit(), invade(),
  resolveCombats(), pendingBattlesFor(), and prepareBattleAt(). A starbase
  never leaves its home system, so it must never alone enable orbital
  superiority or pick fights with neighbouring hostile colonies (Brian, 2026-08-15).

- VegaAI manageFleets 2a/2b now uses targetColonyAt() instead of colonyAt()
  to resolve the colony it is actually at war with. At multi-colony stars
  this fixes the bug where an idle fleet sitting on a hostile undefended
  colony would silently check a different (not-at-war) colony sharing the
  star and never bombard/invade (Brian, 2026-08-15).

- Add test suite 5f (starbases cannot attack alone) and 5g (AI bombard/invade
  at contested multi-colony stars).
2026-08-15 10:54:16 -06:00
Brian Fertig 9e463164d9 increase planet shot damage multiplier from 1 to 10
Bumps the planetShotDamageMult config value in mastervega-rules.json
to significantly increase damage dealt during planetary bombardment
or planet defense scenarios.
2026-08-15 09:39:51 -06:00
Brian Fertig 033912bc73 feat: redesign planetary defense as ammo model with range gating
- defenseHp is now a pure per-battle ammo gauge (one full-strength
  shot per planetDefensePerShot points, remainder as fractional shot)
  instead of in-battle damage tracking; no longer written back after
  battle outcome
- Planet now has a real range limit (planetRange, 1200) — previously
  the only entity with no range check at all
- Per-shot damage scales with the defending empire's best known weapon
  tech (weaponAvgDmg) instead of a flat HP-proportion curve
- defenseHp is only wiped to 0 when the planet is actually DESTROYED,
  fixing the bug where a defeated planet could be re-attacked multiple
  times in one turn with full strength each time
- Added combat config: planetDefensePerShot (5), planetShotDamageMult (1)
- Added combatV2 config: planetRange (1200)
- Comprehensive tests for range gating, shot formula, ammo exhaustion,
  multi-battle-same-turn fix, and tech-scaled damage
2026-08-15 09:20:43 -06:00
Brian Fertig d920d8e476 feat(combat): freeze colony defense regen and defensive builds while under siege
Add siegeFreezesDefense mechanic (default true) that stops a colony's
passive defenseHp trickle and blocks defensive building completion at the
front of the build queue while a hostile warship fleet is present.

This fixes the recurring "Under Attack" notification loop reported by Brian
where defenseHp would regenerate each turn, re-arming the pendingBattlesFor
gate and triggering fresh popup notices for an already-beaten colony.

Also adds an AI dispatch throttle in manageFleets: idle fleets no longer
open redundant attack orders against colonies the empire already holds orbit
over with defenseHp beaten to 0. Excluded fleets fall through to rally logic
and naturally join the existing siege or find a fresh front.

New helpers: isDefensiveBuildingId, isHostileWarshipFleet, hasHostileWarshipFleet
— shared across processColony, pendingBattlesFor, and VegaAI to ensure a
single definition of "under active siege".

Includes tests (sections 5d, 5e) covering regen freeze, build queue freeze,
siegeFreezesDefense=false toggle, and AI throttle.
2026-08-15 08:00:40 -06:00
Brian Fertig 869f041b39 feat(master-vega): overhaul bombard/invasion UX, consequences, and battle logic
- **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.
2026-08-14 23:17:31 -06:00
Brian Fertig 3bad628968 fix(mastervega): balance planetary defense and improve AI attack logic
- 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.
2026-08-14 14:24:22 -06:00
Brian Fertig 2b1fe96bf6 Changes to battle system so the player can view battles initiated by the other side. 2026-08-14 12:17:14 -06:00
Brian Fertig 52b9f2b29f Small Updates 2026-08-14 12:00:26 -06:00
Brian Fertig cba84dc0b8 Updated Battle Scanner 2026-08-14 11:19:30 -06:00
Brian Fertig c8e22a51a5 feat(mastervega): add Galactic Expansion/Expansion advisor focuses and fleet urgency system
- Add "Galactic Expansion" colony focus and "Expansion" allocation focus
  for early-game land grab phase (one colony ship per discovered open world,
  then 2 frigate escorts per colony ship)
- Introduce fleetUrgency() — sliding-scale fleet recommendation based on the
  coldest contacted relationship, throttled pre-contact to avoid premature
  militarization
- Hide Council menu button until the Council has actually convened (lastResult)
- Add tooltip to disabled population send button explaining why it's off
- Rename "Production" allocation preset to "Industrial Buildout"
- Expand Colony Improvement recommendation to fire when factories are well
  below cap, not just near cap
- Add comprehensive tests for all new logic paths
2026-08-14 10:55:38 -06:00
Brian Fertig 5ce7fc2367 feat(mastervega): contact-gate relationsRows and expand alert suppression to tech
- relationsRows now filters out empires the human hasn't contacted, matching
  the existing contact-gating behavior of rankingRows (Brian, 2026-08-14)
- Expand GNN alert suppression from espionage-only to include tech breakthroughs
  via new ALERT_STORY_KINDS set, skipping ranking/relations pages for these
  one-off notifications
- Update verifyMasterOfVega tests to assert uncontacted empires are excluded
  from relationsRows while confirming names can still appear in contacted
  rows' war/trade/ally lists
2026-08-14 09:52:57 -06:00
Brian Fertig c84b668553 feat(mastervega): add allocation icons and tooltips to colony sliders
- 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
2026-08-14 09:52:36 -06:00
Brian Fertig 44868e5032 feat(mastervega): leader system, bombard cap, GNN contact-gating, population rounding
- 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
2026-08-13 23:14:42 -06:00
Brian Fertig 8f0b079fa4 feat(vega-gnn): suppress ranking/relations pages during espionage alerts
When a fresh espionage notification is pending, skip ranking metrics and
relations pages so the alert reads as a focused notification rather than
being interleaved with unrelated charts. Reopening GNN without pending
events (using history) always shows the full experience, providing an
escape hatch for players who want the charts.
2026-08-13 16:45:53 -06:00
Brian Fertig 57a8a14ade feat(mastervega): add third-party peace requests, pre-battle formation picker, and combat V2 planet fixes
- Add "peace request" diplomacy: player can ask an AI to end a war with a
  third empire, and AIs can ask the player the same. Refusing costs attitude.
  Implemented in VegaDiplomacy.js (wouldAcceptPeaceRequest/requestPeace/offerPeaceRequest),
  VegaAudience.js (Demand Peace button + war picker), and full chat lines for
  all species in VegaChat.js.

- Extract openFormationPicker to VegaScreens.js and wire it into
  MasterOfVegaGame.js so the player chooses a formation before every battle.
  AI opponents still pick silently.

- Fix Combat V2 planet positioning (fixed at worldWidth * 0.75 instead of
  formation-relative), pass typeId for real planet art, and apply the
  Planetary Shield building's shieldBonus (was hardcoded to 0).

- Add icon images to research screen tech field headers.

- Add comprehensive tests for peace requests and prepareBattleAt fixes.
2026-08-13 16:12:10 -06:00
Brian Fertig 590bca1721 feat(master-vega): add Galactic Council Session ceremony UI
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.
2026-08-13 15:16:43 -06:00
Brian Fertig b145beb28d feat(master-vega): add Galactic Council Session ceremony UI
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.
2026-08-13 14:37:27 -06:00
Brian Fertig 0c6c4b8452 feat: add Galactic News Network (GNN) broadcast system
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
2026-08-13 12:03:08 -06:00
Brian Fertig ea70fb4e07 Intro Movie Optimization 2026-08-13 08:43:24 -06:00
Brian Fertig d63d81fb66 visualize focus misalignment and improve research recommendation logic
Highlight colony pills in warm orange-brown when their current focus
(colony or allocation) disagrees with the advisor's recommendation,
mirroring the yellow-outline signal already used in dropdowns.

Refactor recommendAllocationFocus to avoid oscillation: instead of
reading the colony's own slider (which would flip between Default
at 0.20 and Research at 0.50), check for an eligible research
building and population ≥ 3, and include the building name in the
advice message.
2026-08-12 23:28:29 -06:00
Brian Fertig e78f626406 feat(masterofvega): add studio intro video and colony focus misalignment indicators
- 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)
2026-08-12 23:00:18 -06:00
Brian Fertig 72f44178b0 feat(mastervega): add Colonies screen for empire-wide colony management
Introduce VegaColoniesScreen.js, a spreadsheet-style screen that displays
and manages all of the player's colonies at once, grouped by star and
sorted by population. Features include:

- JIT-loaded advisor video panel (one 1:1 muted loop per species, falling
  back to the species portrait when no clip is recorded)
- Retro terminal with typing animation, scanlines, and glitch effects
  that displays advisorColonyReport commentary for the selected colony
- Inline Colony Focus and Allocation Focus pills with dropdown pickers
  showing the advisor's live recommendation outlined in yellow
- Population transfer (arm-and-target idiom matching fleet orders)
- Manage button delegating to the existing single-colony flyout

Refactor VegaColonyView.js to use shared applyColonyFocus and
applyAllocationFocus setters from VegaLogic.js so both the flyout and
inline pills apply identical side effects. Add empireColoniesByStar
grouping helper for the spreadsheet view. Wire a "Colonies" entry into
the Empire dropdown menu in MasterOfVegaGame.js. Add advisorVideos
entries to mastervega-artwork.json with JIT-loading helpers in VegaArt.js.
Update verifyMasterOfVega.js to validate the new assets, lazy-loading
behavior, and all new logic functions.
2026-08-11 20:10:40 -06:00
Brian Fertig f150737004 Button Changes 2026-08-10 23:06:42 -06:00
Brian Fertig 167fdd6e3f refactor: replace scanline with diagonal shimmer and add orbiting border lights to VegaButton
- Replace horizontal scanline sweep with an occasional diagonal shimmer effect
  that crosses the button face at a 22° angle with a 1.5s pause between passes
- Add three white border lights that slowly orbit the button's stroke outline
  (~3.6s per full revolution), drawn above all other layers
- Reduce corner brackets from all four corners to upper-right and lower-left
  only, matching the chamfered panel's 45° cuts
- Extract reusable perimeter utilities (_computePerimeter, _perimeterPoint)
  cached once at construction to avoid per-frame arc-length recomputation
- Wire shimmer and border lights into hover enter/exit and destroy lifecycle
2026-08-10 21:43:34 -06:00
Brian Fertig 4c3b17610a refactor(mastervega): consolidate HUD buttons into Empire dropdown and fix ghost button styling
- Replace four separate HUD buttons (Research, Diplomacy, Council, Leaders)
  with a single "Empire" dropdown button, freeing HUD space for future
  buttons like "Colonies"
- Add toggleEmpireMenu/openEmpireMenu/closeEmpireMenu with a popover panel
  containing the four options, click-outside-to-dismiss, and ▸/▾ indicator
  on the button label
- Fix ghost button glow washout by introducing GHOST_ALPHA (0.85) constant
  and using it instead of hardcoded 0.3 alpha for ghost button backgrounds
- Change ghost button hover text color from glow color to textDark for
  consistent readability
- Remove unused glowHex from SCHEMES config
2026-08-10 21:30:15 -06:00