Cockpit: the CONFIG-MODE weapon-regrouping session + the live-play fire fixes (tasks #6+#11)
TASK #6 -- the pod's in-cockpit weapon regrouping, fully reconstructed and live-verified (hold-configure -> tap fire button -> toggle membership -> release-commit): - MechWeapon handlers id 9 ConfigureMappables @004b9550 / id 10 ChooseButton @004b95b8 (binary table @0x511860; the old "Myomers fns" mislabel swept) + the GetMessageHandlers() accessor chain through Emitter/ProjectileWeapon/ MissileLauncher/GAUSS/PPC (empty per-class sets swallowed dispatch). - Mapper vtable truth: +0x38 EnterConfiguration / +0x3C ExitConfiguration / +0x40,+0x44 AddOrErase evt/dir. No "secondary vtable @0050f498", no "CreateTemporaryEventMappings" virtual (RP-name drift; swept incl CLASSMAP). L4 Enter/Exit rebuilt complete: StartMappableButtonsConfigure (the NonMapping 0x10000 <-> Mapping 0x8000 mode flip + the gauge's active-weapon latch) + the held-button re-arm + the 4 fire-button temp maps; only the RIO mapper implements the toggle (Thrustmaster no-ops = can't regroup). - MechSubsystem +0xE8/+0xEC corrected to controlDestination/controlMessageID (ex hostEntity/subsystemId2 mislabel); MechWeapon ctor defaults the destination to &fireImpulse (@004b99a8). - ConfigMapGauge state loop reconstructed (PE-recovered DAT_00518eb4 table; buttonGroup GetMapState sampler -- the "needs ModeManager" guard rationale was wrong). Finding [T1]: the shipped binary NEVER enables this gauge (no SetColor caller) -- authentically dormant; BT_CONFIGMAP=1 is the dev enable. - Dev harness: HOLD 'G' opens the session (BT_CONFIG_SLOT picks the weapon); BT_CONFIG_TEST scripts a headless verify. @004afbc4 corrected to its real Fail-trap body (the guessed AddOrErase(NULL) body would corrupt groups). - Bonus [T1]: the binary MechWeapon ATTRIBUTE table has ELEVEN entries (PercentDone..WeaponState) -- "TriggerState is the only one" was wrong. TASK #11 -- the user-reported live-play regressions (both real bugs): - PHANTOM FIRE: the mech4 bring-up shot block painted an explosion at the victim on its OWN 0.3s cadence whenever fire was held -- desynced once the authentic recharges landed. Retired (the real impact visual flows from each discharge via the messmgr SubmitExplosion). - WEAPON BRICKING (the "cuts out" bug): the Loading->Loaded snap window (+-0.01 around seekV) assumes the pod's LOCKED 60 fps; one port dt-spike jumps it, the byte-verified >1.0 clamp (_DAT_004ba830=0) zeroes readiness, and the weapon sticks in Loading at level ~10000 forever (observed live). Fixed with pod-frame (1/60s) sub-stepping of the binary's own Loading tick -- also fixes the I^2R integral over-heating generators on big steps. NEW GOTCHA CLASS recorded: reconstruction-gotchas #12 (frame-pacing trap). - Duty-cycle measured (max-rate autofire): generators equilibrate in the degradation band (recharge stretch ~3.5-4.4x), the FailureHeat breaker never trips solo, PPCs sustain ~11.8-damage full-charge fire. The slow kill pacing and recharge gaps are the AUTHENTIC heat economy; the pilot's counters (this regrouping UI, generator reassignment, coolant valves) are the reconstruction queue. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
4e63a7b6c3
commit
092408041c
@@ -59,6 +59,7 @@
|
||||
|
||||
#include <bt.hpp>
|
||||
#include <messmgr.hpp> // SubsystemMessageManager (task #8 damage submission)
|
||||
#include <mechmppr.hpp> // MechControlsMapper -- the config-session virtuals (task #6)
|
||||
#pragma hdrstop
|
||||
|
||||
#if !defined(MECHWEAP_HPP)
|
||||
@@ -81,7 +82,27 @@ Derivation
|
||||
"MechWeapon"
|
||||
);
|
||||
|
||||
Receiver::MessageHandlerSet MechWeapon::MessageHandlers;
|
||||
// task #6 -- the binary's MechWeapon handler table @0x511860 (section_dump:
|
||||
// {9, "ConfigureMappables"@0x511994, @004b9550}, {10, "ChooseButton"@0x5119A7,
|
||||
// @004b95b8}); chained onto the PoweredSubsystem set.
|
||||
const Receiver::HandlerEntry
|
||||
MechWeapon::MessageHandlerEntries[]=
|
||||
{
|
||||
MESSAGE_ENTRY(MechWeapon, ConfigureMappables), // id 9 @004b9550
|
||||
MESSAGE_ENTRY(MechWeapon, ChooseButton) // id 10 @004b95b8
|
||||
};
|
||||
|
||||
Receiver::MessageHandlerSet&
|
||||
MechWeapon::GetMessageHandlers()
|
||||
{
|
||||
static Receiver::MessageHandlerSet messageHandlers(
|
||||
ELEMENTS(MechWeapon::MessageHandlerEntries),
|
||||
MechWeapon::MessageHandlerEntries,
|
||||
PoweredSubsystem::GetMessageHandlers()
|
||||
);
|
||||
return messageHandlers;
|
||||
}
|
||||
|
||||
Simulation::AttributeIndexSet MechWeapon::AttributeIndex; // legacy empty member (superseded by GetAttributeIndex)
|
||||
|
||||
// gauge data-binding wave: OutputVoltage/PercentDone -> rechargeLevel (1.0 ==
|
||||
@@ -112,12 +133,89 @@ MechWeapon::AttributeIndexSet&
|
||||
MechWeapon::SharedData
|
||||
MechWeapon::DefaultData(
|
||||
&MechWeapon::ClassDerivations,
|
||||
MechWeapon::MessageHandlers,
|
||||
MechWeapon::GetMessageHandlers(),
|
||||
MechWeapon::GetAttributeIndex(),
|
||||
MechWeapon::StateCount
|
||||
);
|
||||
|
||||
|
||||
//#############################################################################
|
||||
// The CONFIG-MODE session handlers (task #6)
|
||||
//
|
||||
|
||||
//
|
||||
// @004b9550 -- id 9 "ConfigureMappables": the press-and-HOLD session bracket.
|
||||
// dataContents = +-(element+1) (press/release, the L4 button value convention).
|
||||
// Press: open the session on THIS weapon -- the roster-slot-0 mapper flips the
|
||||
// global mode NonMapping->Mapping, latches &fireImpulse as the active configure
|
||||
// target, and temp-maps the fire buttons to send ChooseButton (id 10) here.
|
||||
// Release: close the session (mode restored, temp layer stripped).
|
||||
// The +0x110 write (0 open / -1 idle) is the binary's config-session flag
|
||||
// (ctor default -1, part_012.c:15775); the port field carries the older name
|
||||
// vitalSubsystemIndex -- no confirmed reader yet (read-site survey pending).
|
||||
//
|
||||
void
|
||||
MechWeapon::ConfigureMappablesMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(message);
|
||||
|
||||
int value = message->dataContents; // +-(element+1)
|
||||
int element = ((value < 0) ? -value : value) - 1;
|
||||
|
||||
MechControlsMapper *mapper = ((Mech *)owner)->MappingMapper(); // **(mech+0x128)
|
||||
if (mapper == 0)
|
||||
{
|
||||
return; // (binary assumes slot 0 is live)
|
||||
}
|
||||
|
||||
if (value < 1)
|
||||
{
|
||||
mapper->ExitConfiguration(element); // vtbl+0x3C
|
||||
vitalSubsystemIndex = -1; // this+0x110 -> idle
|
||||
}
|
||||
else
|
||||
{
|
||||
vitalSubsystemIndex = 0; // this+0x110 -> session open
|
||||
mapper->EnterConfiguration( // vtbl+0x38
|
||||
element,
|
||||
(ControlsButton *)&fireImpulse, // this+0x31C (TriggerState)
|
||||
this,
|
||||
ChooseButtonMessageID, // 10
|
||||
ConfigureMappablesMessageID, // 9
|
||||
0); // active_message_id (direct bind)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// @004b95b8 -- id 10 "ChooseButton": while the session is open, a tapped fire
|
||||
// button sends its RAW 1-based value here; the mapper's direct AddOrErase
|
||||
// TOGGLES buttonGroup[value-1]'s permanent (0x10000) mapping onto
|
||||
// &fireImpulse -- join the group if absent, leave it if present. Press only.
|
||||
//
|
||||
void
|
||||
MechWeapon::ChooseButtonMessageHandler(
|
||||
ReceiverDataMessageOf<ControlsButton> *message
|
||||
)
|
||||
{
|
||||
Check(this);
|
||||
Check_Pointer(message);
|
||||
|
||||
if (message->dataContents > 0)
|
||||
{
|
||||
MechControlsMapper *mapper = ((Mech *)owner)->MappingMapper();
|
||||
if (mapper != 0)
|
||||
{
|
||||
mapper->AddOrErase( // vtbl+0x44 (direct overload)
|
||||
(unsigned int)message->dataContents, // RAW 1-based
|
||||
(ControlsButton *)&fireImpulse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//#############################################################################
|
||||
// Firing -- abstract base body
|
||||
//
|
||||
@@ -195,6 +293,12 @@ MechWeapon::MechWeapon(
|
||||
usesExternalModel = (strstr(GetName(), "EXT") != 0) ? True : False;
|
||||
|
||||
fireImpulse = 0.0f; // 0x31C
|
||||
// task #6: the binary MechWeapon ctor defaults its controls-destination
|
||||
// pass-through to &fireImpulse when the caller passes NULL (@004b99a8
|
||||
// `if (param_7==0) param_7 = this+0x31C`); the chain stores it at
|
||||
// MechSubsystem+0xE8/+0xEC where ConfigMapGauge's GetMapState reads it.
|
||||
controlDestination = (void *)&fireImpulse; // 0xE8
|
||||
controlMessageID = 0; // 0xEC
|
||||
rechargeLevel = 1.0f; // 0x320 (fully charged)
|
||||
previousFireImpulse = 0.0f; // 0x3A4
|
||||
recoil = 0.0f; // 0x3E8
|
||||
|
||||
Reference in New Issue
Block a user