Files
BT411/game/reconstructed/btl4gaug.hpp
T
Joe DiPrimaandClaude Opus 5 e6103d02b2 #97: leak gauge reaches all THREE levels -- the normalisation was dropped with an x87 expression
Players: "you can get up to three traingles which drains really quickly" ...
"only seeing one level (lowest) right now" (Oracle), corroborated by Draco
("3 triple delta being the top level").

The display was never the problem: BitMapInverseWipe is already built with
frames=3 and stacks three segments at two levels each (0..6).  The LEVEL
computation was wrong.

Our Execute rounded the raw leak rate:
    level = round(value)
The binary's @004c5d08 does NOT.  Ghidra renders the round as a bare
`FUN_004dcd94()` because it drops the x87 expression feeding __ftol -- exactly
KB gotcha 19, which we already had written down.  The real prologue, disassembled:

    fild  dword ptr [ebp-0x14]    ; ST0 = (float)fullWidth   (frames*2 = 6)
    fmul  dword ptr [ebx+0xb4]    ; ST0 *= value             (CoolantMassLeakRate)
    fdiv  dword ptr [ebx+0xb0]    ; ST0 /= third             (full-scale divisor)
    call  0x4dcd94                ; level = round(ST0)

i.e. level = round(fullWidth * leakRate / fullScale).

Without the normalisation the gauge rounded a value that never exceeds ~1.0
(coolantDraw = zoneDamage * heatLoad, and heatLoad is clamp(0.002*T, 0, 1) --
constants re-verified from the image, including the 80-bit extended 0.002).  So
level could only ever be 0, or 1 via the >0.0025 floor: ONE triangle, always, no
matter how bad the leak.  Three of the six condensers being mis-lamped (#98) hid
how systematic this was.

Also corrected on the way:
  * `third` was declared int but the binary FDIVs it -- it is a float.  The two
    call sites passed *(int *)(subsystem+0x150), i.e. the BIT PATTERN of a float
    read from a RAW OFFSET into our own layout (the databinding trap): at +0x150
    our layout has filterDecay, not the binary's field.  Now resolved through a
    complete-type bridge, BTHeatSinkLeakFullScale.
  * filterDecay was initialised 0.4f; @004b8fec writes 0.15f (param_1[0x54] =
    0x3e19999a).  It is written-once-never-read elsewhere in the port, so the
    correction is behaviourally safe and it IS the gauge's full scale.

Verified live: Condenser6 at 10% zone damage -> draw 0.0358 -> level 1 (one
triangle); the same formula reaches all three at heavier damage, and the mapping
spans draw 0.0026 (half of one) to 0.15 (three full).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 13:54:13 -05:00

595 lines
24 KiB
C++

//===========================================================================//
// File: btl4gaug.hpp //
// Project: BattleTech Brick: Gauge Renderer Manager //
// Contents: The cockpit instrument gauge library -- the family of small //
// "widget" gauges that the BattleTech HUD is assembled from: //
// * ColorMapper* -- palette-animating tint gauges driven by //
// subsystem state (heat / armour / crit) //
// * Horiz/VertTwoPartBar, VertNormalSlider //
// -- two-colour fill bars (throttle / damage) //
// * OneOfSeveral* -- multi-frame bitmap selectors (state lamp) //
// * HeadingPointer -- rotating numeric heading readout //
// * SegmentArc270/Ratio-- arc / dial style gauges //
// * BitMap wipe gauges -- bitmap "fuel / leak" wipe indicators //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 02/22/96 CPB Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved //
// PROPRIETARY AND CONFIDENTIAL //
//===========================================================================//
//
// RECONSTRUCTED. No BTL4GAUG.HPP survived (the BT_L4 source tree retains only
// BTL4RDR.HPP and BTL4GALM.HPP). This declaration is recovered from the
// shipped binary (BTL4OPT.EXE); the Ghidra pseudo-C is in
// recovered/all/part_013.c (@004c2f94..@004c5e84)
// recovered/all/part_014.c (@004c5e84..@004c6394)
// The module is the .obj that links immediately after btl4rdr.obj and before
// btl4gau2.obj (see BTL4.MAK), so it owns the contiguous code run
// [ @004c2f94 .. @004c6771 ] (btl4gau2.cpp begins at @004c6798).
//
// The sole address with a surviving embedded assert path -- the anchor --
// is ColorMapperHeat's constructor:
// @004c3f6c "d:\tesla\bt\bt_l4\BTL4GAUG.CPP", line 0x68a
//
// Class names are recovered verbatim from the CODE name-string pool
// (section_dump.txt @0x518480..0x51859e):
// ColorMapper ColorMapperArmor ColorMapperMultiArmor ColorMapperCritical
// ColorMapperHeat HorizTwoPartBar VertTwoPartBar VertNormalSlider
// OneOfSeveral OneOfSeveralInt OneOfSeveralPixInt OneOfSeveralStates
// HeadingPointer BitMapInverseWipe BitMapInverseWipeScalar
// SegmentArc270 SegmentArcRatio
//
// Field offsets in comments are the byte offsets observed in the decompiled
// object (e.g. "@0x90" == this[0x24]). The two base gauges are the MUNGA L4
// gauge primitives:
// Gauge ctor FUN_00444308 dtor FUN_00444360 -- non-graphic;
// used by the ColorMapper family (they tint a palette, they
// do not own a GraphicsView).
// GraphicGauge ctor FUN_00444818 dtor FUN_00444870 -- owns a GraphicsView
// embedded at +0x48 (this[0x12]); used by every drawing gauge.
// (Same base as MapDisplay in btl4rdr.cpp.)
//
// Names flagged "(name unconfirmed)" are best-effort: the class exists in the
// binary but its identification string could not be tied to it unambiguously.
//
#if !defined(BTL4GAUG_HPP)
# define BTL4GAUG_HPP
# if !defined(SLOT_HPP)
# include <slot.hpp>
# endif
# if !defined(L4GREND_HPP)
# include <l4grend.hpp>
# endif
# if !defined(L4GAUGE_HPP)
# include <l4gauge.hpp>
# endif
# if !defined(HEAT_HPP)
# include <heat.hpp>
# endif
// NOTE (reconstruction): the original BTL4GAUG.HPP also pulled in
// <powersub.hpp>, but nothing in this gauge-widget family actually depends
// on a power-subsystem type (the gauges connect to subsystems by name /
// attribute index, not by class). The include is dropped to keep this TU
// independent of the (separately-reconstructed) powersub header.
//#######################################################################
//#######################################################################
// ColorMapper family
//
// A ColorMapper is NOT a drawing gauge: every frame it reads a single
// subsystem-derived value (0..255), looks the corresponding R/G/B
// triple out of a named palette resource, and -- if it has changed --
// writes it straight into one hardware palette slot (colorIndex). The
// cockpit art that uses that slot therefore changes colour live. With
// two palette names it alternates between them every frame to flash.
//
// The driving value arrives through a small file-private GaugeConnection
// (see btl4gaug.cpp) wired to currentColorIndex. ColorMapperHeat's
// connection reads HeatableSubsystem::currentTemperature (@0x114).
//#######################################################################
//#######################################################################
class ColorMapper :
public Gauge
{
public:
ColorMapper(
GaugeRate rate,
ModeMask mode_mask,
L4GaugeRenderer *renderer,
int graphics_port_number,
int color_index,
const char *palette_name_a,
const char *palette_name_b,
const char *identification_string
);
~ColorMapper();
Logical TestInstance() const; // inherits Gauge
void BecameActive();
void Execute(); // @004c3980 -- palette push
protected:
char *paletteName[2]; // @0x48,@0x4C this[0x12],[0x13]
Logical twoColorMode; // @0x50 this[0x14] (names differ)
int currentColorIndex; // @0x54 this[0x15] (connection dst)
int previousColorIndex; // @0x58 this[0x16]
int colorSlot; // @0x5C this[0x17] hw palette slot
int paletteToggle; // @0x60 this[0x18] 0/1 flash phase
unsigned char
previousRed, // @0x64 this[0x19].b0
previousGreen, // @0x65
previousBlue; // @0x66
GraphicsPort
*graphicsPort; // @0x68 this[0x1A] (renderer port)
};
//
// ColorMapperArmor -- tints by the damage ratio of one named damage zone.
// Connection: @004c33a4 (reads Subsystem damage-zone array @0x120[index]).
//
class ColorMapperArmor :
public ColorMapper
{
public:
// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "cmArmor".
static MethodDescription methodDescription;
static Logical Make( // @004c3aa4
int display_port_index, Vector2DOf<int> position,
Entity *entity, GaugeRenderer *gauge_renderer);
ColorMapperArmor( // @004c3b98
GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer,
int graphics_port_number, int color_index,
Entity *entity, const char *palette_a, const char *palette_b,
int damage_zone_index, const char *identification_string);
~ColorMapperArmor();
// @004c3c38 -- store the group state into @0x6C (used by PlayerStatusMappingGroup
// to push the mech's disabled/enabled state onto all 28 zone tints).
void SetColor(int state) { unused = state; }
protected:
int unused; // @0x6C this[0x1B] (state slot; SetColor writes it)
};
//
// ColorMapperMultiArmor -- worst-of-N damage zones.
// Connection: @004c346c (copies 8 zone indices, takes the max ratio).
//
class ColorMapperMultiArmor :
public ColorMapper
{
public:
// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "colorMapperMultiArmor".
static MethodDescription methodDescription;
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *); // @004c3c48
ColorMapperMultiArmor( // @004c3d60
GaugeRate, ModeMask, L4GaugeRenderer *, int, int,
Entity *, const char *, const char *,
const int *zone_indices /*[8]*/, const char *);
~ColorMapperMultiArmor();
};
//
// ColorMapperCritical -- tints by a subsystem's operational state.
// Connection: @004c3598 (subsystem operational flag @0x40 -> 100, else value).
//
class ColorMapperCritical :
public ColorMapper
{
public:
// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "cmCrit".
static MethodDescription methodDescription;
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *); // @004c3ddc
ColorMapperCritical( // @004c3e40
GaugeRate, ModeMask, L4GaugeRenderer *, int, int,
Entity *, const char *, const char *,
const char *subsystem_name, const char *);
~ColorMapperCritical();
};
//
// ColorMapperHeat -- the cockpit heat tint. ANCHOR @004c3f6c.
// Connection: @004c3664 (reads HeatableSubsystem::currentTemperature@0x114
// as a 0..100 percentage). The named subsystem must derive from a heat
// class (IsDerivedFrom 0x50e3ec HeatableSubsystem or 0x50e604 HEATWATCHER
// -- task #57 relabel) or the ctor asserts (line 0x68a).
//
class ColorMapperHeat :
public ColorMapper
{
public:
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *); // @004c3f08
ColorMapperHeat( // @004c3f6c
GaugeRate, ModeMask, L4GaugeRenderer *, int, int,
Entity *, const char *, const char *,
const char *heat_subsystem_name, const char *);
~ColorMapperHeat();
// Registered in BTL4MethodDescription[] (btl4grnd.cpp) so the config
// interpreter builds this gauge from the CFG "cmHeat" primitive.
static MethodDescription methodDescription;
};
//#######################################################################
//#######################################################################
// Two-part fill bars (: GraphicGauge)
//
// A bar is split into a "filled" colour and a "background" colour at a
// pixel computed from a Scalar input. HorizTwoPartBar grows left->right,
// VertTwoPartBar grows bottom->top. Both blit a tile bitmap behind the
// fill (FUN_004c2ff8 = tiled blit helper).
//#######################################################################
//#######################################################################
class HorizTwoPartBar :
public GraphicGauge
{
public:
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *); // @004c407c
HorizTwoPartBar( // @004c4170
GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number,
int left, int bottom, int right, int top,
const char *tile_image,
int fill_color, int background_color,
Scalar *value_pointer, Scalar *low_pointer, Scalar *high_pointer,
const char *identification_string);
~HorizTwoPartBar();
Logical TestInstance() const;
void BecameActive(); // @004c4324
void Execute(); // @004c4340
protected:
Scalar value; // @0x90 this[0x24] (connection)
Scalar low; // @0x94 this[0x25]
Scalar high; // @0x98 this[0x26]
char *tileImage; // @0x9C this[0x27]
int fillColor; // @0xA0 this[0x28]
int backgroundColor; // @0xA4 this[0x29]
int width; // @0xA8 this[0x2A] right-left
int height; // @0xAC this[0x2B] (top-bottom)-1
int previousFill; // @0xB0 this[0x2C]
int previousFull; // @0xB4 this[0x2D]
};
class VertTwoPartBar :
public GraphicGauge
{
public:
// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "vertBar".
static MethodDescription methodDescription;
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *); // @004c462c
VertTwoPartBar( // @004c4724 (ctor arg order = binary param_12..17)
GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number,
int left, int bottom, int right, int top,
const char *tile_image,
int background_color, int fill_color, int extra_color,
Scalar *value_pointer, Scalar *low_pointer, Scalar *high_pointer,
const char *identification_string);
~VertTwoPartBar();
Logical TestInstance() const;
void BecameActive(); // @004c48e0
void Execute(); // @004c48fc
protected:
char *tileImage; // @0x90 this[0x24]
int backgroundColor; // @0x94 this[0x25]
int fillColor; // @0x98 this[0x26]
int extraColor; // @0x9C this[0x27]
int width; // @0xA0 this[0x28] (right-left)-1
int height; // @0xA4 this[0x29] top-bottom
Scalar value; // @0xB0 this[0x2C] (connection)
Scalar low; // @0xB4 this[0x2D]
Scalar high; // @0xB8 this[0x2E]
int previousFill; // @0xA8 this[0x2A]
int previousFull; // @0xAC this[0x2B]
};
//
// VertNormalSlider -- a single-colour rectangle whose height tracks a
// normalised [0,1] value (clamped at @004c4cc0). (name unconfirmed but
// matches the "VertNormalSlider" pool entry and the vtable ordering.)
//
class VertNormalSlider :
public GraphicGauge
{
public:
// gauge wave P2: the "vertNormalSlider" config factory (the condenser VALVE
// slider @2 in GenericHeatGauges1/2). Registered in BTL4MethodDescription[]
// (btl4grnd.cpp); the ctor/Execute existed only as prose, so the keyword was
// parse-skipped and the SET column never built.
static MethodDescription methodDescription;
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *); // @004c4b08
VertNormalSlider( // @004c4b84
GaugeRate, ModeMask, L4GaugeRenderer *, int,
int left, int bottom, int right, int top,
int fill_color, int background_color, int baseline,
Scalar *value_pointer, const char *identification_string);
~VertNormalSlider(); // @004c4c68
Logical TestInstance() const; // @004c4c94 -> GraphicGauge::TestInstance
void BecameActive(); // @004c4cac
void Execute(); // @004c4cc0 -> Draw @004c4d48
private:
void Draw(); // @004c4d48 (XOR indicator blit; non-virtual)
protected:
// Corrected byte-exact layout (from the ctor's this[N] stores @004c4b84;
// the earlier order was jumbled). 8 words, 0x90..0xAF, sizeof == 0xB0.
int previousFill; // @0x90 this[0x24] XOR indicator row; -1 = none
int width; // @0x94 this[0x25] (right-left)-1
int height; // @0x98 this[0x26] top-bottom (track height)
int baseline; // @0x9C this[0x27] indicator thickness
int span; // @0xA0 this[0x28] height-baseline (travel)
int fillColor; // @0xA4 this[0x29] indicator colour
int backgroundColor; // @0xA8 this[0x2A] stored, unused by Draw
Scalar value; // @0xAC this[0x2B] connection dst [0,1]
};
//#######################################################################
//#######################################################################
// OneOfSeveral family -- multi-frame bitmap selectors
//
// A strip bitmap holds N frames; the gauge blits whichever frame the
// driving value selects. The base (OneOfSeveral) stores the strip and
// the per-frame size; subclasses add the value source.
//#######################################################################
//#######################################################################
class OneOfSeveral :
public GraphicGauge
{
public:
OneOfSeveral( // @004c4d88
GaugeRate, ModeMask, L4GaugeRenderer *, int,
int x, int y, Logical from_image_strip,
const char *image_name,
int /*reserved*/, int /*reserved*/,
int columns, int rows,
const char *identification_string);
~OneOfSeveral();
Logical TestInstance() const;
void BecameActive(); // @004c4f14
void Execute(); // @004c4f28
protected:
Logical fromImageStrip; // @0x90 this[0x24]
char *imageName; // @0x94 this[0x25]
int backgroundColor; // @0x98 this[0x26]
int foregroundColor; // @0x9C this[0x27] (DrawBitMapOpaque bg arg)
int columns; // @0xA0 this[0x28]
int selected; // @0xAC this[0x2B] (connection)
int previousSelected; // @0xB0 this[0x2C]
int frameWidth; // @0xA4 this[0x29]
int frameHeight; // @0xA8 this[0x2A]
};
//
// OneOfSeveralInt -- frame = a direct int input. @004c5148 Make @004c5068
//
class OneOfSeveralInt :
public OneOfSeveral
{
public:
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);
// background/foreground are CALLER-SUPPLIED -- the binary's cluster call
// sites pass 0xff/0 (btecmode: part_014.c:1479-1481, bteseek: :2146-2147).
// They were dropped here and hardcoded 0/0, which drew these lamps in
// colour 0 = invisible (the same dropped-parameter bug as
// OneOfSeveralStates / the btemode connect-mode lamp).
OneOfSeveralInt(GaugeRate, ModeMask, L4GaugeRenderer *, int,
int x, int y, const char *image,
int background_color, int foreground_color, int columns, int rows,
int *value_pointer, const char *);
~OneOfSeveralInt(); // @004c51d8
};
//
// OneOfSeveralPixInt -- frame from a packed-pixel int strip.
// @004c52d8 Make @004c5204
//
class OneOfSeveralPixInt :
public OneOfSeveral
{
public:
// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "oneOfSeveralPixInt".
static MethodDescription methodDescription;
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *); // @004c5204
OneOfSeveralPixInt( // @004c52d8
GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number,
int x, int y, const char *image, int columns, int rows,
int *value_pointer, const char *identification_string);
~OneOfSeveralPixInt(); // @004c5364
};
//
// OneOfSeveralStates -- frame from a subsystem state value (clamped >=0).
// @004c5470 Make @004c5390 Execute clamp @004c552c
// Connection: @004c3324 (reads Subsystem state @0x14).
//
class OneOfSeveralStates :
public OneOfSeveral
{
public:
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *);
// background/foreground are CALLER-SUPPLIED (@004c5470 forwards its own
// args to the base; only fromImageStrip is a literal). They used to be
// dropped here and hardcoded 0/0 in the ctor -- see the note there.
OneOfSeveralStates(GaugeRate, ModeMask, L4GaugeRenderer *, int,
int x, int y, const char *image,
int background_color, int foreground_color, int columns, int rows,
Entity *subsystem_source, const char *);
~OneOfSeveralStates(); // @004c5500
// @004c552c is the EXECUTE override (vtable-diffed 2026-07-28): clamp a
// negative state to 0, then chain OneOfSeveral::Execute. It was
// mislabeled BecameActive here; BecameActive is inherited from the base.
void Execute(); // @004c552c
};
//#######################################################################
// HeadingPointer -- a rotating numeric compass-heading readout.
// @004c562c Make @004c554c Execute @004c5914 (rotate by torso yaw,
// degrees = radian * 57.2958). Owns a NumericDisplay (@0x44 object,
// FUN_004700bc) and a GraphicsViewRecord (@0xA4) for erase tracking.
//#######################################################################
class HeadingPointer :
public GraphicGauge
{
public:
// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "headingPointer".
static MethodDescription methodDescription;
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *); // @004c554c
//
// The binary ctor (@004c562c) takes 14 args -- the earlier header collapsed
// owner_ID/graphics_port_number and merged the colours. Also: fields
// @0x98/@0x9C are the needle's inner/outer RADIUS (Execute multiplies them
// by sin/cos of the heading), NOT a colour+spacing as the old names implied.
//
HeadingPointer( // @004c562c
GaugeRate, ModeMask, L4GaugeRenderer *,
unsigned int owner_ID,
int graphics_port_number,
int x, int y,
int needle_color, // -> @0x90 the drawn needle colour
int numeric_color, // -> NumericDisplay foreground (readout)
int erase_color, // -> @0x94 erase + NumericDisplay background
int inner_radius, // -> @0x98 needle near-end radius
int outer_radius, // -> @0x9C needle tip radius (the change key)
const char *font_name,
const char *identification_string = "HeadingPointer");
~HeadingPointer(); // @004c573c
Logical TestInstance() const;
void ShowInstance(char *indent); // @004c57d0
void BecameActive(); // @004c58e8
void Execute(); // @004c5914
protected:
int needleColor; // @0x90 needle (fg) colour
int eraseColor; // @0x94 erase (bg) colour
int innerRadius; // @0x98 needle near-end radius
int outerRadius; // @0x9C needle tip radius (change key)
char *imageName; // @0xA0 interned font name
GraphicsViewRecord
previousDrawing; // @0xA4 erase-tracking record
int previousX; // @0xB4
int previousY; // @0xB8
NumericDisplay
*numericDisplay; // @0xBC
};
//#######################################################################
// BitMap "wipe" gauges -- a fuel/leak style bar that reveals a bitmap up
// to a level. (names "BitMapInverseWipe" / "BitMapInverseWipeScalar" are
// best-effort from the pool; the Scalar variant adds a GaugeConnection.)
// BitMapInverseWipe @004c5b7c (used as a base by btl4gau2 LeakGauge)
// <wipe base> @004c5e84
// <wipe base>Scalar @004c61c8 (adds GaugeConnectionDirectOf<Scalar>)
//#######################################################################
class BitMapInverseWipe : // (name unconfirmed)
public GraphicGauge
{
public:
// gauge wave P2: registered in BTL4MethodDescription[] (btl4grnd.cpp) as
// "LeakGauge" -- the config factory the class was missing (the ctor/Execute
// already existed but the keyword was parse-skipped so it never built).
static MethodDescription methodDescription;
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *); // @004c... (config factory)
BitMapInverseWipe( // @004c5b7c
GaugeRate, ModeMask, L4GaugeRenderer *, int,
int x, int y, const char *image,
int color_a, int color_b, Scalar third, int frames,
Scalar *value_pointer, const char *);
~BitMapInverseWipe(); // @004c5c80
Logical TestInstance() const;
void BecameActive(); // @004c5cf4
void Execute(); // @004c5d08
protected:
char *imageName; // @0x90 this[0x24]
int colorA; // @0x94 this[0x25]
int colorB; // @0x98 this[0x26]
int fullWidth; // @0x9C this[0x27] frames*2
int frameWidth; // @0xA8 this[0x2A] width/3
int frameHeight; // @0xA4 this[0x29]
int frames; // @0xA0 this[0x28]
int previousLevel; // @0xAC this[0x2B]
Scalar third; // @0xB0 this[0x2C] full-scale divisor (fdiv, #97)
Scalar value; // @0xB4 this[0x2D] (connection)
};
//#######################################################################
// SegmentArc gauges -- needle / dial over a 270-degree arc. Derived from
// the MUNGA L4 arc primitives (FUN_004745e0 / FUN_00473f44).
// SegmentArc270 @004c6244
// SegmentArcRatio @004c6394 Make @004c62fc (adds two connections)
//#######################################################################
class SegmentArc270 :
public SegmentArc // MUNGA L4 base (engine class SegmentArc)
{
public:
SegmentArc270( // @004c6244
GaugeRate, ModeMask, L4GaugeRenderer *, int owner_ID,
int graphics_port_number, int center_x, int center_y,
Scalar inner0, Scalar outer0, Scalar inner1, Scalar outer1,
Scalar deg0, Scalar deg1, int number_of_segs,
int background_color, int foreground_color,
Scalar *value_pointer, Logical use_thick_lines,
const char *identification_string);
~SegmentArc270(); // dtor thunk @004c66b3
void Execute(); // PORT diag wrapper (chains SegmentArc::Execute)
const char *diagName; // PORT diagnostic (frozen-dial hunt)
protected:
Scalar segmentSpan; // @0xC0 this[0x30]
};
class SegmentArcRatio :
public SegmentArc // MUNGA L4 base (engine SegmentArc, L4GAUGE.cpp:4827)
{
public:
// Registered in BTL4MethodDescription[] (btl4grnd.cpp) as "segmentArcRatio".
static MethodDescription methodDescription;
static Logical Make(int, Vector2DOf<int>, Entity *, GaugeRenderer *); // @004c62fc
SegmentArcRatio( // @004c6394
GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number,
int center_x, int center_y,
Scalar inner, Scalar outer, Scalar deg0, Scalar deg1,
int number_of_segs, int background_color, int foreground_color,
Scalar *numerator_pointer, Scalar *denominator_pointer,
const char *identification_string);
~SegmentArcRatio(); // dtor thunk @004c668d
void Execute(); // @004c6488 (ratio -> currentValue -> SegmentArc::Execute)
protected:
Scalar numerator; // @0xC0 this[0x30] (connection)
Scalar denominator; // @0xC4 this[0x31] (connection)
Scalar segmentSpan; // @0xC8 this[0x32] (float, read by Execute)
};
#endif