diff --git a/restoration/source410/BT/AMMOBIN.CPP b/restoration/source410/BT/AMMOBIN.CPP index 93f87b0e..88dd24f9 100644 --- a/restoration/source410/BT/AMMOBIN.CPP +++ b/restoration/source410/BT/AMMOBIN.CPP @@ -273,14 +273,20 @@ void // // The charge: rounds x the per-round damage. // - // [T1] THE PER-ROUND FIGURE IS NOT SOURCED YET. The binary reads it - // from the bin's streamed EXPLOSION RECORD (+0x1f4, the second field - // of the block our `cookOffState[12]` reserves and nothing parses), - // then writes the product back into a copy of that record. Until - // that record is parsed we stand in the FED WEAPON's authored - // per-shot damage -- the right order of magnitude and the physically - // sensible reading, but a stand-in; the first pass over the ammo - // resource block should replace it. + // [T2] DELIBERATE DIVERGENCE -- WE ARE MORE LETHAL THAN THE ORIGINAL. + // The binary multiplies the rounds by the amount held in the bin's own + // Damage struct (+0x1f4; our `cookOffState[12]` IS that struct). But + // across the whole AmmoBin TU that Damage is only default-constructed + // and read -- nothing writes its amount -- so the shipped cook-off + // appears to compute ZERO damage: it destroys the bin, announces every + // zone, and delivers nothing. + // + // Either the feature is vestigial in 4.10, or a writer lives outside + // the TU (a table-registered handler is the place to look), or the + // multiplier cell is misidentified. Until that is settled we stand in + // the FED WEAPON's per-shot damage, which makes the mechanic real -- + // an inert mechanic is indistinguishable from an unfinished one and + // would hide the question. See MECH4.NOTES.md 5.3.138. // // (The first attempt used `heatPerRound`, a HEAT figure of about // 3e-9, which made the whole detonation a silent no-op -- caught only diff --git a/restoration/source410/BT/MECH4.NOTES.md b/restoration/source410/BT/MECH4.NOTES.md index 58008464..d6bd4ebb 100644 --- a/restoration/source410/BT/MECH4.NOTES.md +++ b/restoration/source410/BT/MECH4.NOTES.md @@ -752,3 +752,48 @@ computed 4.8e-08 of damage and did nothing at all -- a mechanic that fires, announces itself, and is silently inert. Only printing the arithmetic in the soak log exposed it. Log the numbers, not just the event. + +## 5.3.138 -- THE COOK-OFF CHARGE: our version may be MORE lethal than the original + +Chasing the 5.3.137 [T1] to retire it produced an uncomfortable answer +that must not be papered over. + +First, two corrections to my own 5.3.137 note: + +* `FUN_0041db7c` is the engine's **Damage constructor** (it zeroes the + amount, seeds the force vector, sets the normal to (0,1,0) and a + trailing flag). So the bin's `+0x1f0` block is a **Damage struct**, not + an "explosion record", and `+0x1f4` is simply its `damageAmount`. Our + `cookOffState[12]` is therefore a `Damage` member in disguise. +* The resource read I thought filled it (`param_1[0x7d] = *(param_4 + + 0x108)`) belongs to the **Generator** ctor @004b225c -- same dword + index, different class. The per-class offset trap, twice in two days. + +Now the uncomfortable part. Across the WHOLE AmmoBin TU +(@004bd060..@004bd6f0) that Damage is only ever: + +* default-constructed by the ctor (`FUN_0041db7c(bin + 0x1f0)`), and +* READ by CookOff. + +Nothing writes its amount. The constructor leaves it **0**, so +`rounds * 0 == 0`: **the shipped game's ammo cook-off appears to compute +zero damage.** It destroys the bin and announces "ammo explosion +damaging " for every zone, then delivers nothing. + +Three readings, none yet eliminated: the feature is vestigial in 4.10; a +writer exists outside the TU (a message handler registered in a table +elsewhere is the obvious candidate, and is where to look next); or our +identification of the multiplier cell is wrong. + +**THEREFORE THE LANDING IS RE-MARKED [T2], A DELIBERATE DIVERGENCE, NOT +[T1] STAGING.** With the fed weapon's per-shot damage standing in, OUR +cook-off does 500-800 points across the zones and destroys subsystems, +where the shipped one -- as far as this decode can see -- does nothing. +That is us being MORE lethal than the original, which is exactly the kind +of silent gameplay drift this project exists to avoid. It is left ON +because an inert mechanic is indistinguishable from an unfinished one and +would hide the question, but it is now flagged in the code, here, and to +the operator, and `BT_FORCE_COOKOFF` is the only way to trigger it +without genuine heat failure. + +Resolve before this is ever considered authentic.