#87 dig closure: host response is linear (raw decomp re-read); the pixel curve was div-card firmware

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>
This commit is contained in:
Joe DiPrima
2026-08-03 13:10:00 -05:00
co-authored by Claude Fable 5
parent fe48accb6b
commit 440cee1e4f
5 changed files with 132 additions and 8 deletions
+27
View File
@@ -1451,9 +1451,36 @@ void
}
if (log)
{
DEBUG_STREAM << "[armor] entity " << (void *)entity << " skel="
<< tree.skeletonType << ": " << tree.dmgBinds.size()
<< " material binding(s)\n" << std::flush;
// ORPHAN inventory: drawn ops NO zone claimed. These panels never
// darken -- if the big hull materials land here (a .DZM name the mesh
// doesn't carry, or per-zone material instancing collapsed at load),
// the mech reads "no darkening" live even while every bound op logs
// perfectly (the #87 visibility gap).
for (std::map<int, MechRenderTree::SegPick>::iterator si = tree.segPick.begin();
si != tree.segPick.end(); ++si)
{
d3d_OBJECT *obj = si->second.obj;
if (obj == NULL)
continue;
for (int op = 0; op < obj->GetDrawOpCount(); ++op)
{
L4DRAWOP *draw_op = obj->GetDrawOp(op);
if (draw_op->dzMatName[0] == '\0')
continue;
int claimed = 0;
for (size_t b = 0; b < tree.dmgBinds.size() && !claimed; ++b)
if (tree.dmgBinds[b].obj == obj && tree.dmgBinds[b].op == op)
claimed = 1;
if (!claimed)
DEBUG_STREAM << "[armor] ORPHAN op seg=" << si->first
<< " '" << draw_op->dzMatName << "'\n" << std::flush;
}
}
}
}