guts/web/js/flight/tuning.js
type-two 87a4803bde [lane A+B+C] L3 Stomach: the acid sea, and pH as a resource you can see
The last skeleton. L3 has been 4 events since round 1, waiting (in its own status field) on
"the pH field" and a boss framework; both exist now, so the level is authored: 46 events,
2500 units, the sea, and the Guardian at the end of it.

THE PH MECHANIC, finally load-bearing. Lane A built an acid plane in round 2 and left two
hooks on it — depthAt() labelled "B:" and set() labelled "C's event pump drives this" — and
nothing had ever called either. Now:
  - player.js scales the biome's ambient coat drain by SUBMERSION. Stomach 2.2/s x5 = 11/s
    under the surface (measured: 8/s net of regen, and regen is off for 2.5s after any hit,
    so it is brutal mid-fight); x0.15 above it, which is effectively safe air.
  - a new `acid` level event names a target height and boot eases the sea toward it in step(),
    so a RISING TIDE is a beat C can author. L3 uses two: -14 -> -6 mid-sea, then -6 -> +2 in
    the antrum, where the surface goes ABOVE the centreline and the safe lane simply stops
    existing. Measured: the identical spot (y -5) goes from 0/s to 9.67/s across that tide.
This is the GDD's "mucus shallows are safe lanes" expressed as DEPTH rather than wall-hugging,
which is better on two counts: it reads instantly (you can SEE the surface) and it makes the
vertical axis matter in the one level that is a room. Every collectible worth having is under it.

Gated on the sea's s-span, not on depthAt alone — depthAt returns a bare -1 outside the span
and that is indistinguishable from "1 unit above the surface", so reading it naively would have
quietly scaled ambient drain on every level in the game. Caught before it shipped.

Level: cardia (still teal, so the fundus can REVEAL the sea) -> fundus (the teaching room:
huge, low tide, nothing kills you fast) -> body (the sea proper, tide rises while you are in
it) -> antrum (no safe air left, only speed) -> pyloric antrum (the Guardian). H. pylori is
taught alone in the dome and tested in a rising sea; pepsin swarms scale 3 -> 6; bezoar_chunk
is a new catalogue row for the stomach's traffic.

L3 has NO commensals and no biofilm gate, which is anatomically exact — acid sterilises, which
is why H. pylori is famous for surviving it. So BIOME STANDING goes quiet for nine minutes and
comes back in L4, which makes L4's colonies read as relief rather than furniture.

C's sim: par 540s vs par-pace 555s ("requires pushing above par-pace"), pressure
3.75/1.50/2.44/2.16, min clearance 7.15 vs the 2.5 law, all 21 checkpoint gaps under 30s.
par.score corrected 9000 -> 5500, because 9000 was above everything the level can actually pay.

Deferred, and said out loud rather than quietly dropped: churn cyclones. A vortex that flings
the player is a FORCE and no hazard in the tree applies one; it wants the same A/B work as the
Guardian's arena churn and should land with it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 00:26:31 +10:00

147 lines
8.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// flight/tuning.js (Lane B) — THE FEEL. Every number that decides how GUTS handles lives
// here and nowhere else. Tuned by hand on the stub esophagus; re-tune per biome later.
//
// Reference frame these are sized against — CORRECTED round 2 (C caught the stale numbers,
// LANE_C_NOTES §→ Lane B #4). The round-1 header quoted the round-0 stub; A's real world has
// since measured the esophagus wave at amp 1.4 (not 0.9) + breathe 0.15, and `wallRho`
// subtracts BOTH plus SKIN:
// biome.flow = 14 u/s · radius 10 ±15% wobble => 8.50 .. 11.50
// wallRho = radius (amp 1.4 + breathe 0.15) SKIN 0.6 => 6.35 .. 9.35 playable disc
// minus ship.radius 0.9 => 5.45 .. 8.45 free disc
// The envelope shrank ~0.65 u under us. disc.maxSpeed/accel and the graze numbers were sized
// against the old 7.0..10.0 and still read fine at 6.35..9.35, but that is luck, not design —
// if A retunes the wave again, re-check `disc` and `wall` here, not just C's clearances.
//
// SURF: FIXED THIS ROUND — it is a ride now, not a shove.
// Round 1 measured the mechanic as strictly dominated: a crest travelling at flow (13.64 u/s)
// cannot carry anything faster than itself, while throttle-mashing gave 19.6 u/s, so the
// correct play was to ignore the level's signature mechanic. Tuning could not fix it (the
// crest window is fixed in SPACE, so a bigger bonus just ejected you sooner — measured ~3.0
// units gained per crest at gain 0.4, 0.75 AND 1.2, identical).
//
// F's round-2 ruling #1 fixed it at the source: `crestSpeed = CREST_FACTOR(1.6) × flow`, which
// beats throttleMax 1.4. So the wave now outruns the player and B **speed-locks to
// world.crestSpeed(s)** while riding instead of adding a flat bonus. Riding at flow 14 =
// 22.4 u/s vs 19.6 for mashing: +14%, and because you match the crest's own speed you STAY on
// it instead of being thrown off the front. Throttle still decides how long you hold it —
// see surf.authority. Read the crest, don't hold W.
export const TUNING = {
ship: {
radius: 0.9, // collision sphere (hull reads ~1.9 long, 1.2 wide)
},
// --- forward motion along s -------------------------------------------------------
flow: {
throttleMin: 0.6, // GDD: throttle is ±40% of biome flow, never a full stop
throttleMax: 1.4,
throttleRate: 1.8, // throttle units/s while held (0.6 -> 1.4 in ~0.45 s)
throttleReturn: 0.9, // /s spring back to neutral 1.0 when hands off
},
boost: {
gain: 1.2, // +120% of biome flow (GDD)
duration: 0.55, // s of burst
cooldown: 2.4, // s from spend until available again
iframes: 0.35, // s invulnerable "at spend" (GDD) — shorter than the burst,
// so boosting *through* something is a read, not a get-out
fovKick: 13, // degrees of extra FOV at full burst (speed you feel)
},
surf: {
threshold: 0.45, // world.flowPulse(s,t) above this = on the crest.
// pulse=pow(sin,3) so 0.45 => sin>0.766 => the peak 22% of each
// wave. Under CREST 1.6 the wavelength grew to ~45.7 u at flow
// 14, so that window is now ~10 u long (was ~6.3) — the crest is
// a wider, faster lane than it was in round 1.
authority: 0.85, // how completely the crest owns your speed while riding, 0..1.
// THE knob. At 1.0 the wave takes you at exactly crestSpeed and
// throttle stops mattering while surfing — you'd ride forever
// and the mechanic would have no skill floor. At 0.85 you sit
// just under the crest and drift off the back at a rate YOU set:
// throttle 1.4 -> 21.98 vs crest 22.4 => drift 0.42 u/s, ~12 s ride
// throttle 1.0 -> 21.14 => drift 1.26 u/s, ~4 s ride
// throttle 0.6 -> 20.30 => drift 2.10 u/s, ~2 s ride
// So catching a crest is positioning; HOLDING one is throttle
// discipline. Never applied when it would slow you (boosting
// past the crest keeps your speed — see player.js).
ramp: 3.0, // /s blend in/out so cresting doesn't pop
},
// --- movement inside the cross-section disc ---------------------------------------
disc: {
accel: 78, // u/s²
maxSpeed: 13, // u/s — crosses the ~16 u tube in ~1.2 s: dodgeable, not twitchy
damping: 6.5, // /s exponential drag => coasts to rest in ~0.3 s
},
// --- arena / 6DOF: in a room, the anatomy stops carrying you -----------------------
// GDD: "the same controller unlocked to free 6DOF, Descent-style, no gravity. Slower,
// spatial, exploratory." The felt difference is NOT extra axes — spline space already spans
// a room (s is the axial one, x/y are the cross-section) — it is that YOU own the forward
// axis. You can stop. You can reverse. Nothing is shoving you at the boss.
arena: {
thrust: 44, // u/s² axial. Softer than disc accel 78: a room is read, not strafed
maxSpeed: 11, // u/s — under the esophagus's 12-20 flow on purpose (GDD: "slower")
damping: 2.2, // /s — a long coast (no gravity), but it does come to rest
},
// --- aim: the reticle leads, the ship follows (Star Fox lag) -----------------------
aim: {
distance: 26, // u ahead (in s) that the reticle plane floats
sensitivity: 0.022, // disc units per pixel of mouse movement
padSpeed: 20, // u/s at full right-stick deflection
range: 9, // max |aim| from the centreline (≈ the widest wallRho)
recenter: 0.8, // /s drift back to centre when hands off
lag: 9, // /s spring — the ship's nose chases the reticle, never snaps
},
// --- attitude: bank into lateral motion -------------------------------------------
bank: {
gain: 0.055, // rad of roll per u/s of lateral disc velocity
max: 0.75, // rad (~43°)
rate: 7, // /s spring toward target roll
pitchGain: 0.03, // rad of pitch per u/s of vertical disc velocity
},
// --- chase camera ------------------------------------------------------------------
cam: {
back: 7.2, // u behind the ship (along tan, measured in s)
up: 1.4, // u along the frame normal — ship sits low-centre
lookAhead: 16, // u ahead of the ship for the look target
discLag: 8.0, // /s spring on the camera's own disc offset
discFollow: 0.82, // camera tracks only 82% of the ship's offset, so hard dodges
// visibly move the ship within the frame instead of gluing it
aimInfluence: 0.35, // how much the look target drifts toward the reticle
fov: 75, // matches boot.js's camera so wiring in changes nothing
fovRate: 4.5, // /s toward target fov
},
// --- durability (GDD: regenerating mucus coat over a pickup-only hull) -------------
coat: {
max: 100,
regen: 8, // /s
regenDelay: 2.5, // s after the last damage before regen resumes
// ambient drain is the biome's: world.biomeAt(s).coatDrain (esophagus = 0.5/s)
//
// --- the pH mechanic (L3) ---------------------------------------------------------
// On a level with an acid sea (`level.acid`), the biome's drain is scaled by WHETHER YOU
// ARE IN IT — world.acid.depthAt(pos) > 0 means submerged. This is the GDD's "pH as
// environmental damage; mucus shallows are safe lanes", and it makes L3's promise literal:
// position is the resource. Against the 8/s regen, stomach 2.2 x 5 = 11/s bleeds even at
// rest and is punishing mid-fight (regen is off for 2.5s after any hit); above the surface
// 2.2 x 0.15 = 0.33/s is effectively safe air. A level with no acid plane is untouched.
acidMult: 5.0,
surfaceMult: 0.15,
},
hull: { max: 100 },
// --- wall contact: arcade. Shove + graze damage, NEVER a hard stop -----------------
wall: {
restitution: 0.35, // fraction of inward velocity returned on contact
grazeFloor: 3.0, // impact u/s below this is free — you can lean on the wall
damagePerSpeed: 1.6, // coat damage per u/s of impact above grazeFloor
maxHit: 28, // cap: a full-speed slam is a mistake, not a death
shoveOut: 1.0, // extra u/s pushed off the wall
cooldown: 0.25, // s between wall damage ticks (scraping ≠ machine-gun damage)
},
};