Flight (js/flight/): tube-mode controller in spline space (s,x,y) — flow-locked forward motion, throttle as a spring-back lean, boost + i-frames, banking chase cam on the parallel-transport frame, arcade wall response (shove + graze damage, never a hard stop). Twin-stick input: WASD/left-stick moves the ship in the disc, mouse/right-stick aims, Shift/Ctrl is throttle. Gamepad supported. Combat (js/combat/): lysozyme cannon (pooled, instanced, heat-limited with hysteresis lockout) + antacid torpedo emitting level:neutralize. Enemy framework with floater/seeker/turret and turn-rate-limited homing darts, spawned from C's level:event. Coat/hull model and the full bus surface E builds against. Measured (deterministic stepper): flow-lock exact (3s at flow 14 -> s=44.0); boost peak 30.8 u/s; heat 4s fire -> 2s lockout; wall slam 13.3 coat at 11.3 u/s with forward speed untouched; 10 combat draws at 55 live enemies (budget <=80); 0.10 ms/frame CPU; 0 leaks over 20 create/dispose cycles. fps NOT claimed — rAF does not run in the automated pane. Evidence: docs/shots/laneB/. Three findings escalated in LANE_B_NOTES: - qa.sh gate #1 is a no-op: node --check silently exits 0 on ESM, so the syntax gate has never checked anything. I shipped a real SyntaxError past a GREEN qa. Fix + verification handed to F. - Surf is structurally broken: the peristalsis wave (13.64 u/s) is slower than the player (19.6 u/s), so level 2's signature mechanic loses to mashing throttle. Not tunable from this lane; escalated to A/F with options. - Custom ShaderMaterials need #include <colorspace_fragment>, else ART_BIBLE's hostile amber reaches the display as rgb(255,26,6). Fixed here; stub/walls inherit it. js/flight/dev.html is a dev harness (boot.js has no player wiring yet); it retires once F pastes the snippet in LANE_B_NOTES. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
60 lines
3.0 KiB
JavaScript
60 lines
3.0 KiB
JavaScript
// combat/balance.js (Lane B) — every combat number. Sibling of flight/tuning.js: that file
|
||
// decides how ENDO-1 handles, this one decides what the fight is worth.
|
||
//
|
||
// Sized against the stub esophagus (flow 14 u/s, playable disc radius ~7..10 u) and against
|
||
// the player's own numbers: disc top speed 13 u/s, coat 100 with 8/s regen after 2.5 s.
|
||
|
||
export const BALANCE = {
|
||
// Lysozyme cannon: infinite ammo, heat-limited (GDD). Heat is the whole design — the gun
|
||
// is free, so the cost has to be time. Sustained fire nets +25 heat/s (11 shots/s × 5.5,
|
||
// less 30/s cooling) => ~4 s of held fire before lockout, then ~2 s to recover to resumeAt.
|
||
// Burst and you never see the meter; hold and you're disarmed exactly when it's busiest.
|
||
cannon: {
|
||
rof: 11, // shots/s
|
||
speed: 95, // u/s in world space (closing speed ~75 with player flow)
|
||
life: 1.15, // s => ~109 u range, comfortably past the fog
|
||
damage: 12,
|
||
radius: 0.35,
|
||
heatPerShot: 5.5,
|
||
coolRate: 30, // /s
|
||
overheatAt: 100,
|
||
resumeAt: 40, // hysteresis — no stutter-firing on the edge of lockout
|
||
spread: 0.004, // rad, seeded — a hair of life, not a handicap
|
||
pool: 96, // rof × life = ~13 in flight; 96 covers spikes with room
|
||
},
|
||
|
||
// Antacid torpedo: the dual-use secondary (GDD). Also neutralizes an acid zone for ~10 s
|
||
// via the level:neutralize bus event — A/C consume it. Ammo-limited, pickup-fed (round 2).
|
||
torpedo: {
|
||
rof: 0.8, speed: 42, life: 3.2, damage: 45, splash: 9, radius: 0.7,
|
||
ammo: 6, ammoMax: 6,
|
||
neutralizeRadius: 14, neutralizeDuration: 10,
|
||
pool: 8,
|
||
},
|
||
|
||
enemies: {
|
||
// amylase droplet — slow floater with a corrosive contact aura. A soft obstacle: it
|
||
// doesn't chase, it taxes the lane it sits in. Aura ticks discretely (see enemies.js).
|
||
floater: { hp: 24, radius: 2.2, score: 100, drift: 1.6, bob: 0.5,
|
||
auraRadius: 4.2, auraDps: 18, auraTick: 0.2, pool: 24 },
|
||
|
||
// pepsin — small fast seeker, dissolves on contact. Chases in spline space (s,x,y), so
|
||
// a pursuit costs three floats. speed 19 > player flow 14: it WILL catch you from
|
||
// behind, and the answer is to shoot it or boost, not to outrun it at throttle 1.4.
|
||
seeker: { hp: 14, radius: 1.0, score: 150, speed: 19, turn: 2.4, contact: 16,
|
||
aggroS: 60, pool: 32 },
|
||
|
||
// antibody turret (Peyer's patch) — wall-mounted, fires homing darts. Dart turn radius
|
||
// is speed/turn = 24/1.8 = 13.3 u, wider than the tube itself: it can never corner you,
|
||
// only punish a straight line. Dodgeable by design (charter).
|
||
turret: { hp: 40, radius: 1.6, score: 250, fireEvery: 1.9, rangeS: 55,
|
||
dartSpeed: 24, dartTurn: 1.8, dartLife: 4.5, dartDamage: 14, pool: 12 },
|
||
},
|
||
|
||
darts: { pool: 48, radius: 0.45 },
|
||
|
||
// Chained kills feed the combo meter (GDD: score × style multiplier; E's music layer
|
||
// listens). Window is generous enough to cross a fold, tight enough to mean something.
|
||
combo: { window: 2.5 },
|
||
};
|