Commit Graph
17 Commits
Author SHA1 Message Date
arcattackandClaude Fable 5 6f6a39b8c9 Issue #3 (b)+(c): weapon damage reaches cultural icons -> full trkdead explosion + authored burn fire
(b) The 'tiny explosion' on the ram kill is AUTHORED: crunch res 31 = 'stephit'
(one video object, effect 1008 = ddam5 damage smoke) -- a step/ram squash is
small by design.  The FULL explosion res 32 = 'trkdead' = psfx 15 dtrkboom
(fiery omni burst) + psfx 16 dtrkburn (the burning-wreck fire), reached by
WEAPON kills -- which the 1995 binary dispatches [T1]:
  - MechWeapon::SendDamageMessage @004b9728 (part_013.c:6765) gates only
    "target NOT derived from Mech@0x50bdb4 OR aimed zone set": a non-Mech
    boresight target takes the zone=-1 damage UNCONDITIONALLY;
  - Missile contact @004be078 dispatches at the struck solid's OWNER entity
    with no class test at all.
Port wiring: Mech::WorldStructurePick returns the struck solid's owning entity
(BoxedSolid::GetOwningSimulation; TERRAIN.cpp:107/246 build every static solid
with its Terrain/CulturalIcon/Door entity as owner); the mech4 pick block
designates IT instead of the gBTTerrainEntity sentinel (sentinel = fallback);
the projectile contact path grew the non-mech damage-zoned else-branch
(@004be078 mirror, direct Dispatch).  Plain terrain ignores the damage
(ENTITY.cpp:885 zone==-1 guard); an icon's handler maps -1 -> 0 and dies.
Truck armor is WeaponDamagePoints=1 (TRK.DMG): one laser = one dead truck.

(c) The burning fire is dtrkburn.pfx, authored INTO the death package (every
icon family carries 1016: trkdead/bigdead/meddead/msldead/twrdead).  There is
NO looping BurningState fire in the binary: the damage-zone effect watcher
ctor @0042a984 has exactly one call site (the Mech ctor, part_012.c:10405), so
icon ExplosionTables are inert, and CulturalIcon has no Performance.
Documented as authentic -- nothing invented.

Verified live (BT_SHOT pixel capture): 26 laser kills, [cult] TakeDamage
type=3 -> DYING res=32 -> DPLIndependantEffect 1015+1016 at the icon origin;
frames show the orange dtrkboom fireball, dtrkburn flames on the fresh wreck,
and the rubble aftermath; ram harness re-run still fires crunch res 31.
Diags: BT_FIRE_AT_ICON (designate nearest ahead icon; live-icon census in
CULTURAL.cpp), BT_FX_TEST="1015,1016".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 12:02:15 -05:00
arcattackandClaude Fable 5 9fff079df4 Issue #3: wreck scorch quad ramp + RGBA4444 alpha cutout (the 'dark square')
MECHMD's scorch base (basev:bvx9_mtl, bexp9_tex = BEXP.BSL RGBA4444
slice 8, ramp cdusty) drew as a hard-edged dark square for two stacked
reasons:

1. The blanket 'truecolor BSL slice (channel >= 6) never ramps' gate
   blocked its cdusty ramp.  Corpus scan: only 4 shipped textures use
   truecolor slices; bexp9/bdet9 are grayscale in RGB (100% / 98.8%
   r==g==b) and their materials author ramps -- only bdam8 (damage
   sheet) is truly coloured.  bgfload rampableSlice() now probes the
   decoded slice: a truecolor slice ramps iff effectively gray (>=95%),
   keeping bdam8's colour protected.

2. The RGBA4444 authored alpha channel -- a binary 0/240 cutout mask
   (the splat silhouette, 78.5% transparent) -- was never alpha-tested,
   so the quad's transparent surround rendered as an opaque rectangle.
   New BgfDrawBatch.texAlpha (channel >= 8) routes these batches
   through the PUNCH alpha-test draw states, WITHOUT the black-texel
   keying (which would hole the near-black charred centre).  Side
   benefit: tree9 (tree/leaf cards) + bdet9 (trans-rail lattice) get
   their authored cutouts too.

Pixel-verified (ram-kill run, BT_SHOT): irregular char splat, dark
brown (71,44,34) lifting to near-terrain tan (115,100,91 vs terrain
131,119,108), no rectangle; pre-death frames unregressed (vehicles
stay lit/diffuse -- hasNormals gate untouched).  Awaiting human
verification.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 10:39:43 -05:00
arcattackandClaude Fable 5 83385b0661 KB: issue-3 pickup trail -- bvx9_mtl scorch quad + crunch-vs-full explosion
Human-verified: wreck swap works live; small ram explosion visible.
Remaining detail recorded for the next session.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 10:06:05 -05:00
arcattackandClaude Fable 5 df2a97fe20 KB: rubble placement fix status (pixel-verified; scorch/explosion/fire still open)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 09:56:58 -05:00
arcattackandClaude Fable 5 28b01e3529 KB: truck destruction NOT fixed -- playtest falsified the harness claim
Human playtest (2026-07-19): ramming a truck makes it disappear entirely --
no rubble, no smoke/fire, no visible explosion.  The [cultvis] log evidence
verified the STATE MACHINE (pointer swaps), not pixels: the rubble child
component (DCSInstanceRenderable/DPLStaticChildRenderable) is itself
2007-stubbed and never draws, and the routed psfx 1008 produces nothing
visible.  rendering.md section corrected from 'verified live' to PARTIAL
with the three remaining gaps (rubble draw, visible explosion, burning
fire).  Gitea #3 reinstated as open/wip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 09:32:54 -05:00
arcattackandClaude Fable 5 53ac927d4b Destructible props LIVE: revive StateInstanceSwitchRenderable (Gitea issue #3)
Playtest report: trucks play a collision sound on impact but never change
state -- no explosion swap, no destroyed model, collision volume persists.

Investigation (BT_CULT_LOG census + BT_GOTO ram harness): the SIM was never
broken.  ARENA1 map-streams 124 CulturalIcon entities, each with a damage
zone, explosion resource and removeOnDeath; the mech crunch dispatch
(ProcessCollision -> BTDispatchCollisionDamage) reaches them; ~19 walking
bumps burn the zone -> CulturalIcon::TakeDamageMessageHandler spawns the
Explosion (psfx effect 1008 observed), posts the delayed BurningState and
deletes the collision boxes.  All of that ran correctly and invisibly.

The ACTUAL bug: the 2007 WinTesla port fully stubbed
StateInstanceSwitchRenderable ('STUBBED: DPL RB 1/14/07') -- ctor never
registered on the state dial, Execute never toggled anything -- so the
intact->rubble visual swap on BurningState NEVER fired, for every cultural
icon in the game.  The destroyed truck kept its intact model: exactly the
reported 'no state change'.

Revival (D3D9-native, 1995 semantics verbatim):
- StateInstanceSwitchRenderable now controls the draw COMPONENT via the
  SetDrawObj in-place drawable swap (the mech RemakeEntity mechanism):
  visible = captured d3d_OBJECT, hidden = NULL.  Initial state in the ctor,
  AddVideoWatcher on the SimulationState dial (SetState fires video
  watchers), toggle only on a real change.
- L4VIDEO cultural case passes the draw component + object (the dead
  dpl_INSTANCE param is gone); [video] Object hides at BurningState,
  Rubble shows.
- REQUIRED: cultural objects stay OUT of static-mesh consolidation
  (RecurseStaticObject, same exclusion class as banded LODs/shadows) --
  a merged static draws forever regardless of DrawObj.
- Permanent env diag BT_CULT_LOG: creation census (zones/explosion/flags/
  pos), TakeDamage trace, death transition, [cultvis] switch actions.

Verified live (BT_GOTO=-620,-328 ram, ARENA1): 19 crunches -> DYING ->
explosion 1008 at the icon -> [cultvis] HIDE x2 (intact) + SHOW (rubble)
-> contacts cease, mech walks into the former footprint.  Boot + render
un-regressed (statics consolidate as before minus the 124 icons).

KB: context/rendering.md new section (the full chain + the consolidation
gotcha).  MP replicant path shares the same SetState watcher (cross-pod
verification pending -- noted in the issue).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 09:23:02 -05:00
arcattackandClaude Fable 5 e0474ff92a Per-pilot mech paint: wire the color/badge/patch substitution end-to-end
- Mech::resourceNameA/B/C -> real CString members (the binary's 16-byte
  CStringRepresentation; deep-copy bind from the MakeMessage = FUN_00402a98,
  implicit member dtors) + paint-name accessors
- SetupMaterialSubstitutionList reads the real egg names ([paint] log);
  TearDown clears the callback first (FUN_004d11e8)
- dpl_SetMaterialNameCallback is real now (L4VIDEO registry); bgfload
  MaterialResolver::resolve() applies it to every material name -- the
  port analogue of the dpl board rewriting names at load
- MP_BHMC.EGG: color=Red -> Crimson (vehicletable has no Red; binary Fail()ed)

Verified live 2-node MP: crimson MadCat with hip hazard stripes + yellow VGL
leg emblems; white Blackhawk + emblems; replicants painted on both nodes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 09:50:23 -05:00
arcattackandClaude Fable 5 dda517b65c KB: mech paint audit -- per-pilot color/badge/patch substitution authored but unwired (the 'missing stripes/coloration' report)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 09:32:53 -05:00
arcattackandClaude Opus 4.8 82e6bb306a KB: sweep STALE "unfinished" claims -> match landed commits (context-system audit)
4-agent audit cross-checked every open/pending/stub/deferred claim in the context
system against git + code. Fixed ~13 stale spots (currency only, no code change),
each contradicted by its own file body + a landed commit:

- 0xBD3 SubsystemMessageManager (task #7, afefaee): subsystems.md frontmatter+body
  line 57; decomp-reference.md 0xBD3 row + +0x434 row -- all still said
  "MISLABELS controlsMapper / WAVE 8 untangle" (done; mech.hpp names it messageManager).
- Cylinder hit-location STEP 6 (d07ac7d): combat-damage.md frontmatter;
  decomp-reference.md "not reconstructed" line.
- Per-mech turn-rate wiring (task #64b, a83995a): multiplayer.md + locomotion.md
  frontmatter (still "bring-up constant / not yet wired").
- Mech-level update records (task #1, c9f0c2a): open-questions.md "dead Wword
  branches mech.cpp:1511/1613" (those branches are gone; named fields now).
- Collision damage + DeathShutdown (2026-07-08/12): combat-damage.md frontmatter.
- Myomers un-stub (8b36440): decomp-reference.md "INERT un-stub" row.
- Day/night BT_MATPRI (shipped, default-on): rendering.md frontmatter (LOD half kept).
- Fire-trigger path (task #5, 8ed6184): open-questions.md "still gBTWeaponTrigger
  bring-up" (globals retired/never-read).
- HEAT entry FACTUAL fix: "heatLoad -> effectiveRange 0 = overheat cutout" was false
  per aab7a8a -- effectiveRange reads host-zone damage; the real cutout is the
  FailureHeat charge-hold.

Frontmatter open_questions re-pointed at genuinely-open items. VERIFIED NOT stale
(left as-is): multiplayer body-channel-projection notes (a real open [T3] residual
per the coupled-motion section's ~2.9u leg-vs-body snap). Genuinely-open items
(factory roster loops 2-4, subsystem-panel gate, missile cluster, console-death
freeze, gyro tails, etc.) untouched. checkctx CLEAN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 14:35:41 -05:00
arcattackandClaude Opus 4.8 c0a0ec5e69 KB: document the searchlight fog-swap latent bug (task #63, left as-is by decision)
Investigation (workflow) found the searchlight-driven fog swap never worked in the
ORIGINAL 1995 binary either -- it's a latent bug, not a port regression:
SearchlightSimulation (@004b841c) reads requestedOn@0x1E0 (never written) while
ToggleLamp (@004b860c) toggles commandedOn@0x1DC; no bridge exists, so lightState
@0x1D8 is perpetually 0 (lamp never lights). The self-consistent sibling
ThermalSight reads the field it toggles (0x1DC) -- the tell. The port reproduces
the bug faithfully (searchlight.cpp:189). Additionally the port never constructs
PullFogRenderable, so even absent the bug the swap wouldn't fire.

Decision: LEAVE AS-IS + document (faithful to the buggy original); the port keeps
the static lights-ON fog= values. A working swap would DEVIATE from the shipped
binary (repair the sim to read commandedOn + construct PullFogRenderable at the
btl4vid MakeMechRenderables inside pass + a toggle input) -- fully scoped in the KB
if ever wanted. No code change this commit.

Documented in rendering.md (fog section), open-questions.md (deferred subsystems),
subsystems.md (Searchlight). Core per-map/time/weather fog (task #63) is unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 22:04:29 -05:00
arcattackandClaude Opus 4.8 225fa5951b Render: fog searchlight-swap verified INERT + BT_FOG_LOG diag (task #63)
Verifying the searchlight/nosearchlightfog swap (user request): it does NOT work.
The arcade swaps active fog between fog= (headlight on) and nosearchlightfog=
(off, darker/tighter) via PullFogRenderable::Execute (edge-triggered on the mech's
light attrs -> SetFogStyle searchLightOn/Off).  But PullFogRenderable is NEVER
CONSTRUCTED in the port (grep: only the .h decl + .cpp def; no `new`), and
searchLightOn/Off is called from nowhere else.  Empirical confirmation via the new
BT_FOG_LOG hook: over a 22s run SetFogStyle fired only style 0, zero style 2/3.

So fog is static at the searchlight-ON (fog=) values -- normal lights-on play, so
core per-map/time/weather fog is unaffected -- but the nosearchlightfog variant is
dead.  Corrects my earlier "the swap is wired end-to-end" claim (code paths exist,
trigger never instantiated).  KB rendering.md updated; wiring it back is a scoped
reconstruction (bind the Searchlight subsys light state to a constructed
PullFogRenderable at viewpoint setup).  No behavior change this commit -- diag only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 21:36:48 -05:00
arcattackandClaude Opus 4.8 083b148bb0 Render: FOG restored -- authentic per-map/time/weather fog now renders (task #63)
User: "aren't some levels supposed to have fog?" -- they were, and none showed.
BTDPL.INI (the DPL env INI, L4DPLCFG) authors fog=near far r g b (+ often
nosearchlightfog=) on EVERY map/time/WEATHER leaf; weather is a fixed egg field
(clear/fog/soup). Shipped eggs pin cavern/night/clear -> page dsnitclear
(near 90, far 1100, dark blue). The env pipeline resolved + pushed it to D3D, but
it rendered INVISIBLE: D3DRS_FOGTABLEMODE=D3DFOG_LINEAR (table fog) derives its
factor from the perspective-NONLINEAR z-buffer, so without WFOG the 90..1100 range
collapsed to fog-factor ~1 (no fog everywhere).

Fix (L4VIDEO.cpp world pass): auto-detect D3DPRASTERCAPS_WFOG -> per-pixel W-fog
(smooth, == the arcade dpl_fog_type_pixel_lin); else VERTEX fog (eye-space but
per-vertex -> splotchy on coarse terrain tris, so only a fallback). FOGENABLE + the
fog mode are re-asserted each world-pass frame (the old one-time set got clobbered
per-pass, which is why plain table fog showed nothing). Verified on this GPU:
WFOG present -> per-pixel table fog, user-confirmed smooth.

Also corrected task #20's false "shipped maps define no fog" comment (it checked
.MAP/.RES, not BTDPL.INI). Env hooks: BT_FOGMODE=table|vertex|off, BT_WEATHER=
clear|fog|soup, BT_FOG="near far r g b" (now honored on the authored branch too);
[fog] resolved/model diagnostics. KB: rendering.md fog section added.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 21:24:06 -05:00
arcattackandClaude Fable 5 065c114590 Impact-FX FORENSICS wave: the i860 specialfx engine, per-round detonations, the ram economy closed
The "we're off the rails" reinvestigation -- a 5-thread evidence workflow
(logs / PFX data / RES model lists / decomp / port audit) + the i860 firmware
decode, then surgical fixes.  Every claim tiered; the wrong turns are on the
record in the KB alongside the corrections.

THE OLD-STYLE SPECIALFX ENGINE [T1, firmware-decoded from VREND.MNG]:
rebuilt scratchpad/i860dis.py (binutils opcode table); mapped the dispatch
(data+0xdd0c; sfx trigger 0xf040cda0, install 0xf040cdc0, step ~0xf0413698,
instance init 0xf04128d8); decoded the heat model EXACTLY: per 30Hz board
frame h *= cool_a; RGB_ch = h_old*(h_new*cook_ch - 0.25) + 0.25 (K=0.25 =
the ember floor @VA 0xF080; kill at h <= 1e-4 @0xF0A0); alpha fades cool_b
x RAW dt (PER-SECOND -- the x30 scaling made laser hits invisible); 7s cap;
y_off = the kill plane; "variance" is DEAD DATA (binary reads "variance",
INI authors "varience").  The 13 descriptors (PPCHit/LaserHit/MissileHit/
Chunks/Sparks/Fireball...) parse from BTDPL.INI and render via the BTPfx
layer -- heat bursts draw the FIERY sheet (brightness over fire), .PFX keeps
GRAYSCALE (authored colours: DNBOOM orange, DDAM gray).

HIT-PACKAGE CENSUS [T1, RES byte-verified]: ppchit=[8] lzrhit=[9] mghit=[7,11]
canhit=[11] mslhit=[10,12,1023] explode=[6]; all 8 mech death lists identical.
Effect routing corrected in BOTH consumers: <100 = specialfx, >=1000 = psfx.

"SILVER MIST x5" ROOT CAUSE: SHKWAVE.PFX (mslhit's 1023) authors maxIssue=5
relPeriod=0.2 rate=1 -- the ONE file where rate contradicts the window; the
emitter trusted rate -> 5 shells at exactly 1Hz.  Emission rate now always
maxIssue/releasePeriod.

PER-ROUND DETONATIONS [T1 @004bef78]: every missile round spawns its own
ExplosionModelFile at ITS impact (hull + terrain) -- a volley ripples 12
fireballs like the demos; rack-tube launch spread [T3] (GUIDED rounds only --
the slot-0 deflection sent every AFC100 shell 3.4deg left/2.5deg down: the
phantom "4th gold beam"); replicant salvos detonate too (launcher index rides
the visual push).  Missile damage bundles through the shooter's messmgr with
the launcher's subsystemID (mslhit fires at the consolidated point; the
binary's dedup CONFIRMED [T1 @0049b784] -- a workflow agent's per-record
claim REFUTED by direct decomp read).

DAMAGE-BAND SEMANTICS [T1]: MechDeathHandler fires the CURRENT band effect on
any damage rise (the binary's changed-flag coalescing) -- a mauled mech under
fire smokes/burns per hit; bands 3/4 are authored fire plumes.

THE RAM ECONOMY -- CLOSED (3 layers, measured live):
 1. armor = POINTS (every zone: damageScale = 1/armorPoints, armor 50-140;
    the [zone-armor] BT_DMG_LOG dump);
 2. StaticBounce prices rams with authored moverMass ~1.3e6 -> ~59,000 pts
    @10m/s; the binary dispatches it RAW but pod MP dropped it on the local
    replicant (MECH.CPP:986 warns) -- ram damage was NETWORK-INERT; our
    task-#47 replicant forwarding surfaced it as a one-shot.  Port
    normalizes x1e-3 to the point economy [T3];
 3. contact EDGE (ramLastVictim/ramContactLinger): the binary's bounce made
    separation implicit; our gait-derived velocity re-priced full rams at
    60Hz (the respawn explode-loop).  One bump = one hit; pressed = BLOCK.

PLUS: sfx size x0.5 + 1.25m visibility floor + hot-phase occlusion [T3];
particle pool 2048->8192 (missile traffic starved laser bursts -- the
"intermittent effects"); replicant beam aging (a lost beam-END record pinned
a stale beam on forever); UV-variant noise stamps (mask-safe mirror/swap);
no scroll on particle stamps (material-path only); BT_FX_TEST/fxshot.py
self-verification harness ([beam-draw]/[zone-armor]/[collide-tx] telemetry).

KB: rendering.md (specialfx engine + census + closeout), combat-damage.md
(ram economy + band semantics).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 08:14:12 -05:00
arcattackandClaude Fable 5 48c9c8444f Fire VISUALS wave: the authored firesmoke sheet, vertex-alpha effect cards, the case-4 wreck dressing
The "fireballs like the demo vids" arc, decomp/content-grounded end to end,
plus the live-play UX batch verified over the same sessions:

FIRESMOKE SHEET (the PFX fireball fix): every firesmokeN_scr_tex in BTFX.VMF
maps the SAME 64x64 tileable noise image bintA (variants differ only in SCROLL
rate) and firesmoke1_mtl colours it through the "fiery" ramp (0.3,0.1,0.1)->
(0.9,0.7,0.3).  The particle layer now bakes ramp(lum(bintA)) as its sprite
colour (noise detail in alpha) and SCROLLS it at firesmoke1's authored rate
via a texture-transform; the port's radial soft-edge mask moved to a second
CLAMPed stage so the WRAPPED scroll rolls flame through the sprite without
scrolling the edge away.  Old grit x radial bake kept as the no-BINTA fallback.
Impact hits, damage-band smoke and death booms all ride this layer.

AUTHORED TEXTURE SCROLL in the model path: the BMF TEXTURE records carry
SPECIAL " SCROLL u0 v0 du dv" (tag 0x2037); the draw path always supported
per-op scrolling (SetTextureScrolling) but the BGF loader never parsed it, so
every scrolling material rendered frozen.  Wired TexRef -> MatInfo -> batch ->
L4TEXOP.doScroll: the flame cards (flamebig/fire5) now roll fire noise.

VERTEX-ALPHA EFFECT CARDS (the "twisted drill bit of fire" fix): FLAMEBIG's
verts carry authored float RGBA -- white-hot base (1.0,0.99,0.97) -> dark-red
tip fading to alpha -0.2 (the DPL clamp convention).  The loader kept a flat
batch colour and drew it OPAQUE = a solid orange spike.  Corpus sweep: exactly
14 shipped BGFs carry vertex alpha, ALL effect cards (flames, MUZFLASH,
EXDISK_A/B/C, TMST_A/B/C, beam models, DECLOUDS).  Such batches now keep the
authored per-vertex gradient and route to the alpha-blend pass, unlit,
colour = texture x gradient, alpha = the vertex fade; sky objects excluded
(drawAsSky + alphaTest passes NEITHER pass filter -- DECLOUDS stays in the
sky pass).  MUZFLASH/EXDISK render correctly for free when the muzzle-model
work lands.

WRECK DRESSING (the 1996 ExplosionScripts case-4 transcription): pieces spawn
HIDDEN and reveal 0.25s after the boom (the InstanceSwitch delay, behind the
dnboom flash); flamebig hangs over the pile, Y-BILLBOARDED at the camera
(SetOffsetYaw + a camera-pos getter -- the dpl_SetDCSReorientAxes analog);
the MakeDCSFall settle arms at the reveal with the two authored rates (hulk/
debris -0.025 t^2, fires -0.01 t^2 -- the flames ride above the sinking pile
and die with it at burial).  EMPTY-PLACEHOLDER hulk guard: THRDBR.BGF is a
153-byte zero-geometry stub that "loads fine" -- vertex-count check now routes
it to the gendbr fallback (a Thor wreck was invisible).  Hulk content census
recorded: AVADBR==MADDBR==VULDBR geometry (palette-only prefix diffs),
RAPDBR==SNDDBR==STIDBR byte-identical -- wreck variety is materials + the
dressing, not unique piles.

LIVE-PLAY BATCH: muzzle resolve uses the named segmentIndex (raw +0xdc read
was layout garbage); forward launch frame (authored MuzzleVelocity +Z vs the
mech's -Z facing); dock-bottom single window (gauge strip appended below the
world viewport, 1100x600 default, BT_DEV_GAUGES_WINDOW=1 restores the separate
window); portrait sec surface unrotated CW; ammo counters live via typed
bridges (BTAmmoBinCountPtr/BTAmmoBinFeeding/BTWeaponAmmoBin -- raw bin+0x180
and a hand-rolled link walk were garbage); fourth fire key ('4' = Pinky);
panel/arc probes de-aliased (%61 prime).

KB: rendering.md (vertex-alpha card family + scroll), combat-damage.md (hulk
census + THRDBR stub), gauges-hud.md (ammo bridges).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 20:04:29 -05:00
arcattackandClaude Fable 5 3c34ae6de6 KB: full staleness audit + sweep -- 35 verified corrections across 16 topics, 15 new glossary terms
Adversarially-verified audit (18 agents) against the task #46-#56 landings:
MP/current-state understatements, superseded punch readings, retired env
gates, dead paths, line-cite drift; env-gate hub table completed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 10:56:51 -05:00
arcattackandClaude Opus 4.8 0bfb3d4ab3 Warp: restore the translocation-vortex look + fix texture-scroll precision collapse (task #52)
The death/respawn "blue whirlwind" (tsphere) now matches the original cabinet
photo (capture.png): a smooth spinning lavender vortex with a bright core.

Root cause of the long-standing "radial spokes" artifact was NOT the warp code
but a general engine bug: L4D3D::SetTextureScrolling computed its texture-matrix
offset as scrollDelta * absolute_time, which grows unbounded and collapses UV
float precision -> a smooth scrolled cloud shatters into grainy radial steps.
Wrapped with fmodf(..., 1.0f) (identical under REPEAT tiling, full precision).
This also cleans the scrolling bexp beam grit and any other SCROLL material.

Visual reconstruction (verified against the real 45-vtx TSPHERE.BGF bicone,
offline-rasterized then ported):
  - view ON-AXIS (eye centred on the throat) + spin in place -> concentric rings
    (decomp FUN_00453dc4 does spin-about-local-Z + submit; the port had stubbed it)
  - bintA cloud through a WIDE lavender ramp at full contrast (drawn as SKY);
    no geometry "bands", no log-polar twist, no off-axis tornado (all discarded)
  - tessellate the 12-facet bicone smooth; isotropic + trilinear; ramp baked into
    the texture and drawn SELECTARG1(TEXTURE) to avoid double-tinting

Env knobs (BT_WARP_*) default to the verified values; BT_WARP_SELFTEST/SELFSHOT
are an off-by-default visual-verification harness (backbuffer frame dump).

Docs: new context/translocation-warp.md (geometry/material/visual/lifecycle/env);
reconstruction-gotchas.md gains the accumulated-time precision-collapse bug class;
rendering.md / multiplayer.md / decomp-reference.md / CLAUDE.md cross-linked.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 14:53:50 -05:00
arcattackandClaude Opus 4.8 f914fc040a context-system: complete migration -> CLAUDE.md is now a 160-line router (zero context lost)
Full migration of the 2236-line monolithic CLAUDE.md into the progressive-context
knowledge graph (per spark-lesson / expert-seed.md), so the deep RE knowledge loads
on-demand instead of every session.

ZERO CONTEXT LOST:
- docs/PROGRESS_LOG.md = the complete old CLAUDE.md, VERBATIM (byte-identical) -- the
  lossless safety net + the "full detail" quick-lookup fallback.
- 18 context/*.md topic files (1343 lines) digest every section (§1-3 -> project-overview,
  §4 -> content-archives, §5 -> asset-formats/bgf-format, §5a -> source-completeness,
  §5b/§8 -> wintesla-port, §7/§10 -> locomotion, §10a -> build-and-run, §10b ->
  reconstruction-method, §10c -> combat-damage + reconstruction-gotchas, §10d -> subsystems,
  render notes -> rendering, gauges -> gauges-hud, MP -> multiplayer, §9 -> open-questions).
- reference/glossary.yaml (53 terms). decomp-reference.md = the offsets/ClassIDs/addresses hub.

CLAUDE.md (160 lines) = router: identity, answer/reason protocols, quick-lookup table,
evidence tiers (T0 engine-truth / T1 decompiled+verified / T2 reconstructed+runtime /
T3 guarded / T4 hypothesis), conventions + DO-NOT (the systemic bug classes), structure.
Retains the load-bearing work directives (build recipe pointer, "keep current" mandate).

Knowledge graph validates CLEAN (scratchpad/checkctx.py -- all [[links]] + quick-lookup +
docs refs resolve; [[name]] -> topic file or glossary term). docs/*.md ledgers stay as the
detailed logs; context/*.md are the curated digests that route into them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 22:19:50 -05:00