Chasing what 5.3.132 and 5.3.133 actually turned on found a visible consequence nobody was looking for. HeatWatcher::WatchSimulation mirrors the watched subsystem's temperature into the watcher's own heat alarm. With every link NULL that mirror was dead -- the gyro never felt a hot avionics bus, the torso never felt hot myomers, no ammo bin ever felt its own gun's heat. It is now live for all seven watchers. And the HUD gates its page visibility on the watchdog reading Ready. Unbound, the watchdog read 0, so the page was hidden. Bound but with the percent bug, it read 1, so the page was still hidden. It took both fixes to reach 4, and the page now draws: [hud] page_visible=1 watchdog=4 heat=0 Flagged in the notes for the next cockpit A/B session: the gauge-ab rig last scored 98.9% identical against the shipped binary with this page missing on our side. If the shipped exe draws it, part of that residual should close on its own -- so the comparison wants re-running rather than trusting the old number. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
193 lines
5.1 KiB
C++
193 lines
5.1 KiB
C++
//===========================================================================//
|
|
// File: hud.cpp //
|
|
// Project: BattleTech Brick: Mech subsystems //
|
|
// Contents: HUD -- head-up display / targeting reticle //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include <bt.hpp>
|
|
#pragma hdrstop
|
|
|
|
#if !defined(HUD_HPP)
|
|
# include <hud.hpp>
|
|
#endif
|
|
|
|
#if !defined(MECH_HPP)
|
|
# include <mech.hpp>
|
|
#endif
|
|
|
|
static const Point3D HudZeroVector(0.0f, 0.0f, 0.0f);
|
|
|
|
Derivation
|
|
HUD::ClassDerivations(
|
|
PowerWatcher::ClassDerivations,
|
|
"HUD"
|
|
);
|
|
|
|
HUD::SharedData
|
|
HUD::DefaultData(
|
|
HUD::ClassDerivations,
|
|
Subsystem::MessageHandlers,
|
|
Subsystem::AttributeIndex,
|
|
Subsystem::StateCount
|
|
);
|
|
|
|
HUD::HUD(
|
|
Mech *owner,
|
|
int subsystem_ID,
|
|
SubsystemResource *subsystem_resource,
|
|
SharedData &shared_data
|
|
):
|
|
PowerWatcher(owner, subsystem_ID, subsystem_resource, shared_data)
|
|
{
|
|
Check(owner);
|
|
Check_Pointer(subsystem_resource);
|
|
|
|
flickerRate = 0.0f;
|
|
rotationOfTorsoHorizontal = 0.0f;
|
|
torsoLimitRight = 0.0f;
|
|
torsoLimitLeft = 0.0f;
|
|
torsoSpeed = 0.0f;
|
|
rangeToTarget = 0.0f;
|
|
scratch1F0 = 0;
|
|
visible = True;
|
|
lockFlag = False;
|
|
hotBoxVector = HudZeroVector;
|
|
threatVector = HudZeroVector;
|
|
compassHeading = 0.0f;
|
|
blinkTimer = 0.0f;
|
|
flickerTimer = 0.0f;
|
|
blinkState = True;
|
|
transitionFlag = False;
|
|
previousHorizontal = 0.0f;
|
|
|
|
statusAlarm.Initialize(2);
|
|
|
|
freeAimSlew = 0.0f;
|
|
scratch290 = 0.0f;
|
|
horizontalTorsoOffset = 0.0f;
|
|
|
|
flickerRate = subsystem_resource->flickerRate;
|
|
horizontalMovementPerSecond = subsystem_resource->horizontalMovementPerSecond;
|
|
horizontalLimit = subsystem_resource->horizontalLimit;
|
|
|
|
//
|
|
// The torso-orientation source is a Mech link not yet live at
|
|
// construction time; HudSimulation refreshes these per-frame.
|
|
//
|
|
linkedEntity = 0;
|
|
flickerActive = 0;
|
|
|
|
//
|
|
// The master instance runs the HUD per-frame.
|
|
//
|
|
// The binary's master gate: MasterInstance + DynamicFlag -- the
|
|
// simulationFlags 0xC/0x100 pair, now decoded as engine enum identities
|
|
// (InstanceBits=2 makes InstanceMask 0xC; DynamicBit=8 makes DynamicFlag
|
|
// 0x100; Entity::DefaultFlags carries both, seeded from the MakeMessage).
|
|
if (
|
|
(owner->simulationFlags & Entity::InstanceMask) == Entity::MasterInstance &&
|
|
(owner->simulationFlags & Entity::DynamicFlag) != 0
|
|
)
|
|
{
|
|
SetPerformance(&HUD::HudSimulation);
|
|
}
|
|
|
|
Check_Fpu();
|
|
}
|
|
|
|
HUD::~HUD()
|
|
{
|
|
}
|
|
|
|
Logical
|
|
HUD::TestClass(Mech &)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
Logical
|
|
HUD::TestInstance() const
|
|
{
|
|
return IsDerivedFrom(ClassDerivations);
|
|
}
|
|
|
|
//
|
|
//#############################################################################
|
|
// @004b7830 -- the per-frame HUD, PARTIAL: the base tick, the heat/voltage
|
|
// page gating and the blink are reconstructed (the donor's confident half);
|
|
// the reticle / target-lock / torso-horizon math (its blocks 4-6) survives
|
|
// only as summarised offsets in the recovered shard and stays STAGED --
|
|
// the page visibility is the cockpit-bound behaviour, and it is real.
|
|
//
|
|
// The blink comparison is >= (the decomp shard's literal != would toggle
|
|
// every tick through float inequality; the shard's own banner describes
|
|
// "compared against flickerRate; on expiry ... toggles").
|
|
//#############################################################################
|
|
//
|
|
void
|
|
HUD::HudSimulation(Scalar time_slice)
|
|
{
|
|
Check(this);
|
|
|
|
PowerWatcher::Simulation(time_slice);
|
|
|
|
//
|
|
// Page gating off our own mirrored alarms (the watchers, 5.3.109):
|
|
// a heat failure or an unpowered watched subsystem hides the page.
|
|
//
|
|
Logical
|
|
page_visible = True;
|
|
|
|
if (watchdogAlarm.GetLevel() != PoweredSubsystem::Ready)
|
|
{
|
|
page_visible = False;
|
|
}
|
|
if (heatAlarm.GetLevel() == HeatSink::FailureHeat)
|
|
{
|
|
page_visible = False;
|
|
}
|
|
|
|
if (getenv("BT_HUD_LOG"))
|
|
{
|
|
static int s_lastVisible = -1;
|
|
if ((int)page_visible != s_lastVisible)
|
|
{
|
|
s_lastVisible = (int)page_visible;
|
|
DEBUG_STREAM << "[hud] page_visible=" << (int)page_visible
|
|
<< " watchdog=" << watchdogAlarm.GetLevel()
|
|
<< " heat=" << heatAlarm.GetLevel() << endl << flush;
|
|
}
|
|
}
|
|
|
|
//
|
|
// The blink.
|
|
//
|
|
if (transitionFlag == 0)
|
|
{
|
|
blinkTimer += time_slice;
|
|
if (blinkTimer >= flickerRate)
|
|
{
|
|
blinkTimer = 0.0f;
|
|
blinkState = (blinkState == 0);
|
|
}
|
|
}
|
|
else if (transitionFlag == 1)
|
|
{
|
|
blinkState = True;
|
|
}
|
|
|
|
visible = (page_visible && blinkState) ? 1 : 0;
|
|
|
|
//
|
|
// STAGED (donor blocks 4-6): engine/start flag mirror, target lock +
|
|
// sliding range + compass, and the torso-horizon slew -- summarised
|
|
// offsets only in the recovered shard (part_013.c @004b7830).
|
|
//
|
|
|
|
Check_Fpu();
|
|
}
|