Both frozen files live inside the versioned install and neither ships in the
zip -- environ.ini is generated on first run, glass_layout.cfg is ours. So
Nick extracting the next build would get a cab that comes up wrong with no
error anywhere, which is exactly the failure the freeze was supposed to end.
Masters now live at the stable C:\bt411\ (podprofile.ini, glass_layout.cfg,
podkit.ps1). setup_pod.bat pushes them into the newest BT411_* folder -- run
once per extract. runpod.bat resolves the newest install and applies the kit
itself, so the remote launch path needs no per-build edit. Re-tuning means
editing the MASTER: the apply overwrites the install's copy on purpose, so a
moved panel has one place to look.
Also records, for playtesting on the cab: all five tester launchers set no pod
key at all, so each inherits the rig from environ.ini without knowing the pod
exists -- verified by running play_solo.bat on the cart (7 settings applied,
not 9, because the bat sets BT_PLATFORM and BT_START_INSIDE itself and the
real environment wins). That is the case against a separate pod-only ini: a
second file would need every launcher to opt in.
Verified: kit re-applies idempotently, and the rewritten runpod.bat brings the
cab up correct -- 9 settings, GLASS, -fit borderless, all three surfaces on
their intended displays.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rw7No5wLTpkaUgA3ANbtZZ
BT_GLASS is a compile-time #ifdef; getenv("BT_GLASS") appears nowhere in the
tree. The line rode along from the bring-up launcher into the frozen profile
and into the pod-hardware runbook, reading like the switch that turns the
glass path on. It never did anything -- the rig worked because glass is the
DEFAULT profile when nothing is set.
Replaced with BT_PLATFORM=glass (the real spelling, so the cart does not lean
on that default) and noted why NOT BT_PLATFORM=pod: the pod profile selects
the 1995 multi-surface gauge path, which needs the NVIDIA horizontal span no
modern driver has. Behaviourally identical -- both land gBTPlatformGlass=1.
Re-verified on the cart: 9 settings applied, GLASS profile, -fit borderless,
all three surfaces on their intended displays.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rw7No5wLTpkaUgA3ANbtZZ
The cart's display config was carried by a launcher .bat, so it only came up
right if the game was started one particular way. Move it into the file the
engine already reads before anything touches the environment.
content/environ.ini <- scratchpad/pod/podprofile.ini, merged idempotently
between markers by scratchpad/pod/mergeprofile.ps1
Two gates were missing for that to be enough:
BT_FIT=1 the env spelling of -fit, so the borderless main view does not
depend on one launcher's command line (shortcut, scheduled
task and autostart all have to produce the same rig)
L4PLASMA= NONE / OFF / 0 -> no marquee at all. Leaving it unset does
NOT work: the GLASS profile force-defaults it to SCREEN, which
drops a desktop plasma window on the cab's glass. The boot
banner now reports the live state instead of always claiming
"plasma window".
Also lands the bring-up engine work this depended on: monitor:<name|index>
layout binding (device-bound, not pixel-bound -- desktop rects move when a
display re-enumerates), ",bare" implying frameless, rotation-aware radar
surface sizing, BT_GAUGE_SEC_ROT accepting 0-3 (it silently forced 3 for
anything but 1), 180-degree ExpandPlaneToBGRA, and the BT_POD_CHANMAP /
BT_POD_IDENT / BT_POD_CHANTEST identification gates.
Verified on the cart, build 4.11.813, launcher carrying none of it:
[boot] environ.ini: 9 setting(s) applied
[boot] platform profile: GLASS (PadRIO; plasma off [L4PLASMA])
[cockpit] -fit: borderless 800x600
[glasswin] radar rotation 0 (none)
... all three surfaces on their intended \.\DISPLAYn
No [plasmawin] line in an otherwise-logging run = the ctor never ran.
KB: pod-hardware.md gains the ALPHA-MR section (mapping, the two wiring
deviations, the frozen profile, the session-0 remote-work traps) and its RGB
SPLIT "OPEN: which way is the cart wired" is now SETTLED -- it is splitter
wired, the composite is what lit it. glass-cockpit.md documents monitor:
binding, BT_FIT and L4PLASMA=NONE.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rw7No5wLTpkaUgA3ANbtZZ
Implements what the pod actually does (pod-hardware.md THE RGB SPLIT): a VGA
port's R/G/B lines each drive a separate mono MFD monitor, so a window is not
one MFD -- it is one PORT carrying up to three. BT_POD_RGB=1 collapses the
five MFD windows into the two ports the cab drives (Port A: Comm=red,
Mfd2=green, Heat=blue; Port B: Mfd1=red, Mfd3=green) and composites each
group's planes into the colour channels, leaving the radar on its own
full-colour port. Channel comes from the live port (GetEnableID), never a
hardcoded table, so an Eng-page swap follows automatically; BlankColor planes
contribute nothing, exactly as on the pod. Implies BT_POD_SURFACES (bare
640x480 pictures -- the cab's buttons are physical).
Verified locally (bare windows, "RGB COMPOSITE of 2 plane(s): Comm Mfd2") and
LIVE ON NICK'S CRASH CART over the tailnet: Port A -> DISPLAY4, Port B ->
DISPLAY2, radar -> DISPLAY1, all exact-fit. Pod scratch kit included (ssh
helper, layout cfgs for both modes, launcher; the mission-egg launcher fix --
a bare MP.EGG exits the mission loop with no relay, and BT_FE_SOLO parks at
the menu, so neither lights the panels).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Answering 'how do the panels split RGB into 3 monitors' from primary sources
rather than inference:
- content/GAUGE/L4GAUGE.CFG (the authentic 1996 pod config) configures each
gauge port with a bit-plane mask AND A COLOUR CHANNEL: Comm=red,
Mfd2=green, Heat=blue on clut2 (the upper row); Mfd1=red, Mfd3=green on
clut1 (the lower row, blue spare); sec/radar = full rgb, rotation 270 (the
portrait CRT). Eng1/2/3 are the engineering-page twins on the same
monitors, swapped in/out via reconfigure() with 'blank'.
- L4GraphicsPort::BuildSecondaryColor (L4VB16.cpp) proves the mechanism at
T0: it walks the palette entries owned by the port's bit group and writes
exactly ONE component (RedChannel->Red, GreenChannel->Green,
BlueChannel->Blue, AllChannels->whole triplet); BlankColor blanks the
group. So one palettized framebuffer emits three independent pictures on
the R/G/B analog lines, and the splitter feeds each line to its own mono
monitor -- which is also what the '1280x480 horizontally spanned' MFD
surface actually is: two VGA outputs x three channels.
Port consequence recorded: the per-panel window path (BT_POD_SURFACES) is
right for per-panel outputs but WRONG for splitter-wired glass, which needs a
channel-composite mode (three planes -> one RGB image, pure primary tints).
ExpandPlaneToBGRA already does the per-plane half. Open: how Nick's cart is
actually wired. Also lands the pod bring-up scratch (ssh helper, layout cfg,
launcher, firestorm repo browser).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The WIP's 'pose does not hold' was a chain of bench-instrument errors, not a
code bug: every capture ran in COCKPIT view (the pilot cannot see their own
legs; the eye-height residual masked as reversion). Joint probes prove the
park holds indefinitely (knee 1.138, root -2.219 steady); the 2-node bench
shows the observer's replicant fully crouched and held (duckmpA_031 -- the
type-3 state record carries it with zero new replication code); the second
scripted press (new BT_BTNTEST2 env) verifies RISE -> standing zeros.
MP button delivery confirmed mode-mask-clean (the one miss was round-start
jitter). Diags added, all BT_DUCK_LOG-gated: SetLegAnimation re-arm tracer,
1 Hz joint probe, RIO press mode-mask, BT_TREE_LOG topology dump, and the
squat-park log. RESIDUAL filed: pilot's own cockpit eye does not ride the
root drop (DPLEyeRenderable chain composition; cosmetic).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The subsystem (sim/toggle/attribute/replication) was already complete; this
lands the missing VISUALS, decoded from MakeMechRenderables @004cef28 case
0xbd8 (raw pseudocode part_014):
- COCKPIT: the 1995 searchlight is a FOG SWAP -- the @00456778/@00456814
watcher switches DPLRenderer::SetFogStyle between the authored fog= (lit)
and nosearchlightfog= (dark) sets per map/time page in BTDPL.INI. The
engine kept the whole system under its real names; completed the stubbed
plane application (currentFogNear/Far) and transcribed the watcher (with
its inverted-cache seed) into TickSearchlight. CONSEQUENCE: night now
STARTS on the authentic dark set (near-plane 5u on arena pages) -- our
builds had rendered the searchlight-ON fog permanently.
- EXTERNAL: spot.bgf beam cone hung on the searchlight SITE joint, shown/
hidden from the replicated LightOn attribute (@0045612c watcher). Site
segments now build geometry-less DCS children (posed + parentable, as the
1995 graph did) -- previously they were skipped entirely.
- searchlight.hpp: commandedOn @0x1DC identified as mountSegment (resource
segmentIndex; the cone's mount joint).
Benches: searchfog.sh (solo cockpit: first-tick dark sync, F5/0x14 press ->
SetFogStyle(2), red-fog probe end-to-end), spotcone.sh (2-node: B's button ->
lightState replication -> A logs "[spot] cone SHOWN (seg 20)"). Cone look
(size/aim on the mount) pending an eyeball pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reconstructs the dark-gap tail of Mech::TakeDamageMessageHandler
(@0x4a02f4-0x4a0890, raw disasm): the three id-0x16 score reports (kill to
the shooter's player / type-0 wire-fidelity / received to the victim's
player) and the BT 0x38-byte VehicleDeadMessage extension {killed-by player,
kill zone} dispatched from the death tail. Retires BTPostDamageScore /
BTPostKillScore and the per-hit inflicted credit (never existed in 1995:
@0x4c0200 is bound in no handler-table entry -- byte-scan receipt in
decomp-reference). Suicides now dispatch and the handler negates the award
(the #134 panic penalty). Collision divert falls through to the death tail
per @0x4a0375 (wall deaths respawn + blast; no score). ScoreMessage fields
renamed to decoded truth (vitalHit/zoneIndex/subsysID) + wire asserts;
console VTVDamaged points_transfered corrected (Round(award), not Now()).
Benches: scorekill.sh cross-node kill (kills=1 award=4.88, killedBy=2:1
zone=3, single death cycle), scoreself.sh suicide (type=2 award=-39.00
kills=0), deathblast2.sh re-verified (72 bursts at ~9u).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The missing half of Advanced Damage, found by call-scanning
Explosion::SplashDamage @0042fad0: TWO callers, not one -- Missile::Perform
(the known #62 path) and 0x4a0bda, the UN-EXPORTED tail of
Mech::TakeDamageMessageHandler itself. Raw disasm @0x4a07b8-0x4a0bda:
when the victim ENTERS dead(9)/eject(10) during the applications, the
binary sets the wreck burning (id 0x17, deferred -- handler not yet
reconstructed), spawns the death Explosion (model 0x31 -- our death-list
visuals stand in), and SPLASHES:
gates : owning player's advancedDamageOn (+0x264) AND NOT
suppressConsole (+0x258 -- eject sets it: PUNCH-OUTS NEVER
BLAST, the authentic anti-suicide-bomb rule)
damage: type 2 Explosive, amount = deathSplashDamage (mech+0x520),
bursts = round(0.001 * moverMass * 15.0) -- scales with tonnage
radius: deathSplashRadius (mech+0x524); per-victim falloff
bursts/dist^1.25 in the shared core
Draco's collision-divert suspicion is settled: the blast is TYPE 2, the
divert never touched it -- the tail was simply never reconstructed.
Port: deathSplashDamage/Radius PROMOTED from the Wword scratch bank to
named Mech members (the bank is one GLOBAL array -- authored per-chassis
values were clobbered to the last-loaded mech); BTSplashCore split out of
the #62 weapon splash and shared; BTApplyDeathSplash + the death-edge arm
in the handler tail; BTPlayerConsoleSuppressed bridge (friend).
Bench (2-node, B parked 8.9u from a self-destructing A): blast fired with
authored madcat data (radius=50, amount=5, mass=75000 -> 1125 base
bursts), B took 73 bursts (falloff exact: 1125/8.91^1.25), cross-pod
delivery + cylinder spray verified on B's own log ([dmghit] type=2
burst=73 across zones). ~365 damage at 9u -- Draco's 'double kills on
drops' economy restored.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Provocations run under the verified [skate] detector: sustained healthy
walking, 7x respawn-while-moving, gimp onset at speed, ~21s of sustained
GIMPED walking (aimed-leg self-damage: BT_SELF_DAMAGE_ZONE=dz_ldleg),
leg-destruction death (authentic: lvl 1.0 -> leg gone -> fall/death; the
mid-session "died of the gimp edge" reading was a capped-print artifact,
retracted), and respawn. ZERO skate anywhere. Peer gimp replication
VERIFIED live: observer reads gl=3 + sim=3 with the gimp bodyStates
cycling for the whole master limp window (#82 remains fixed). Conclusion:
the field skating does not reproduce at lab scale; the detector + SKATE
matchlog record ship with the next cut and the field names the failing
case. Bench scripts archived (skatebench3-7; 7 is the clean-room one --
the sed-derived chains dropped envs twice).
Also: BT_LAMP_LOG=1 joins the field bats (#135 -- lamp/annunciator edge
forensics; near-zero noise, answers leak-no-flash reports in one grep).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The night-12 field logs eliminated record starvation (zero [ghost] during
three observed skating windows), so the bug lives in gait APPLICATION on
peers. This adds the [skate] detector to the death-handler tick: a
replicant moving >0.08 u/frame for 90+ frames with BOTH animation
channels idle (legCycleSpeed + bodyCycleSpeed ~ 0) logs one line per
episode + a SKATE matchlog record carrying the discriminating inputs
(legCyc/bodyCyc/cmdSpd/destroyed/mode).
Honest history: the first build keyed on legCycleSpeed alone and
false-fired on every healthy movement phase -- the current peer
architecture poses joints from the BODY channel (s_peerLegCh=0,
AdvanceBodyAnimation mj=1), so legCycleSpeed==0 is NORMAL there. Caught
same-session by the [gimpfeed] silence (AdvanceLegAnimation never runs
on peers); corrected to channel-agnostic before anything shipped.
Bench (skatebench2.sh, 2-node, autodrive walker + kill every ~40s):
7 death/respawn cycles, ZERO skate hits either side -- no false fires,
and light local conditions do NOT reproduce the field skating. Next
provocations: leg-GIMPED walker (the #82 family transition) and 6-player
load; otherwise the detector rides the next cut and the field names the
failing case for us.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Night-12 field report (Ronin/Conn Man/Oracle, blackhawk-correlated): lock
ring lit with the reticle visibly off the mech + no-reg complaints. Root
cause: TWO port stand-ins answered where the 1995 card (which cast against
the DRAWN geometry) would miss -- the pick's any-object sphere fallback and
the caller's whole-mech AABB fallback. The regime that exposes them: a
LEVEL boresight over a SHORT mech -- the blackhawk's mesh tops out below
eye-ray height, so the ray clears every triangle but pierces the fat cull
spheres; the ring lights with the reticle above the mech's head (the
operator watched exactly this on the sweep bench). Careful aimed-down fire
rides triangles, which is why Oracle's per-panel audit passed on the same
build.
Fix: MechSegmentPick returns 1=drawn-geometry hit / 0=TRUE MISS / -1=no
render tree; the sphere may answer ONLY for a mesh the reader cannot parse
(pm==0 -- currently none exist: counters objs/invFail/noTri all clean);
the AABB survives ONLY as the pre-tree replicant grace. A readable mesh
the ray misses is a MISS -- no lock.
Verified (2-node vs bhk1 at 100u, all runs on force-relinked string-
verified exes after today's stale-link flake):
- LEVEL lock-sweep: 0 locks all run (pre-fix: lock band from 168 sphere
answers; picksrc tri=0 sphereFB=168).
- DOWN-PITCHED sweep: locks return 100%% tri-sourced (tri=158 sphereFB=0),
landing on real parts (rarm/ldleg/rdleg) with honest gaps.
- Full zone-walk matrix: tri=18874 sphereFB=0 box=0; victim took 156 hits
across 16 zones incl. both side torsos -- combat un-regressed.
New instruments (all env-gated): BT_LOCK_SWEEP=<axis> torso pan (the
operator-visible lock-envelope bench), [locksweep] transition log,
BT_LOCK_ENVELOPE synthetic unit-sweep probe, [picksrc]/[pickbox] source
telemetry with objs/invFail/noTri localization counters.
Bench: scratchpad/night12/zonewalk_bhk.sh.
NOTE for the field: locking is now strictly TIGHTER (ring = reticle truly
on the machine). If era testers feel the pods were more forgiving,
Draco's "slight lock linger" memory becomes a deliberate investigation
(sourced hysteresis), not an accidental sphere halo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 08-03 zone rule (struck SEGMENT's SKL dzone, ALWAYS -> every aimed
torso hit = center torso) was wrong, and era players' pushback caught it.
Byte-level proof: MAD_TOR.BGF zone-tags the hull PER PANEL (dz_utorso x36,
dz_ltorso/rtorso x18, dz_dtorso x16, all four rear panels, searchlight);
the dpl hit result kept GEOGROUP granularity (dplHitGeoGroup, T0); and the
binary's segment->zone map @49db20 has NO runtime caller (raw call-scan:
sole caller = CreateStreamedDamageZone, load time) -- no segment-level
collapse mechanism exists. Oracle's night-10 'only LCT gets hits' audit
was the BUG's fingerprint, not the pod's design.
Fix: MechSegmentPick attributes the struck triangle to its draw op (index
range) and takes the op's .DZM-bound zone -- the #87 armour-darkening
bindings, the same authored patch->zone mapping that already paints the
panels -- with the segment dzone as the untagged fallback. ZoneAimPoint
now aims hull zones at their patch CENTROIDS (all hull zones previously
shared the chest cull-center), which also upgrades the zone walker.
Bench (2-node zone-walk vs spinning madcat, zonewalk_madcat.sh): every
hull panel resolves individually -- utorso 11/12 in-zone, no L/R
mirroring, all four rear panels register; misses are the panel facing the
shooter mid-spin (correct geometry, not misattribution). Victim applied
254 hits spread across every panel family. Was 102/102 hull aims ->
dtorso before the fix.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Operator reports audited vs the binary (full matrix in RESPAWN_REARM_PLAN
addendum):
- VALVES (real gap): Condenser reset @004ae534 was missing from the decomp
export -- raw disasm shows it chains HEATSINK (coolant refill runs; the
old body chained HeatableSubsystem per the stale TCP shard) then, respawn-
side, resets valveState to detent 1 and restores massScale from
refrigerationFactor. Mech::Reset now also runs the binary's tail call
(@0049f788 BTRecomputeCondenserValves) so flow fractions rebuild from the
reset detents. Bench: detent 5 -> death -> "[respawn] Condenser1 valve
detent 5 -> 1".
- #129 SMOKE (real gap, peers-only): the replicant un-wreck edge rebuilt
the model without the @004d0c14 per-entity effect cleanup, so the
observer's last 10s wreck-plume window rode the teleport onto the fresh
mech. BTStopEntityPfx now runs on the edge; bench shows no plume line
after any un-wreck until the next death.
- AUTHENTIC (no fix): weapon->generator taps persist (@004b0e6c only
resolves the link) and MFD display/control modes persist (mapper vtables
0050f45c/0051e440 slots 8-11 = plain root bodies, read from the exe).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The frame-adapter's inferred twist-sign flip (SelectSlice theta -= twist,
vs the binary's += pre-reflection) was the last unverified half of #124 --
every earlier probe ran at twist 0. Bench: stationary madcat target with
the torso PINNED at 0 / +140 / -140 deg, LRM salvos from a fixed shooter
(missiles = the authentic cylinder path; the binary DROPPED zone -1 beam
damage). Result: slice picks track the physically-facing flank in BOTH
directions (twist-left -> right-family zones for left-flank impacts,
twist-right -> left-family), deterministic, wrong-sign outcome (slice 7
vs observed slice 1) clearly excluded. No game-code change needed.
Instrumentation added (all env-gated):
- torso.cpp BT_FORCE_TWIST=<-1..1>: HOLD the sim's analogTwistAxis (the
input-level pin was dead -- live input rides the CONTROLS.MAP device
push, and Basic mode auto-centers; sim-level is plumbing-independent).
- dmgtable.cpp [slice] line: rot flag, live twist, thetaIn/thetaAdj,
chosen slice -- the weighted leaf roll made zone-only logs ambiguous.
- [dmgresolve] now names the zone (BTMechZoneSegAndName).
- mech4.cpp BT_FORCE_TWIST input pin + one-shot mode cycle (kept as doc
of the dead path), mechmppr [mppr] mode probe.
- scratchpad/night11/twistsign.sh: the 3-config bench.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The absolute-pointer scan missed the E8-relative call; the later byte-scan
found it (FUN_004a9b5c+0x10 -- the master performance evaluates eject
permission per frame in the shipped binary). Under deadline pressure the
disproven 'unfinished/dead code' claim leaked back into three comments and
the handoff; swept per the correction mandate.
Settled press model, now stated correctly everywhere: pilot eject = the
pilot KEYPAD bank while armed (+ the PANIC key reporting through that
matrix). The MFD soft keys NEVER pilot-eject in the binary -- every page
routes them to authored functions; the flashing engEject cell is the
INVITE LAMP. The port's page-gated eng-key eject is a MARKED CONVENIENCE
deviation (operator-requested), and the coolant hysteresis is a MARKED
smoothing deviation for a degenerate boundary oscillation -- not
completions of unfinished code.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Re-read the material damage watcher RAW (@004573e4 ctor / @00457784
change-push): 16 floats snapshotted, damaged = pristine x 0.1 (literal at
the MakeMechRenderables call site, watching zone+0x158), linear lerp, 13
floats written back, then FUN_0048d4d4 -- which is "flush_material": a dpl
command-stream marshal (opcode 100) to the i860 division card. The
material->ramp->texel response curve was CARD firmware and is not in
BTL4OPT.EXE; logged as an open question (ask: firmware/DIV docs/period
screenshots).
Field reconciliation, measured live: one 25-pt hit (ERLG class) snaps a
77-pt arm 0 -> 0.3247 in a frame -- "a single missile leaves visible
armor damage" holds under the linear curve for heavy hits; 2-pt ERS creep
(the leg-audit weapon) is the invisible case.
Bench additions: BT_WALK_ZONES=<name-list> walker filter (concentrated
per-region audits, scratchpad/night10/legwalk.sh) + BindArmourDamage
ORPHAN inventory under BT_ARMOR_LOG (proved every drawn op is
zone-claimed on the full tree).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The binary's effect watcher (FUN_0042aa2c) raises
ForceUpdate(DamageZoneUpdateModelFlag) when a zone's damageLevel CROSSES a
band-descriptor threshold (FUN_0042a5f4, master-gated on entity+0x28 & 0xc)
-- that send is how every other pod's replicant learns zone levels
mid-fight. The port's band hub kept only the graphic-state branch, so an
observer's copy sat at 0.0 until destruction: no enemy hull darkening, no
doll movement, ever (the night-10 "no armour discoloration" report).
Restored the level branch with the already-reconstructed DescriptorCrossed
(@0042a5f4) + the master gate on both branches (mesh swap still runs on
every instance). 2-node verified: A-side armour watcher pushed 114 level
changes; every replicant peak matched the master's finals to 4 decimals
(dtorso 0.9321 == 0.9321).
Render path cleared separately (gotcha #23 discharged): BT_ARMOR_FORCE 0/1
A/B captures prove the tint renders (hull -> charcoal at 1.0). Solo
perception is the authentic economy: 2-25 pt lasers vs 68-185 pt pools.
Bench: zonewalk.sh node A now carries BT_ARMOR_LOG + BT_SHOT_EVERY (the
standing zone-replication receipt) + digest_walk.py; armorpx.sh is the
force-pair pixel rig.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
struck drawn segment's dzone, ALWAYS -- the cylinder embellishment removed
The open question ('what zone did 1995 designate for hull hits') was
already answered in the KB's #73 dig [T0+T1]: no software pick writer
exists -- the pod's pick was a dpl scene intersection, struck triangle
-> DCS segment -> its SKL-authored dzone; the cylinder lottery was only
ever the UNAIMED path (missiles/splash/rams). The live segpick dump
completes it with the authored data: the madcat's pickable skeleton is
18 segments -- hip, shoulders, guns, thighs, knees, ankles+toes, and
ONE hull piece (jointshakey -> dtorso). No ltorso/rtorso/utorso/rear/
door/searchlight segments exist. Aimed fire at any torso panel
authentically designates CENTER TORSO; the side/rear/upper panels strip
via the unaimed path.
Changes:
* the shared-carrier -> cylinder override (yesterday's embellishment)
is REMOVED: triangle hit -> that segment's dzone, period;
* SegAimPoint: the walker's hull anchor moves from the joint ORIGIN
(crotch gap -- rays sailed between the legs to the terrain sentinel)
to the carrier segment's cull center (the chest);
* [picktri]/[pickwin] diagnostics grew tri/seg/zone fields -- three
consecutive 'mystery' regressions in this stretch were the STALE-EXE
trap (CWD-relative cmake --build from content/ resolved to a
nonexistent dir and the old binary kept running) -- the harness doc's
warning, hit again.
Final zone-walk matrix (spinning target, real MP, full cycles):
limbs 55/70 in-zone (legs/feet 6/6; arm strays = hull/occlusion);
hull-family aims -> dtorso 56/69; victim consumption matches. The
night-10 field table now reads as this model's fingerprint: 'only LCT
gets hits' from aimed energy IS the pod -- one hull piece, dtorso.
What was actually broken and is now fixed: the sphere mis-picks
(rgun-from-a-dtorso-aim class), the unaimed path's 180-degree frame,
and the vertical scatter.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
approximation retired; shared-hull hits route through the cylinder
The zone-walk matrix caught the pick red-handed: with the servo
verifiably holding the reticle on the dtorso segment, the per-segment
BOUNDING-SPHERE pick returned rgun/ruleg -- the gun pods and legs
thread the ray before the torso from most angles (its own comments
admitted a foot could be unhittable behind its own knee). The 1995
pick was a dpl scene intersection against the drawn geometry.
Restored that semantic:
* BTGetPickMesh caches each segment d3d_OBJECT's triangles CPU-side
once (its own BGF VB/IB, managed-pool locks); MechSegmentPick now
runs sphere PRE-FILTER -> Moller-Trumbore nearest-hit across the
threaded segments' posed meshes; the old smallest-sphere selection
survives only as the no-triangle fallback.
* Segments claimed as CARRIER by 2+ zones (the shared hull: madcat
seg 4 carries dtorso+ltorso+rtorso+utorso+rears) cannot resolve one
zone from geometry -- those hits return zone -1 WITH the accurate
triangle point, and the victim's bit-verified (frame-fixed) cylinder
assigns the panel by band/wedge. Unique carriers (legs, feet, arms,
gun pods) keep the direct zone.
* ZoneAimPoint: the walker aims at a zone's VISUAL center (largest
pick object's cull-center) instead of the segment origin -- joint
origins made feet/lower legs strike the part above.
* Walker upgrades from live operation: 3-column truth (aim/pick/land),
engage gate, damped servo with polarity watchdog, approach port.
Zone-walk verdict (full cycles, spinning target, real MP): limbs 5-6/6
direct in-zone; every hull panel routes CYL; the victim's landed zones
now include ltorso/rtorso/reardtorso/rearutorso/rearrtorso -- the
panels night-10 reported unhittable. Residuals tracked on #124:
rtorso/utorso aim-anchor placement, doors/searchlight small-zone
sample, twisted-torso twist-sign verify.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The precision rig the operator specified: two nodes, target visible,
every zone aimed at deliberately through the REAL reticle/pick path.
* BT_SPIN_SELF=<deg/s> (target node): rotates the node's own viewpoint
mech in place (the BT_SPAWN_AT write pattern per frame) so every
aspect passes the shooter's boresight; the operator watches this
node's paper doll take the hits.
* BT_ZONE_WALK=<secs/zone> (shooter node): walks the target's damage
zones in order, resolves each zone's carrier segment's live world
position (BTResolveSegmentWorld + the new BTMechZoneSegAndName
bridge), SERVOS the torso twist + aim elevation until the centered
reticle ray (BTGetAimRay) points at the segment, fires 3 laser
pulses, advances. [walk] ZONE/FIRE/HOLD on A pairs with [dmghit]
zone/level lines on B.
* scratchpad/night10/zonewalk.sh: launch both + relay, map sed'd to
grass/day, NO kill timer -- the session stays up for observation.
Hard-won servo constraints (documented in test-harness.md so they are
never relearned): the ENGAGE GATE (ray live + range<150 + bearing<1.1;
outside it RELAX the twist -- servoing at the twist limit while the
goto marches is a limit-clamp fight that visibly shakes the mech, and
a 0.55 gate deadlocks against the goto's ~0.55 resting bearing); YAW
POLARITY -1 (the twist cell's angular sense is opposite atan2(x,-z)
world yaw -- operator-observed live, the SECOND witness for the #124
SelectSlice twist-sign flip) with a divergence watchdog that
self-flips; damped correction (gain .40, cap .025/frame -- the aim ray
lags the twist write a frame); and a one-shot approach PORT to 100u
off the target instead of a cross-map march.
First live run: walker cycles zones, settles, fires; the target's
luleg climbed 0.458->0.523 under its own aimed pulses -- aimed shot,
correct panel, damage consumed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Audit of Cyd's hit-model artifact against THE BINARY (user mandate: not vs the
port). res29_scan.py parses the type-29 streams straight from BTL4.RES bytes:
18 streams / 8 distinct confirmed; the 7-wedge cells (BLH band 6, VUL band 4)
and the all-fixed BLH/OWN twist patterns are authored fact; every artifact
spot-check cell matched the raw bytes verbatim. Chassis->table resolved by
live-dump matching (MadCat and Avatar ride DIFFERENT same-zone-set tables).
Authored slice names fix the wedge orientation: FRONT = the +Z arc, W1|W2 seam
= dead ahead -- corrects the #92 comment's W6-frontal claim. Collision type-0
divert re-grounded at 0x4a0361/0x4a036d: rams never touch the cylinder.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
For verifying Cyd's hit-location artifact (the platform serves it to this
session as an unreadable public artifact, so the diff base is published here
instead). scratchpad/night9/hitmodel_groundtruth.txt: every chassis's 7
layers x per-layer slices with zone NAMES and percentages, from the live
BT_DMGTABLE_LOG dump joined against [zone-armor] names.
Structure fingerprints (rot = rotateWithTorso per layer 0..6):
ava/lok/mad/snd/thr/vul rot=0001111 (legs hull-fixed, torso bands twist)
bhk/own rot=0000000 (chicken-walkers: NOTHING twists)
slices: 8 everywhere EXCEPT bhk layer 6 = 7 and vul layer 4 = 7
Variants share tables: lok2==lok1, mad2==mad1 -- '8 distinct chassis' is exact.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>