#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:
co-authored by
Claude Fable 5
parent
fe48accb6b
commit
440cee1e4f
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6025,6 +6025,19 @@ void
|
||||
static float s_zwT = 1.0e9f;
|
||||
static int s_zwZone = -1;
|
||||
static int s_zwShots = 0;
|
||||
// BT_WALK_ZONES=<comma-list>: restrict the walk to zones whose NAME
|
||||
// contains one of the tokens (e.g. "leg,foot,hip" -- the concentrated
|
||||
// per-region audit; repeated passes pile damage into few zones so the
|
||||
// doll movement is unmistakable). Empty/absent = walk everything.
|
||||
static const char *s_zwFilter = 0;
|
||||
static int s_zwFilterInit = 0;
|
||||
if (!s_zwFilterInit)
|
||||
{
|
||||
s_zwFilterInit = 1;
|
||||
s_zwFilter = getenv("BT_WALK_ZONES");
|
||||
if (s_zwFilter != 0 && *s_zwFilter == '\0')
|
||||
s_zwFilter = 0;
|
||||
}
|
||||
if (s_zwPeriod <= 0.0f)
|
||||
{
|
||||
s_zwPeriod = (float)atof(getenv("BT_ZONE_WALK"));
|
||||
@@ -6119,8 +6132,32 @@ void
|
||||
s_zwZone = -1; // wrap
|
||||
continue;
|
||||
}
|
||||
if (segIdx >= 0)
|
||||
break;
|
||||
if (segIdx < 0)
|
||||
continue;
|
||||
if (s_zwFilter != 0) // BT_WALK_ZONES name filter
|
||||
{
|
||||
int match = 0;
|
||||
const char *tok = s_zwFilter;
|
||||
while (*tok != '\0' && !match)
|
||||
{
|
||||
const char *end = tok;
|
||||
while (*end != '\0' && *end != ',')
|
||||
++end;
|
||||
char buf[64];
|
||||
int len = (int)(end - tok);
|
||||
if (len > 0 && len < (int)sizeof(buf))
|
||||
{
|
||||
memcpy(buf, tok, len);
|
||||
buf[len] = '\0';
|
||||
if (strstr(zname, buf) != 0)
|
||||
match = 1;
|
||||
}
|
||||
tok = (*end == ',') ? end + 1 : end;
|
||||
}
|
||||
if (!match)
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
DEBUG_STREAM << "[walk] ZONE " << s_zwZone << " '" << zname
|
||||
<< "' seg=" << segIdx << " target="
|
||||
|
||||
Reference in New Issue
Block a user