EJECT/PANIC wired: Mech::EjectPilot (id 0x19 @0049f854) + the crippled-mech gate
The button died twice before reaching game logic: no handler (0x19 was
unregistered) and no sender (the pod's panic was a control bit, not a
mappable). Both halves reconstructed from raw disasm -- the handler AND
its permission evaluator sat in export gaps.
@0049f854 EjectPilot: press-only; gated on ejectPermitted (@0x414) and
!IsDisabled; console eject notice (relay wire = tracked tail; the
suppressConsole@0x258 latch that prevents the death double-notify IS
wired); graphicAlarm -> 10, which kills via the >=9 predicate; then a
self TakeDamage {inflicting=SELF, zone -1, Explosive, amount =
ScenarioRole::killBonus}. Role layout byte-settled via the role reader
@00429bec dest offsets + the ctor record copy: +0x1c IS killBonus, +0x20
is the 4.10-only SpecialCaseDeathPenalty, +0x28 returnFromDeath (all
prior citations reconciled). KillBonus authors NOWHERE in shipped
content -> the charge is 0 and the ALARM does the killing: our bench
outcome is the pod outcome.
@0049fa1c EvaluateEjectPermission: eject only from a CRIPPLED mech --
bank coolant fraction < 0.05 | zero live generators | live weapons
below mech+0x448 (no exported writer: zero, clause inert) | leg-gimped
novice. A healthy mech REFUSES the button; no free resets.
Input: binding-engine "Eject" action -- Backspace / pad LeftThumb
(default profile + shipped CONTROLS.MAP). Bridges per the databinding
rule: weapon/generator/bank/player reads land in their complete TUs;
MechSubsystem gains the both-cells destroyed accessors (gotcha #22).
Bench scalpels: BT_EJECT_AT=<frame> (path-identical synthetic press),
BT_KILL_SUBSYS now takes a comma list.
Verified single-node: healthy press REFUSED (x2), four generators
killed, next press PUNCH-OUT -> death, wreck smoke, respawn; the
respawned mech refuses again (permission re-evaluates after Reset).
Death rides the normal damage/death chain, so MP replication is the
proven path. Tails tracked: console relay notice, RIO 0x38 panic
control, alarm-10 eject audio/canopy, SpecialCaseDeathPenalty consumer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
e1ae92264a
commit
e996be249d
@@ -1242,3 +1242,25 @@ Subsystem *CreateProjectileWeaponSubsystem(Mech *owner, int id, void *seg)
|
||||
return (Subsystem *) new (Memory::Allocate(0x448))
|
||||
ProjectileWeapon(owner, id, (ProjectileWeapon::SubsystemResource *)seg, ProjectileWeapon::DefaultData);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
// BTWeaponCountsForEject -- complete-type bridge for the EJECT-permission
|
||||
// evaluator (Mech::EvaluateEjectPermission, @0049fa1c; issue: eject/panic).
|
||||
// The binary's weapon clause: MechWeapon-derived (0x511830), not destroyed,
|
||||
// and -- for the ProjectileWeapon family only (0x5121a8) -- weaponAlarm
|
||||
// (@0x364) != 7 (NoAmmo): a dry ballistic rack is not a fighting weapon.
|
||||
// Destroyed is the BOTH-CELLS test (gotcha #22: statusAlarm level + the
|
||||
// port's split simulationState). Returns -1 = not a weapon, else 0/1.
|
||||
//===========================================================================//
|
||||
int BTWeaponCountsForEject(Subsystem *sub)
|
||||
{
|
||||
if (sub == 0 || !sub->IsDerivedFrom(MechWeapon::ClassDerivations))
|
||||
return -1;
|
||||
MechWeapon *w = (MechWeapon *)sub;
|
||||
if (w->SimulationStateCell() == 1 || w->StatusAlarmLevel() == 1)
|
||||
return 0; // destroyed (both cells)
|
||||
if (sub->IsDerivedFrom(ProjectileWeapon::ClassDerivations)
|
||||
&& ((ProjectileWeapon *)sub)->WeaponAlarmLevel() == 7)
|
||||
return 0; // NoAmmo (@0x364 == 7)
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user