Fix 1 (Gitea #12): disasm-exact ProjectileWeaponSimulation @004bbd04 + the dirty-bit sweep
Replace the RivetGun-modeled ProjectileWeaponSimulation body with the fully recovered binary machine (capstone disasm, every branch address-cited): - gate 1 @4bbd36: simulationState@0x40==1 (destroyed) || heatAlarm==FailureHeat || owner disabled -> recoil=rechargeRate + alarm 7 (was: simulationFlags==1) - gate 2 @4bbd71: bin alarm 2/3 or bin destroyed -> alarm 7 re-pinned per frame - Loaded @4bbec2: DENIED shots (viewFireEnable off / no owner target) blip SetLevel(4);SetLevel(2) and STAY LOADED, no ammo pull (the old FireWeapon early-returns under an unconditionally-cycling caller faked a full firing pip cycle -- the "missiles cycle but never launch" incident mechanic); the ammo pull is bin->FeedAmmo @4bbee6 in the CALLER; both updateModel|=1 marks (@4bbf05/@4bbf4c = ForceUpdate) bracket FireWeapon; recoil set @4bbf51 - Loading @4bbdd2: recoil bleeds ONLY here at electrical Ready and CLAMPS at 0 (it ran to -114 before); bin Loaded -> weapon Loaded - 7 @4bbe4d: binary-faithful roach motel (re-asserted unconditionally; recovery = ResetToInitialState only) - slot 17 @004b9c9c reconstructed as MechWeapon::ComputeOutputVoltage (rechargeLevel=(rechargeRate-recoil)/rechargeRate, Emitter overrides with @4ba738) and called from Loading/7 -- the launcher recharge dial ANIMATES (the old "authentically static" claim was wrong) FireWeapon bodies stripped to heat+spawn only per @004bcc60 (no view gate, no ConsumeRound, no recoil); ConsumeRound retired (not a binary method). Gotcha #20 sweep (all sites disasm-verified): simulationFlags|=0x1 == engine DelayWatchersFlag (audio watchers muted forever) removed everywhere -- projweap/mislanch fire marks, ProjectileWeapon::ResetToInitialState (@4bbb47 = updateModel|=1); Emitter::SetDirty retired and split per binary site into ForceUpdate() (@4bafaa/@4ba55d) vs ExecuteOnUpdate() (@4ba99a/@4ba943); Emitter fault gate GetFlags()==1 -> simulationState==1 (@4baab9). AmmoBin::GetAmmoState() accessor added (named-member read of ammoAlarm@0x1A8). BT_LOOK_TEST=<frame> scripted verify added (mech4.cpp): holds the rear-view button 300f on/300f off to drive viewFireEnable headlessly. Verified solo ARENA1 (bhk1, autofire): 54-60 [projectile] PUSH + impact smoke; look-back denial window = trigger pulses, state stays 2, zero launches, resumes on release; enemy (disabled) mech launchers pinned 7 + full recoil; STREAK-6 recharge dial sweeps across BT_SHOT frames; lasers fire throughout; zero gauge faults. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
2215932016
commit
2edde29671
@@ -212,8 +212,16 @@ LWord Emitter::GetFlags() { return simulationFlags; }
|
||||
// the emitter family (task #10) -- an overheated emitter resets its firing
|
||||
// state and holds currentLevel at 0 until it cools below FailureTemperature.
|
||||
int Emitter::GetFaultState() { return heatAlarm.GetLevel(); }
|
||||
void Emitter::SetDirty() { simulationFlags |= 0x1; }
|
||||
void Emitter::ClearDirty() { simulationFlags &= ~0x2; }
|
||||
// Gitea #12 / gotcha #20: SetDirty() { simulationFlags |= 0x1 } RETIRED -- bit 0
|
||||
// of simulationFlags is the engine DelayWatchersFlag (SIMULATE.h:170): once set,
|
||||
// PerformAndWatch skips this subsystem's ExecuteWatchers (the AUDIO watchers)
|
||||
// FOREVER. The binary sites it transcribed are two DIFFERENT writes:
|
||||
// `or word [this+0x18], 1` == updateModel |= 1 == engine ForceUpdate()
|
||||
// (FireWeapon tail @4bafaa, ResetToInitialState tail @4ba55d)
|
||||
// `or dword [this+0x28], 2` == DontExecuteFlag == engine ExecuteOnUpdate()
|
||||
// (ServiceDischarge idle @4ba99a + beam-end @4ba943)
|
||||
// Call sites now use the engine calls directly.
|
||||
void Emitter::ClearDirty() { simulationFlags &= ~0x2; } // AlwaysExecute (@004ba65c write path)
|
||||
|
||||
|
||||
//#############################################################################
|
||||
@@ -344,7 +352,7 @@ void
|
||||
? *(Entity **)((char *)owner + 0x388) : 0; // 0x474 <- mech target entity
|
||||
targetLocalFlag = 1; // 0x470
|
||||
|
||||
SetDirty(); // this+6 |= 1 (needs replication)
|
||||
ForceUpdate(); // @4bafaa `or word [this+0x18],1` (updateModel -- needs replication)
|
||||
}
|
||||
|
||||
//
|
||||
@@ -400,9 +408,12 @@ void
|
||||
}
|
||||
targetWithinRange = UpdateTargeting(); // @004b9bdc -> this+0x34c
|
||||
|
||||
// hard failure: powered-off, faulted, or the OWNING MECH destroyed (@004baa88
|
||||
// checks IsDestroyed on the owner -- a dead mech's weapons drop everything)
|
||||
if (GetFlags() == 1 || GetFaultState() == 2 || BTMechDestroyed((Entity *)owner))
|
||||
// hard failure @4baab9: weapon DESTROYED (`simulationState@0x40 == 1` -- the
|
||||
// old `GetFlags() == 1` was the gotcha-#20 mis-transcription onto
|
||||
// simulationFlags@0x28, a latent kill-switch), own heatAlarm at FailureHeat
|
||||
// (this+0x184 == 2), or the owning mech disabled (FUN_0049fb54) -- a dead
|
||||
// mech's weapons drop everything.
|
||||
if (simulationState == 1 || GetFaultState() == 2 || BTMechDestroyed((Entity *)owner))
|
||||
{
|
||||
ResetFiringState(); // @004ba9a8
|
||||
currentLevel = 0.0f; // 0x414
|
||||
@@ -541,7 +552,7 @@ void
|
||||
{
|
||||
if (firingActive == 0) // 0x418
|
||||
{
|
||||
SetDirty(); // this+0x28 |= 2
|
||||
ExecuteOnUpdate(); // @4ba99a `or dword [this+0x28],2` (DontExecuteFlag)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -554,7 +565,7 @@ void
|
||||
weaponAlarm.SetLevel(2); // Loaded
|
||||
beamFlag = 0; // 0x46c
|
||||
dischargeTimer = dischargeTime; // 0x440 = 0x43c
|
||||
SetDirty();
|
||||
ExecuteOnUpdate(); // @4ba943 `or dword [this+0x28],2`
|
||||
// replicate the beam END: one final Emitter update record turns the
|
||||
// peer's copy off (the 1995 flush wrote idle-flagged subsystems too).
|
||||
ForceUpdate();
|
||||
@@ -835,7 +846,7 @@ void
|
||||
beamScale = Vector3D(1.0f, 1.0f, 1.0f); // 0x42c
|
||||
beamOrientation = EulerAngles(Radian(0.0f), Radian(0.0f), Radian(0.0f)); // 0x41c
|
||||
firingActive = 0; // 0x418
|
||||
SetDirty(); // this+6 |= 1
|
||||
ForceUpdate(); // @4ba55d `or word [this+0x18],1` (updateModel)
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user