Cockpit: GENERATOR POWER ROUTING -- assign weapons to generators (task #12)
The pilot's second heat-management tool: the PoweredSubsystem message table
@0x50F4EC (ids 4-8) registered and implemented -- SelectGeneratorA-D
(@004b099c..@004b0a74: FindGeneratorByNumber roster walk on generatorNumber
@0x1E0 -> AttachToVoltageSource re-tap with tap accounting -> modeAlarm
Connected) and ToggleGeneratorMode (@004b0abc: Manual -> Auto -> detach+Manual
cycle). Weapons inherit via the MechWeapon handler chain. Desktop: F5-F8
assign the selected weapon (BT_CONFIG_SLOT) to Generator A-D, F9 toggles
reconnect mode; BT_GENSEL_TEST scripts a headless verify.
Verified live end-to-end: dispatch -> handler -> re-tap ("PPC_1 ->
GeneratorD (tapped)") -> the charging I^2R physically moved (GenD cold ~90K
baseline -> ~1570K carrying the PPC; GenA relieved), stable over a sustained
autofire soak with thermal-breaker trips.
FOUR defects found and fixed on the way [all T1/T2]:
- THE e17 HEAT EXPLOSION: Generator::SourceLevel misread *(this[0x38]+0x158)
as linkedSinks->heatEnergy; it is the engine-base DamageZone @0xE0 ->
damageLevel [0..1] (the same named-member pattern as the bank radiator's
zone read). A breaker-restarting generator emitted (1 - 4e8) x 10000
volts; squared through the customers' I^2R feed, one restart blew the
whole thermal network to e17. Authentic: a damaged generator yields
proportionally less voltage.
- FUN_004ac9c8 is NOT "IsDamaged": raw body = owner -> mech+0x190 player ->
roleClassIndex(+0x274) == 0 -- the ROOKIE-role lockout for advanced
cockpit systems. New bridge BTPlayerRoleLocksAdvanced (NULL player =
unlocked [T3]; bring-up role 2 = unlocked). The old stand-in gated the
handlers off permanently (healthy subsystems have simulationState==1).
- MESSAGE_ENTRY tables must be FUNCTION-LOCAL statics inside the accessor:
as namespace-scope arrays they are read by other TUs' static-init chains
before their own initializers run -- Build copies zeros and every id in
the table is silently dropped (ids 9/10 only worked by TU-order luck;
both tables relocated; gotcha recorded, reconstruction-gotchas #9).
- The AutoConnect hunt scanned GetSegment() -- the raw @004b0bd0 walks the
subsystem ROSTER (+0x124/+0x128); EntitySegments were being cast to
Subsystems (the classic +0x128 gotcha).
Also: the dense handler table's GAP slots (skipped ids) are uninitialized
heap -- the name-based Find strcmp-walks them and AVs; diagnostic probes use
the id-based Find only (the 1995 binary's own tables carry the same holes).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
092408041c
commit
d7b900d108
@@ -645,6 +645,8 @@ static int gBTLaserKey = 0; // raw key states (set by the keyboar
|
||||
static int gBTPPCKey = 0;
|
||||
static int gBTMissileKey = 0;
|
||||
static int gBTConfigKey = 0; // task #6: HOLD 'G' = the weapon-configure button
|
||||
static int gBTGenSelKey = 0; // task #12: F5..F8 = SelectGeneratorA..D, F9 = mode toggle
|
||||
// (0 idle; else the message id 4..8)
|
||||
|
||||
// Damage: each shot dispatches a REAL Entity::TakeDamageMessage to the target. Now
|
||||
// that the damage zones are constructed (mech.cpp Pass-3 zone build), the engine base
|
||||
@@ -1529,6 +1531,15 @@ void
|
||||
// weapon (BT_CONFIG_SLOT, default: the first weapon); while
|
||||
// held, the fire keys TOGGLE its group membership.
|
||||
gBTConfigKey = focused && (pAsync('G') & dn) ? 1 : 0;
|
||||
// task #12: F5..F8 assign the selected weapon to Generator
|
||||
// A..D; F9 toggles Manual/Auto reconnect.
|
||||
gBTGenSelKey =
|
||||
(focused && (pAsync(0x74 /*F5*/) & dn)) ? 4
|
||||
: (focused && (pAsync(0x75 /*F6*/) & dn)) ? 5
|
||||
: (focused && (pAsync(0x76 /*F7*/) & dn)) ? 6
|
||||
: (focused && (pAsync(0x77 /*F8*/) & dn)) ? 7
|
||||
: (focused && (pAsync(0x78 /*F9*/) & dn)) ? 8
|
||||
: 0;
|
||||
// gBTDrive.fire = "any weapon trigger down" (feeds the bring-up
|
||||
// damage dispatcher + the beam-visual keepalive)
|
||||
gBTDrive.fire = (gBTLaserKey || gBTPPCKey || gBTMissileKey) ? 1 : 0;
|
||||
@@ -3101,6 +3112,67 @@ void
|
||||
}
|
||||
|
||||
|
||||
// task #12 scripted verify (BT_GENSEL_TEST=1): one SelectGeneratorD
|
||||
// press at frame ~2500 -- the PPC re-taps from its authored GeneratorA
|
||||
// onto GeneratorD; the charging I^2R then lands on GenD ([heat-t]).
|
||||
if ((Entity *)this == application->GetViewpointEntity()
|
||||
&& getenv("BT_GENSEL_TEST"))
|
||||
{
|
||||
static int s_gsFrame = 0;
|
||||
++s_gsFrame;
|
||||
gBTGenSelKey = (s_gsFrame >= 600 && s_gsFrame < 610) ? 7 : 0;
|
||||
}
|
||||
|
||||
// task #12 dev harness: the POWER-ROUTING buttons. F5..F9 edge ->
|
||||
// dispatch SelectGeneratorA..D / ToggleGeneratorMode (ids 4..8) to the
|
||||
// selected weapon -- the same ReceiverDataMessageOf<ControlsButton>
|
||||
// press payload the pod's aux-panel EventMappings deliver. The
|
||||
// handler chain is PoweredSubsystem's (weapons inherit via MechWeapon).
|
||||
if ((Entity *)this == application->GetViewpointEntity())
|
||||
{
|
||||
static int s_prevGenSel = 0;
|
||||
if (gBTGenSelKey != s_prevGenSel)
|
||||
{
|
||||
int pressedID = gBTGenSelKey; // 0 on release
|
||||
s_prevGenSel = gBTGenSelKey;
|
||||
if (pressedID != 0)
|
||||
{
|
||||
Subsystem *weapon = 0;
|
||||
const char *slotEnv = getenv("BT_CONFIG_SLOT");
|
||||
int wantSlot = (slotEnv != 0) ? atoi(slotEnv) : -1;
|
||||
for (int s = 1; s < GetSubsystemCount(); ++s)
|
||||
{
|
||||
Subsystem *sub = GetSubsystem(s);
|
||||
if (sub == 0)
|
||||
continue;
|
||||
int cid = (int)sub->GetClassID();
|
||||
if (wantSlot >= 0 ? (s == wantSlot)
|
||||
: (cid == 0xBC8 || cid == 0xBCA || cid == 0xBCE
|
||||
|| cid == 0xBD0 || cid == 0xBD4))
|
||||
{
|
||||
weapon = sub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (weapon != 0)
|
||||
{
|
||||
if (getenv("BT_FIRE_LOG"))
|
||||
{
|
||||
extern void BTGenSelProbe();
|
||||
BTGenSelProbe();
|
||||
DEBUG_STREAM << "[gensel-tx] id=" << pressedID
|
||||
<< " -> " << weapon->GetName() << std::endl;
|
||||
}
|
||||
ReceiverDataMessageOf<ControlsButton> msg(
|
||||
pressedID /*4..8 (powersub.hpp ids)*/,
|
||||
sizeof(ReceiverDataMessageOf<ControlsButton>),
|
||||
(ControlsButton)1 /*press*/);
|
||||
weapon->Dispatch(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// task #6 dev harness: the config-session BRACKET. 'G' edge ->
|
||||
// dispatch ConfigureMappables (id 9) press/release to the selected
|
||||
// weapon -- the exact ReceiverDataMessageOf<ControlsButton> payload
|
||||
|
||||
Reference in New Issue
Block a user