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>
This commit is contained in:
arcattack
2026-07-17 09:50:23 -05:00
co-authored by Claude Fable 5
parent dda517b65c
commit e0474ff92a
10 changed files with 382 additions and 53 deletions
+15 -10
View File
@@ -888,10 +888,11 @@ Mech::Mech(
//
// Three ref-counted creation-name holders (badge/color/insignia).
// CString members now: their default ctors run in the member-init phase and
// allocate the empty CStringRepresentation + addref -- exactly the binary's
// new(0x10)/FUN_004023f4/refs++ triple @part_012.c:9841-9871. Nothing to
// do here.
//
resourceNameA = NewRefCounted(); // Wword(0x211)
resourceNameB = NewRefCounted(); // Wword(0x212)
resourceNameC = NewRefCounted(); // Wword(0x213)
instanceFlags |= 0x10; // this[10] |= 0x10
// Zero the optional-subsystem back-pointers up front (binary @9873-9875).
@@ -1710,11 +1711,14 @@ Mech::Mech(
}
//
// Bind the three creation-name strings from the MakeMessage.
// Bind the three creation-name strings from the MakeMessage. CString::
// operator=(const char*) releases the empty ctor rep and allocates a fresh
// rep COPYING the message's inline char[20] -- byte-for-byte FUN_00402a98
// (part_012.c:10427-10441); the names survive the transient message.
//
resourceNameA = creation_message->resourceNameA; // param_2+0x7c -> Wword(0x211)
resourceNameB = creation_message->resourceNameB; // param_2+0x90 -> Wword(0x212)
resourceNameC = creation_message->resourceNameC; // param_2+0xa4 -> Wword(0x213)
resourceNameA = creation_message->resourceNameA; // badge param_2+0x7c -> Wword(0x211)
resourceNameB = creation_message->resourceNameB; // color param_2+0x90 -> Wword(0x212)
resourceNameC = creation_message->resourceNameC; // patch param_2+0xa4 -> Wword(0x213)
//
// Register this Mech in the global "Mechs" directory.
@@ -1810,9 +1814,10 @@ Mech::~Mech()
delete (MechDeathHandler *)deathHandler; // real class -> plain delete
}
ReleaseRefCounted(resourceNameC); // Wword(0x213)
ReleaseRefCounted(resourceNameB); // Wword(0x212)
ReleaseRefCounted(resourceNameA); // Wword(0x211)
// resourceNameC/B/A: the binary's inline refcount-decrement/delete triple
// (part_012.c:11388-11403) is the CString member dtors -- implicit at the
// closing brace now that the members are real CStrings (dtor-epilogue rule:
// do NOT also write them out here).
//
// ⚠ RECONSTRUCTION RULE (root cause of the P5 death-row crash AND the app-exit