Combat visible + killable: Wword root-cause fix, .PFX effect layer, RemakeEntity swap
The 'can't kill the enemy / no visible damage' cluster, root-caused and fixed faithfully: - STEP-6 unaimed path was INERT: the cylinder table was 'cached' at Wword(0x111) -- the recon ABSORBER bank (stores nothing, reads 0) -- so every unaimed hit silently no-op'd. Promoted to the named member Mech::damageLookupTable (binary this[0x111], was mislabeled ammoExpended). New gotcha class recorded (reconstruction-gotchas §2) + sweep; 2 dead multiplayer branches logged. - Fire path migrated off the stale vital-zone aim onto the completed STEP-6 unaimed dispatch (zone=-1 + beam entry point -> cylinder resolves the exterior zone). No more invisible 1-shot kills; death via the authentic cascade (~14 center-mass hits). Wreck stays TARGETED on kill (beams stop on it); scoring latches off. - SendSubsystemDamage AV fixed: unbound critical-subsystem plug guard (43 unbound plugs/mech logged as an open question -- the binding itself is a gap). - RemakeEntity (render damage swap): the 1996 render state machine's missing Remake state, reconstructed as an in-place SetDrawObj mesh swap keyed by each segment's damage-zone graphic state (tree dtor doesn't cascade -> never rebuild). Destroyed arms/guns visibly wreck (the only variants the RES registers). - BT .PFX particle layer (L4VIDEO.cpp): the 1995 explosion/damage effect layer, unported since 2007 (DPLIndependantEffect/ReadPSFX/ExplosionScripts all stubs). Parses the authentic VIDEO/*.PFX definitions via the [pfx_day] psfxN mapping; premultiplied blending renders BOTH families from the same data (additive-style fire + occluding smoke -- DDAM2 is 30% grey, DDTHSMK ramps negative: impossible additively); depth-sorted billboards with a radial-masked grit sprite; impact-frame orientation (.PFX offsets are authored mech-local, -Z = out of the struck armor toward the shooter) for weapon hits AND damage bands (via lastInflictingID, now maintained -- was declared but never written). Both effect-number encodings route (raw dpl <100 + WinTesla 1000+slot carried by the band resources). Death fires the authentic dnboom (7) + ddthsmk smoke plume (1). - Effects anchor at the impact point / damaged zone's segment, not the mech origin (no more fire at the feet). - Dev force-input gates BT_AUTOFIRE / BT_AUTODRIVE for headless fire-chain verification; BT_PFX_ADD=1 flips the particle blend for A/B. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
7c455303bd
commit
a3d67cc639
@@ -486,7 +486,13 @@ void
|
||||
Mech::TakeDamageMessageHandler(TakeDamageMessage *message)
|
||||
{
|
||||
Check(message);
|
||||
DamageLookupTable *table = (DamageLookupTable *)Wword(0x111);
|
||||
// Maintain the last-attacker bookkeeping (mech[0x43c]): read by the
|
||||
// DamageZone LOD router (same-attacker redirect reuse, mechdmg.cpp:374)
|
||||
// and by the damage-band effect orientation. Was declared but never
|
||||
// WRITTEN -- a reconstruction gap; the natural authentic write site is
|
||||
// this handler (every damage message carries the inflictor). [T3]
|
||||
lastInflictingID = message->inflictingEntity;
|
||||
DamageLookupTable *table = (DamageLookupTable *)damageLookupTable; // named member (Wword absorbs!)
|
||||
if (message->invalidDamageZone && table != 0)
|
||||
{
|
||||
int zone = table->ResolveHit(message->damageData.impactPoint);
|
||||
@@ -1323,7 +1329,7 @@ Mech::Mech(
|
||||
// cached at mech[0x111] (byte 0x444). (Was an empty-name StandingAnimation
|
||||
// stub -> 0 rows; the real class is dmgtable.cpp.)
|
||||
//
|
||||
Wword(0x111) = 0;
|
||||
damageLookupTable = 0; // named member (Wword absorbs!)
|
||||
ResourceDescription *dzForName =
|
||||
MechFindResource(creation_message->resourceID,
|
||||
ResourceDescription::DamageZoneStreamResourceType); // type 0x14 (for its name)
|
||||
@@ -1339,7 +1345,7 @@ Mech::Mech(
|
||||
DynamicMemoryStream cylStream( // FUN_004032dc, offset 0
|
||||
cylRes->resourceAddress, cylRes->resourceSize, 0);
|
||||
DamageLookupTable *table = new DamageLookupTable(this, &cylStream); // FUN_0049ea48
|
||||
Wword(0x111) = (int)table;
|
||||
damageLookupTable = (int)table; // named member (Wword absorbs!)
|
||||
DEBUG_STREAM << "[cyl] table '" << dzForName->resourceName
|
||||
<< "' layers=" << table->LayerCount() << "\n" << std::flush;
|
||||
}
|
||||
@@ -1407,9 +1413,9 @@ Mech::~Mech()
|
||||
<< "\n" << std::flush;
|
||||
}
|
||||
|
||||
if (Wword(0x111) != 0) // cylinder hit-location table (STEP 6)
|
||||
if (damageLookupTable != 0) // cylinder hit-location table (STEP 6)
|
||||
{
|
||||
delete (DamageLookupTable *)Wword(0x111); // frees layers/slices/entries
|
||||
delete (DamageLookupTable *)damageLookupTable; // frees layers/slices/entries
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user