Files
TeslaRel410/restoration/source410/BT/HUD.CPP
T
CydandClaude Fable 5 505dae450b BT410 5.3.135: the HUD page was never on -- two watcher fixes later, the cockpit has a page again
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>
2026-08-12 22:48:28 -05:00

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();
}