Gauges: convert generator-voltage bar to named-member bridge
The eng-page generator-voltage bar (evolt.pcc, ScalarBarGauge @004c721c) and the MyomerCluster seek-voltage graph were fed by GeneratorVoltageConnection, which walked the same dead path as the generator-letter lamp: ResolveLink(AttributePointerOf(subsystem,"InputVoltage")) -> read resolved +0x1DC == Generator::outputVoltage. The BT_DEV_GAUGES audio attribute rows shifted the chained attribute ids so AttributePointerOf no longer lands on voltageSource@0x1D0 -> the bar always read 0. New BTGeneratorVoltage(subsystem) bridge (powersub.cpp) reads the NAMED member via PoweredSubsystem::ResolveVoltageSource()->Generator::MeasuredVoltage() (outputVoltage@0x1DC), bypassing the attribute table -- same pattern as BTPowerSourceFrame/BTCoolingLoopFrame. Both GeneratorVoltageConnection callers (the ScalarBarGauge param + the MyomerCluster seekValue) now pass subsystem_in. [voltfeed]-verified: Myomers -> 10000V from GeneratorD (was 0 on the dead path). Both pod + glass builds clean. Eng-page render awaiting live playtest. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
8c7ff639de
commit
f2eaf3d0ac
@@ -162,10 +162,15 @@ independent bugs stacked (all fixed, commit e634709):
|
||||
now passes `subsystem_in` (not the `InputVoltage` attribute slot). **Lesson: gauge value feeds
|
||||
must read named members through a complete-type bridge, NOT `AttributePointerOf`+`ResolveLink`
|
||||
— the attribute table's chained ids are unstable under the audio rows.** The eng-page
|
||||
`GeneratorVoltageConnection` (evolt voltage bar, btl4gau2.cpp:1737) still uses the same
|
||||
`AttributePointerOf("InputVoltage")` path and is the remaining sibling to convert.
|
||||
generator-voltage bar + MyomerCluster seek-voltage graph (`GeneratorVoltageConnection`,
|
||||
evolt.pcc, btl4gau2.cpp:806/1750) were on the same dead path and are now converted the same
|
||||
way -> `BTGeneratorVoltage(subsystem)` reads `Generator::MeasuredVoltage()`
|
||||
(outputVoltage@0x1DC); `[voltfeed]`-verified (Myomers -> 10000V from GeneratorD). Still on the
|
||||
OLD path but NOT yet converted (different attribute, direct read, not confirmed broken): the
|
||||
GeneratorCluster + EnergyWeaponCluster bars that read `AttributePointerOf(subsystem,
|
||||
"OutputVoltage")` directly (btl4gau2.cpp:968, ~1920).
|
||||
Diagnostics retained (env `BT_LOOP_LOG`): `[loopfeed]` (BTCoolingLoopFrame) + `[busfeed]`
|
||||
(BTPowerSourceFrame) print each lamp's resolved frame + source.
|
||||
(BTPowerSourceFrame) + `[voltfeed]` (BTGeneratorVoltage) print each widget's resolved value + source.
|
||||
**HUMAN-VERIFIED live 2026-07-21** (pod build, solo ARENA1 cockpit): the loop number + generator
|
||||
letter boxes render correctly on the weapon panels.
|
||||
|
||||
|
||||
@@ -233,9 +233,18 @@ protected:
|
||||
|
||||
//
|
||||
// GeneratorVoltageConnection -- @004c3288 ctor / @004c32f4 sampler (vt 0x518e90).
|
||||
// Resolves the voltage source and copies its output voltage (+0x1dc); 0 if
|
||||
// unresolved. Drives ScalarBarGauge / SeekVoltageGraph value slots.
|
||||
// The binary resolves the subsystem's InputVoltage link and copies its output
|
||||
// voltage (resolved+0x1DC == Generator::outputVoltage); 0 if unresolved. Drives
|
||||
// the eng-page generator-voltage bar (ScalarBarGauge) + the MyomerCluster
|
||||
// seek-voltage graph.
|
||||
// DATABINDING FIX 2026-07-21 (gotcha 8, sibling of the PowerSource/CoolingLoop
|
||||
// fixes): the ResolveLink(AttributePointerOf(subsystem,"InputVoltage")) path is
|
||||
// dead after the BT_DEV_GAUGES audio attribute rows shifted the chained ids, so
|
||||
// the bar always read 0. 'source' now carries the SUBSYSTEM and
|
||||
// BTGeneratorVoltage (powersub.cpp) reads the NAMED member via
|
||||
// ResolveVoltageSource()->MeasuredVoltage(), bypassing the attribute table.
|
||||
//
|
||||
extern Scalar BTGeneratorVoltage(void *subsystem);
|
||||
class GeneratorVoltageConnection : public GaugeConnection
|
||||
{
|
||||
public:
|
||||
@@ -243,9 +252,7 @@ public:
|
||||
: GaugeConnection(0), source(source), destination(destination) {}
|
||||
void Update() // @004c32f4
|
||||
{
|
||||
void *resolved = ResolveLink(source);
|
||||
*destination = (resolved == 0) ? 0.0f
|
||||
: *(Scalar *)((char *)resolved + 0x1dc);
|
||||
*destination = BTGeneratorVoltage(source);
|
||||
}
|
||||
protected:
|
||||
void *source; // @0x10
|
||||
@@ -1466,8 +1473,8 @@ SubsystemCluster::SubsystemCluster(
|
||||
|
||||
generatorVoltageBar = new ScalarBarGauge(ChildRate(), eng_mode, renderer_in, // @004c721c
|
||||
engPort, 0x89, 0x82, 0x93, 0x13b, "evolt.pcc", 0xff, 0,
|
||||
WipeGaugeScalar::wipeUp, 0.0f, GeneratorMaxVoltage, inputVoltage,
|
||||
"GeneratorVoltage(slotOf)");
|
||||
WipeGaugeScalar::wipeUp, 0.0f, GeneratorMaxVoltage, subsystem_in, // pass the SUBSYSTEM
|
||||
"GeneratorVoltage(slotOf)"); // -> BTGeneratorVoltage reads voltage by name (attr-shift fix)
|
||||
|
||||
// stateLamp only when the subsystem is a Generator (IsDerivedFrom 0x50f4bc).
|
||||
if (IsGeneratorDerived(subsystem_in))
|
||||
@@ -1738,8 +1745,9 @@ MyomerCluster::MyomerCluster(
|
||||
// INFERRED (the MyomerCluster ctor @004c8df4 isn't in the assert-anchored export).
|
||||
(int *)((char *)subsystem_in + 0x320), "OneOfSeveralInt");
|
||||
|
||||
void *inputVoltage = AttributePointerOf(subsystem_in, "InputVoltage");
|
||||
AddConnection(new GeneratorVoltageConnection(&seekValue, inputVoltage)); // @004c3288
|
||||
// Pass the SUBSYSTEM -- BTGeneratorVoltage resolves voltageSource by name
|
||||
// (the attribute-table shift makes AttributePointerOf("InputVoltage") dead).
|
||||
AddConnection(new GeneratorVoltageConnection(&seekValue, subsystem_in)); // @004c3288
|
||||
}
|
||||
|
||||
MyomerCluster::~MyomerCluster()
|
||||
|
||||
@@ -716,6 +716,44 @@ int BTPowerSourceFrame(void *subsystem_v)
|
||||
return frame;
|
||||
}
|
||||
|
||||
//
|
||||
// BTGeneratorVoltage -- complete-type bridge for the GeneratorVoltageConnection
|
||||
// (@004c3288), which drives the eng-page generator-voltage bar (evolt.pcc,
|
||||
// ScalarBarGauge @004c721c) and the MyomerCluster seek-voltage graph. The
|
||||
// binary resolved the subsystem's InputVoltage link and read resolved+0x1DC ==
|
||||
// Generator::outputVoltage (0..12000, == MeasuredVoltage()). Same databinding
|
||||
// trap as BTPowerSourceFrame: the port's ResolveLink(AttributePointerOf(...,
|
||||
// "InputVoltage")) path is dead after the BT_DEV_GAUGES audio attribute rows
|
||||
// shifted the chained ids, so the bar read 0. This reads the NAMED member via
|
||||
// PoweredSubsystem::ResolveVoltageSource(), bypassing the attribute table.
|
||||
//
|
||||
Scalar BTGeneratorVoltage(void *subsystem_v)
|
||||
{
|
||||
static int s_log = -1;
|
||||
if (s_log < 0) s_log = getenv("BT_LOOP_LOG") ? 1 : 0;
|
||||
static int s_n = 0;
|
||||
int trace = s_log && (s_n++ < 40);
|
||||
|
||||
Subsystem *sub = (Subsystem *)subsystem_v;
|
||||
if (sub == 0 || !sub->IsDerivedFrom(*PoweredSubsystem::GetClassDerivations()))
|
||||
{
|
||||
if (trace) DEBUG_STREAM << "[voltfeed] " << (sub ? sub->GetName() : "(null)")
|
||||
<< " -> 0 (not a PoweredSubsystem)\n" << std::flush;
|
||||
return 0.0f;
|
||||
}
|
||||
Generator *gen = (Generator *)((PoweredSubsystem *)sub)->ResolveVoltageSource();
|
||||
if (gen == 0 || gen->GetClassID() != RegisteredClass::GeneratorClassID)
|
||||
{
|
||||
if (trace) DEBUG_STREAM << "[voltfeed] " << sub->GetName()
|
||||
<< " -> 0 (no Generator)\n" << std::flush;
|
||||
return 0.0f;
|
||||
}
|
||||
Scalar volts = gen->MeasuredVoltage(); // outputVoltage @0x1DC
|
||||
if (trace) DEBUG_STREAM << "[voltfeed] " << sub->GetName() << " -> " << volts
|
||||
<< "V (generator '" << gen->GetName() << "')\n" << std::flush;
|
||||
return volts;
|
||||
}
|
||||
|
||||
|
||||
//#############################################################################
|
||||
// Voltage-source linkage helpers
|
||||
|
||||
Reference in New Issue
Block a user