#86: destroyed weapons can no longer fire -- the fire gates read a
never-written cell (the split-cell gotcha) Both weapon fire gates (ProjectileWeapon gate 1 @4bbd36, Emitter hard-failure @4baab9) test the binary's subsystem+0x40 for Destroyed(1). In the 1995 layout that offset sits INSIDE the embedded status alarm (statusAlarm@0x2C + level@+0x14 = 0x40) -- ONE cell, written by ForceCriticalFailure when a zone's crit cascade kills the subsystem. The port models the same address as TWO members: the AlarmIndicator AND a plain int simulationState@0x40. Every destruction path writes the ALARM (so the MFD draws its X correctly) while the gates read the plain int, which nothing ever writes -- so a weapon on a blown-off arm showed destroyed on every panel and kept firing and scoring, locally and on peers (night-7: all three testers, screenshots of a missile leaving a destroyed pod). The tell had been sitting in our own logs for weeks: [ammo] SRM6_1 -> NoAmmo (gate1): destroyed=0 ... on a mech whose launcher was X'd out. Fix: both gates now read statusAlarm.GetLevel()==1 as well as the int. Also added: the crit-cascade log names the destroyed subsystem, a BT_SELF_DAMAGE_ZONE=dz_* named-zone bench mode, and BT_KILL_SUBSYS=<name> (force ForceCriticalFailure on one named subsystem -- the exact call the zone cascade makes, so a bench can ask 'the panel says dead, does it still shoot?' without hunting for the zone that carries a given weapon). Verified A/B in ONE run: before the kill both SRM6 launchers fired 2 salvos each; after, the destroyed launcher fired ZERO (gate log destroyed=1) while its twin kept firing normally. KB: new gotcha #22 (the SPLIT CELL -- one binary offset, two port members, only one written; sibling of #1) + combat-damage entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019Zh7PTkFy4KwTzVighLR9J
This commit is contained in:
co-authored by
Claude Fable 5
parent
62fc8409b6
commit
5410371b0c
@@ -6035,6 +6035,14 @@ void
|
||||
if (zz != 0 && zz->IsLegZone()) { sdZone = zi; break; }
|
||||
}
|
||||
}
|
||||
else if (ze[0] == 'd' && ze[1] == 'z')
|
||||
{
|
||||
// #86 bench: a NAMED zone (e.g. dz_rarm) resolved via
|
||||
// the engine's own name->index map -- lets a bench
|
||||
// destroy a specific ARM and watch its weapons brick.
|
||||
int byName = Entity::GetDamageZoneIndex(CString(ze));
|
||||
if (byName >= 0) sdZone = byName;
|
||||
}
|
||||
else
|
||||
sdZone = atoi(ze);
|
||||
}
|
||||
@@ -6052,6 +6060,36 @@ void
|
||||
}
|
||||
}
|
||||
|
||||
// #86 BENCH (BT_KILL_SUBSYS=<name>): force the AUTHENTIC destruction of
|
||||
// one named subsystem -- MechSubsystem::ForceCriticalFailure, the exact
|
||||
// call the zone crit-cascade (SendSubsystemDamage) makes, and the thing
|
||||
// that raises the MFD's X. Lets a bench answer "the panel says it's
|
||||
// dead -- does it still shoot?" without hunting for the zone that
|
||||
// happens to carry a given weapon (per-mech, and dz_* names vary).
|
||||
// Env-gated, one-shot, viewpoint mech only.
|
||||
if ((Entity *)this == application->GetViewpointEntity()
|
||||
&& getenv("BT_KILL_SUBSYS"))
|
||||
{
|
||||
static int s_ksFrame = 0;
|
||||
if (++s_ksFrame == 900) // ~15 s in, after the mech settles
|
||||
{
|
||||
const char *want = getenv("BT_KILL_SUBSYS");
|
||||
for (int i = 2; i < GetSubsystemCount(); ++i)
|
||||
{
|
||||
Subsystem *s = GetSubsystem(i);
|
||||
if (s == 0 || s->GetName() == 0) continue;
|
||||
if (stricmp(s->GetName(), want) != 0) continue;
|
||||
if (!s->IsDerivedFrom(MechSubsystem::ClassDerivations)) continue;
|
||||
((MechSubsystem *)s)->SetSubsystemDamageLevel(1.0f);
|
||||
((MechSubsystem *)s)->ForceCriticalFailure();
|
||||
DEBUG_STREAM << "[killsub] '" << s->GetName()
|
||||
<< "' force-destroyed (statusAlarm=1, zone=1.0)"
|
||||
<< std::endl << std::flush;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// task #13 scripted verify (BT_VALVE_TEST=1): one MoveValve press at
|
||||
// frame ~600 -- Condenser1's valveState cycles 1 -> 5, so the flow
|
||||
// redistribution gives it 5/10 of the total coolant flow ([valve] log
|
||||
|
||||
Reference in New Issue
Block a user