Gitea #53: generators can be switched off -- ToggleGeneratorOnOff reconstructed from @004b1ed0
TWO missing pieces, both now in place.
1. Generator had NO handler set of its own, so every message aimed at it hit a
default-constructed blackhole. Proved empirically with the new
unhandled-message trace by pressing button 0x1A:
[msg] UNHANDLED: Generator has no handler for message id 4 -- silently dropped
Added Generator::GetMessageHandlers() chained to **HeatSink**, deliberately NOT
PoweredSubsystem: id 4 there is SelectGeneratorA (the weapon-side generator
SELECTION that already works), so chaining to it would have made these four
buttons invoke the WRONG function instead of doing nothing. HeatSink owns id 3
(ToggleCooling), leaving id 4 free.
2. ToggleGeneratorOnOff had no body at all (0 references in game/). Transcribed
instruction-for-instruction from @004b1ed0:
- call @004ac9c8 -> BTPlayerRoleLocksAdvanced: a NOVICE pilot cannot use it
- [msg+0xc] <= 0 -> press only, ignore the release
- ON : startTimer = 0; if heatAlarm(@0x184) < 1 also stateAlarm -> 0
(Starting, so it spins up -- a heat-faulted generator keeps its fault
level); generatorOn = 1, coolantAvailable = 1, coolantFlowScale = 1.0
- OFF : stateAlarm -> 1 (GeneratorIdle); generatorOn = 0,
coolantAvailable = 0, coolantFlowScale = 0 (its coolant share is
released back to the loop)
So taking a generator off line idles it, drops its coolant draw and stops it
feeding its taps -- the authentic heat-management trade from the manual.
VERIFIED LIVE (BT_BTNTEST=0x1A,400,900 through the real click seam):
[btntest] PRESS 0x1a at poll 400
[gensel] GeneratorA generator OFF LINE (stateAlarm 1, coolantFlowScale 0)
and the UNHANDLED warning for Generator is gone.
Answers Cyd's report from two playtests ('still cannot turn of gennies'). Note
this is the ON/OFF control -- generator SELECTION (which generator a subsystem
draws from) is a different message and already worked.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0166KTsC7ADm7VXEi1HF1jNg
This commit is contained in:
co-authored by
Claude Opus 5
parent
33ca99eb69
commit
62513b2f8a
@@ -1085,11 +1085,100 @@ Logical Generator::TestClass(Mech &) { return True; }
|
||||
Logical Generator::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); }
|
||||
|
||||
//
|
||||
// Generator vtable slot 10 -- recovered VERBATIM from the surviving GNRATOR.TCP
|
||||
// fragment (the one Generator method the @0x4b02f0.. cluster decomp omitted; see
|
||||
// gnrator.cpp). Chains the HeatableSubsystem reset (NOT the HeatSink one --
|
||||
// matching the inlined base chain seen across the HeatSink family) and forces
|
||||
// the generator output cold.
|
||||
Receiver::MessageHandlerSet&
|
||||
Generator::GetMessageHandlers()
|
||||
{
|
||||
//
|
||||
// Gitea #53. Chains **HeatSink**, deliberately NOT PoweredSubsystem: id 4 on
|
||||
// PoweredSubsystem is `SelectGeneratorA` (the weapon-side generator SELECTION,
|
||||
// which already works), so chaining there would make the four ON/OFF buttons
|
||||
// invoke the wrong function instead of doing nothing. HeatSink owns id 3
|
||||
// (ToggleCooling) and chains onward to the root, leaving id 4 free for us.
|
||||
//
|
||||
static const Receiver::HandlerEntry entries[]=
|
||||
{
|
||||
MESSAGE_ENTRY(Generator, ToggleGeneratorOnOff) // id 4 @004b1ed0
|
||||
};
|
||||
static Receiver::MessageHandlerSet messageHandlers(
|
||||
ELEMENTS(entries), entries,
|
||||
HeatSink::GetMessageHandlers()
|
||||
);
|
||||
return messageHandlers;
|
||||
}
|
||||
|
||||
//
|
||||
// @004b1ed0 -- ToggleGeneratorOnOff: the pod's Generator A-D ON/OFF buttons (RIO
|
||||
// addresses 0x1A-0x1D on the radar rail, one per generator). Transcribed
|
||||
// instruction-for-instruction from the binary; the body did not exist before
|
||||
// (Gitea #53 -- 0 references in game/).
|
||||
//
|
||||
// call 0x4ac9c8(this); if (ret) return; -> BTPlayerRoleLocksAdvanced: a
|
||||
// NOVICE pilot cannot touch it
|
||||
// if ([msg+0xc] <= 0) return; -> press only, ignore the release
|
||||
// if ([this+0x1d4] != 0) goto OFF -> generatorOn -> we are turning it off
|
||||
//
|
||||
// ON: eax = [this+0x184] -> heatAlarm level
|
||||
// if (eax >= 1) { [this+0x1f0] = 0; } -> heat degraded/failed: clear the
|
||||
// start timer but LEAVE the state
|
||||
// alarm in its fault level
|
||||
// else { [this+0x1f0] = 0;
|
||||
// Set_Alarm_Level(this+0x1fc, 0); }
|
||||
// -> healthy: also drop the state alarm
|
||||
// to Starting so it spins up
|
||||
// [this+0x1d4] = 1 -> generatorOn = 1
|
||||
// [this+0x134] = 1 -> coolantAvailable = 1
|
||||
// [this+0x15c] = 1.0f -> coolantFlowScale = 1.0
|
||||
//
|
||||
// OFF: Set_Alarm_Level(this+0x1fc, 1) -> stateAlarm = GeneratorIdle
|
||||
// [this+0x1d4] = 0 -> generatorOn = 0
|
||||
// [this+0x134] = 0 -> coolantAvailable = 0
|
||||
// [this+0x15c] = 0.0f -> coolantFlowScale = 0 (its coolant
|
||||
// share is released to the loop)
|
||||
//
|
||||
// So taking a generator off line idles it, drops its coolant draw, and -- via the
|
||||
// state machine reading generatorOn -- stops it supplying voltage to its taps.
|
||||
// That is the authentic heat-management trade the manual describes.
|
||||
//
|
||||
void
|
||||
Generator::ToggleGeneratorOnOffMessageHandler(ReceiverDataMessageOf<int> *message)
|
||||
{
|
||||
if (BTPlayerRoleLocksAdvanced(owner)) // @004ac9c8 -- NOVICE lock
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (message->dataContents <= 0) // press only
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (generatorOn == 0)
|
||||
{
|
||||
// ---- turning it ON ----
|
||||
startTimer = 0.0f; // @0x1F0
|
||||
if ((unsigned)heatAlarm.GetLevel() < 1) // @0x184 -- healthy
|
||||
{
|
||||
stateAlarm.SetLevel(0); // @0x1FC -> Starting (spin up)
|
||||
}
|
||||
generatorOn = 1; // @0x1D4
|
||||
coolantAvailable = 1; // @0x134
|
||||
coolantFlowScale = 1.0f; // @0x15C
|
||||
}
|
||||
else
|
||||
{
|
||||
// ---- taking it OFF LINE ----
|
||||
stateAlarm.SetLevel(1); // @0x1FC -> GeneratorIdle
|
||||
generatorOn = 0; // @0x1D4
|
||||
coolantAvailable = 0; // @0x134
|
||||
coolantFlowScale = 0.0f; // @0x15C
|
||||
}
|
||||
|
||||
if (getenv("BT_FIRE_LOG") || getenv("BT_HEAT_LOG"))
|
||||
DEBUG_STREAM << "[gensel] " << GetName() << " generator "
|
||||
<< (generatorOn ? "ON LINE" : "OFF LINE")
|
||||
<< " (stateAlarm " << stateAlarm.GetLevel()
|
||||
<< ", coolantFlowScale " << coolantFlowScale << ")" << std::endl;
|
||||
}
|
||||
|
||||
//
|
||||
void
|
||||
Generator::ResetToInitialState(Logical powered)
|
||||
|
||||
Reference in New Issue
Block a user