the crit system, complete: two gap functions recovered, the dead sink revived, and a wrong verdict reversed (#80)
The whole critical-hit pipeline was dark, three layers deep, and one of those
layers had fooled us into a false conclusion about the 1995 binary itself.
LAYER 1 -- the trigger, recovered from the un-exported gap. The Mech MESSAGE
TABLE at 0x50bdf8 ({id, name, handler} rows) names the real
Mech::TakeDamageMessageHandler at 0x4a0230 -- message 0x12 "TakeDamage" --
plus seven sibling handlers (PlayerLink, RealMaxSpeed, BalanceCoolant,
Set/ClearBurningState, EjectPilot, DuckRequest). Inside it, the crit chance
at 0x4a0164: p = clamp(0.7 * damageLevel^2 + 0.01, 0..1), gated on the
player's simLive flag (+0x25c -- novice never crits), rolled PER BURST on the
current zone, skipping a zone already burning. Chance is ~1% on fresh armour,
~18% at half-stripped, ~58% at 90% -- crits arrive exactly as armour fails.
The handler's application loop replaces the engine base's single call, which
ignored burstCount entirely (multi-burst damage under-applied (burst-1)x).
Faithful shape: per burst, crit-roll -> CriticalHit @0049ccc4 (which routes
half the amount through the armour internally and picks ONE critical
subsystem by criticalWeight) else zone->TakeDamage -- then RE-RUN the
cylinder lottery from the impact point for the next burst, stopping early
once the mech is disabled. Multi-burst damage sprays across zones by design.
LAYER 2 -- the sink. MechSubsystem::TakeDamage was an empty btstubs stand-in;
the real body is at 0x4ac0bc (CLASSMAP had that address mislabeled
"HandleMessage"): zone damage, then on level >= 1.0 the Destroyed alarm, the
PrintState gate, the 1.0 pin, and -- for a vital subsystem -- the owner
mech's graphicAlarm to level 9, the same fall/death level the leg path
raises. That is the #28 vital-subsystem kill machinery, now real.
LAYER 3 -- the one that rewrites yesterday. The subsystem ctor DID copy
armour points + per-type scales into the private zone -- through the
ReconDamageZone PROXY, whose fields sit at struct offsets +4/+8, not the
binary's +0x140/+0x144. The floats landed on the engine object's header and
the real damageScale[] stayed zero. The 2026-07-28 experiment that "proved"
subsystem zones cannot be damaged -- and that the Myomers un-powered
self-repair was dead code in the original -- was measuring exactly this port
bug. Both verdicts reversed: the binary ctor (0x4ac7bb) initializes the zone
from the resource keys WeaponDamagePoints (required) + CriticalHitScoreBonus
(required) + Collision/Ballistic/Explosive/Laser/EnergyDamagePoints, none of
which the CSS parsed. Now parsed (with the binary's own error strings), and
the ctor writes the engine's NAMED members -- layout-parity holds, so they
land on +0x140/+0x144 faithfully. The Myomers repair branch is LIVE, in 1995
and here. KB corrected and swept (combat-damage, subsystems WAVE 6,
myomers.cpp, CLASSMAP).
Live-verified twice: [subarmor] prints real parsed scales for every subsystem
at spawn (HeatSink pts=10 scale=0.1x5, Condensers pts=5 scale=0.2x5, ...);
[critroll] landed full-chain crits in both runs (zone -> weighted pick ->
subsystem's own zone driven to 1.0 -> Destroyed); mech death/respawn and the
ammo gates un-regressed; zero crashes/asserts. Honest gaps: burst>1 spraying
is transcribed but not yet exercised live (self-damage fires burst=1), the
damageType==0 COLLISION divert (@0x49ffcc) is documented-not-reconstructed,
and the id-0x16 damage/kill report messages to the players (the authentic
stats plumbing, decoded to field level in the KB) are deferred to the #45
work.
Diags: BT_CRIT_LOG ([subarmor] + [critroll]), the existing BT_DMG_LOG.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
f7cf9850b1
commit
a5fb96ae96
@@ -580,6 +580,18 @@ void
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// #80 bridge: MechSubsystem::TakeDamage's vital-subsystem kill (@0x4ac126-
|
||||
// 0x4ac137: owner alarm+0x2C -> level 9). MechSubsystem's TU holds only an
|
||||
// incomplete Mech; this TU already writes graphicAlarm level 9 for the
|
||||
// leg-destruction path, so the vital path reuses the same complete-type site.
|
||||
//
|
||||
void BTMechVitalSubsystemKill(void *owner_mech)
|
||||
{
|
||||
if (owner_mech != 0)
|
||||
((Mech *)owner_mech)->graphicAlarm.SetLevel(9); // owner+0x2C, level 9
|
||||
}
|
||||
|
||||
//#############################################################################
|
||||
// CriticalHit -- @0049ccc4
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user