//===========================================================================// // File: btl4gau2.hpp // // Project: BattleTech Brick: Gauge Renderer Manager // // Contents: Cockpit instrument library, part 2 -- the COMPOSITE "panel" // // gauges that the BattleTech engineering / weapon-status HUD is // // assembled from. Where btl4gaug.cpp holds the primitive widgets // // (bars, dials, lamps, colour-mappers), btl4gau2.cpp holds the // // higher-level gauges that AGGREGATE those primitives into a single // // subsystem read-out: // // * SeekVoltageGraph -- energy-weapon seek-voltage curve // // * ConfigMapGauge -- joystick / config-manager state lamp // // * GeneratorCluster -- generator voltage + coolant + leak panel // // * PrepEngrScreen -- per-weapon engineering screen builder // // * SubsystemCluster +-> HeatSinkCluster // // +-> WeaponCluster +-> EnergyWeaponCluster // // +-> BallisticWeaponClu.// //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 02/22/96 CPB Initial coding. // //---------------------------------------------------------------------------// // Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved // // PROPRIETARY AND CONFIDENTIAL // //===========================================================================// // // RECONSTRUCTED. No BTL4GAU2.HPP survived; recovered from the shipped binary // (BTL4OPT.EXE). Ghidra pseudo-C is in recovered/all/part_014.c. // // Translation-unit extent (BTL4.MAK link order: // btl4mode -> btl4rdr -> btl4gaug -> btl4gau2 -> btl4gau3 -> btl4grnd -> ...): // first gau2 code @004c6798 (SeekVoltageGraph::SeekVoltageGraph) // last gau2 code @004c9b50 (BallisticWeaponCluster helpers) // btl4gau3 begins @004c9bd0 (PlayerStatusMappingGroup -- not this TU) // // Class names recovered from the CODE name-string pool around 0x519760 // (the gauge name list) and the per-instance identification strings: // "GeneratorCluster" 0x519a8c "PrepEngr" 0x519a9d // "ConfigMap" 0x519a38 "CoolingLoop" 0x519a42 "PowerSource" 0x519a4e // "GeneratorVoltage(scalar)" 0x519a73 "GeneratorVoltage(slotOf)" 0x519a5a // "EngrGraph" 0x519a2e "WeaponCluster ... " 0x519dcb // Field offsets in comments are byte offsets (e.g. "@0x90" == this[0x24]). // // Bases (MUNGA L4 gauge primitives, shared with btl4gaug.cpp): // GraphicGauge ctor FUN_00444818 dtor FUN_00444870 (GraphicsView @+0x48) // Gauge group ctor FUN_004440d4 dtor FUN_00443f7c (owns a ChainOf // at +0x24; used by PrepEngrScreen -- it draws into a port and // hosts no GraphicsView of its own) // ArcGauge/BarGraph primitives FUN_00472ef0 (bar), FUN_004c6244 (SegmentArc270, // in btl4gaug), FUN_004739d8 (TwoState), FUN_00471d00 // (BackgroundBitmap), FUN_004700bc (NumericDisplay), // FUN_00470888 (NumericDisplayScalar), // FUN_00473c94 (NumericDisplayScalarTwoState). // // Names flagged "(best-effort)" exist in the binary but their identification // string could not be tied to them unambiguously. // #if !defined(BTL4GAU2_HPP) # define BTL4GAU2_HPP # if !defined(SLOT_HPP) # include # endif # if !defined(L4GREND_HPP) # include # endif # if !defined(L4GAUGE_HPP) # include # endif # if !defined(BTL4GAUG_HPP) # include # endif # if !defined(HEAT_HPP) # include # endif // (see btl4gaug.hpp -- intentionally not pulled in; the // composite gauges reference subsystems by pointer/attribute, not by type.) // // Reconstruction type: the original referenced an "AttributeAccessor" handle // (a small object that samples one named subsystem attribute). Only its // address is used here (it is immediately reinterpreted as an Entity*), so an // opaque forward declaration is sufficient for this translation unit. // class AttributeAccessor; //####################################################################### // SeekVoltageGraph -- the energy-weapon / myomer "seek voltage" response // graph on the engineering detail pages (the "POWER" box). // @004c6798 ctor / @004c68ac dtor / @004c6920 BecameActive / @004c6934 Execute. // vtable PTR_FUN_0051a1fc. Resolves the four SeekVoltage attribute // POINTERS off the weapon subsystem (FUN_0041bfc0 returns subsystem+offset: // "CurrentSeekVoltageIndex" / "MinSeekVoltageIndex" / "MaxSeekVoltageIndex" // / "SeekVoltage") and plots the subsystem's voltage-response curve // (vtbl slot 15 sampler: Emitter @004bb42c / Myomers @004b8f94) over the // top data box (0x97,0x80)-(0x17d,0x13b): x = response(v)*230 (0..1 // normalised sqrt response), y = v/12000*187 (voltage axis), with per-gear // tick marks (the current gear drawn as a full L) and, when draw_cursor, // a live 8x8 XOR cursor at the subsystem's live voltage. When the // subsystem is destroyed (simulationState@0x40==1) it shows a centred // "destroyed" bitmap instead. Its Execute's full-box CLEAR (@004c6be4) // is what erases the sibling eng pages' stale pixels on the shared Eng // bit-plane -- the widget IS the top-box eraser (Gitea #10 finding A). //####################################################################### class SeekVoltageGraph : public GraphicGauge { public: SeekVoltageGraph( // @004c6798 GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer, int graphics_port_number, Entity *subsystem, AttributeAccessor *seek_voltage_pointer, const char *destroyed_image, Logical draw_cursor, const char *identification_string); ~SeekVoltageGraph(); // @004c68ac Logical TestInstance() const; void BecameActive(); // @004c6920 void Execute(); // @004c6934 protected: void ClearGraph(); // @004c6be4 (full-box erase) void DrawTicks(); // @004c6c6c (per-gear ticks, XOR) void DrawCursorBox(); // @004c6c30 (8x8 cursor, XOR) char *destroyedImage; // @0x90 this[0x24] int *currentSeekIndexPtr; // @0x94 this[0x25] attr ptr (subsys+off) int *minSeekIndexPtr; // @0x98 this[0x26] attr ptr int *maxSeekIndexPtr; // @0x9C this[0x27] attr ptr Scalar *seekVoltageTablePtr; // @0xA0 this[0x28] attr ptr (array base) Scalar *liveVoltage; // @0xA4 this[0x29] the ctor's // seek_voltage_pointer ("OutputVoltage" // attr ptr / cluster seekValue cache) -- // Execute derefs it for the live cursor Subsystem *subsystem; // @0xA8 this[0x2A] Scalar previousVoltage; // @0xAC this[0x2B] cached response at // 12000 V (9999 sentinel = force replot) Scalar xScale; // @0xB0 this[0x2C] =230.0f Scalar yScale; // @0xB4 this[0x2D] =187.0f int destroyedShown; // @0xB8 this[0x2E] Logical drawCursor; // @0xBC this[0x2F] int cursorX; // @0xC0 this[0x30] (-1 = no cursor drawn) int cursorY; // @0xC4 this[0x31] int tickIndexShown; // @0xC8 this[0x32] gear index the tick // highlight was last drawn at }; //####################################################################### // ConfigMapGauge -- the joystick / config-manager (control-mapper) state // lamp. @004c6d80 ctor / @004c6e54 dtor / @004c6ee0 SetColor / // @004c6ef4 BecameActive / @004c6f1c Execute. vtable PTR_FUN_0051a1b8. // Owns a base joystick bitmap ("btjoy.pcc") plus four config-state pixmaps // (cm_off/cm_other/cm_only/cm_both .pcc) selected from a 4-entry table // (DAT_00518eb8) driven by the control-mapper state. Named "ConfigMap". //####################################################################### class ConfigMapGauge : public GraphicGauge { public: ConfigMapGauge( // @004c6d80 GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number, int x, int y, Entity *subsystem, const char *identification_string); ~ConfigMapGauge(); // @004c6e54 Logical TestInstance() const; // @004c6ee0 -- the GaugeBase::LinkToEntity OVERRIDE (vtbl slot 9, +0x24), // NOT a "SetColor": it stores the viewpoint entity into @0x94 and Execute // gates on it. GaugeRenderer::LinkToEntity (GAUGREND.cpp:3011) broadcasts // it to every gauge when the viewpoint binds (APP.cpp:1277) -- THAT is // what lights the trigger-config joystick in the shipped game. (The old // "SetColor, no callers -> authentically dormant" claim was a mislabel.) void LinkToEntity(Entity *entity); // @004c6ee0 writes this[0x25] void BecameActive(); // @004c6ef4 void Execute(); // @004c6f1c protected: Entity *subsystem; // @0x90 this[0x24] Entity *linkedEntity; // @0x94 this[0x25] (Execute gate; was mislabelled 'color') char *joystickImage; // @0x98 this[0x26] "btjoy.pcc" char *stateImage[4]; // @0x9C this[0x27..0x2A] int previousState[4]; // @0xAC this[0x2B..0x2E] Logical dirty; // @0xBC this[0x2F] }; //####################################################################### // Two small OneOfSeveral subclasses that drive the selected frame from a // subsystem value through a file-private GaugeConnection (the same // connection classes declared in btl4gaug.cpp). // AnimatedSubsystemLamp @004c70a4 (vtable 0051a174) -- connection @004c3134 // AnimatedSourceLamp @004c7160 (vtable 0051a130) -- connection @004c31ec // Both chain OneOfSeveral::OneOfSeveral (@004c4d88, fromImageStrip=1) and // share dtor FUN_004c4e7c. Used for the cooling-loop / power-source lamps. // (Class names best-effort; the gauge is generic and reused with the // instance strings "CoolingLoop" and "PowerSource".) //####################################################################### class AnimatedSubsystemLamp : // (best-effort) public OneOfSeveral { public: AnimatedSubsystemLamp( // @004c70a4 GaugeRate, ModeMask, L4GaugeRenderer *, int, int x, int y, const char *image, int columns, int rows, void *subsystem, const char *identification_string); ~AnimatedSubsystemLamp(); // @004c7134 // SHADOW-FIELD FIX 2026-07-20 (gotcha #2): 'selected' is inherited from // OneOfSeveral (@0xAC). A redeclared 'int selected;' here shadowed the base // at a higher offset -- the CoolingLoopConnection wrote the shadow while // OneOfSeveral::Execute read the base (always 0) so the loop lamp drew frame // 0 ("OFF"). Removed; the ctor's &selected now binds the inherited member. }; class AnimatedSourceLamp : // (best-effort) public OneOfSeveral { public: AnimatedSourceLamp( // @004c7160 GaugeRate, ModeMask, L4GaugeRenderer *, int, int x, int y, const char *image, int columns, int rows, void *source, const char *identification_string); ~AnimatedSourceLamp(); // @004c71f0 // SHADOW-FIELD FIX 2026-07-20 (gotcha #2): same as AnimatedSubsystemLamp -- // 'selected' is inherited from OneOfSeveral (@0xAC); the redeclaration here // shadowed it so the PowerSourceConnection wrote a dead copy and the bus lamp // drew frame 0. Removed; &selected now binds the inherited base member. }; //####################################################################### // ScalarBarGauge -- a generator-voltage bar (derives from the MUNGA L4 bar // primitive @00472ef0). Two ctors: // @004c721c (vtable 0051a0e4) adds an "AltId" connection (@004c3288) // @004c72ac (same vtable) adds a plain GaugeConnectionDirectOf // (@00474855) // Both share dtor FUN_004c733c (chains the bar dtor @00472fb4). Used with // the strings "GeneratorVoltage(slotOf)" / "GeneratorVoltage(scalar)". //####################################################################### // ScalarBarGauge chains the MUNGA L4 bar primitive @00472ef0 == the engine // BarGraphBitMapScalar (WipeGaugeScalar). Its value slot @0xB4 (this[0x2D]) // IS the inherited WipeGaugeScalar::currentValue -- the connection writes it, // so NO own field is declared (declaring one would shadow / mis-align). class ScalarBarGauge : public BarGraphBitMapScalar // @00472ef0 base (WipeGaugeScalar : GraphicGauge) { public: // @004c721c -- the "slotOf" variant: bar body then AddConnection(new // GeneratorVoltageConnection @004c3288) feeding currentValue from a // resolved voltage source. (The @004c72ac plain-Scalar variant is unused // by the cluster path.) ScalarBarGauge( // @004c721c GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number, int left, int bottom, int right, int top, const char *tile_image, int foreground_color, int background_color, WipeGaugeScalar::Direction direction, Scalar min, Scalar max, void *voltage_source, const char *identification_string); // @004c72ac -- the plain-Scalar variant (a DIRECT Scalar* value source, a // GaugeConnectionDirectOf instead of the GeneratorVoltageConnection). // GeneratorCluster is its caller. Disambiguated from the void* overload by // the Scalar* first arg (exact match here, std-conversion to void*). ScalarBarGauge( // @004c72ac GaugeRate, ModeMask, L4GaugeRenderer *, int graphics_port_number, int left, int bottom, int right, int top, const char *tile_image, int foreground_color, int background_color, WipeGaugeScalar::Direction direction, Scalar min, Scalar max, Scalar *value_source, const char *identification_string); ~ScalarBarGauge(); // @004c733c }; //####################################################################### // GeneratorCluster -- the generator read-out panel. @004c7368 Make / // @004c746c ctor / @004c7778 dtor. vtable PTR_FUN_0051a0a0. A GraphicGauge // that owns five child gauges, parented to its own graphics port: // VertTwoPartBar (temperature) this[0x26] // ScalarBarGauge (voltage 0..12kV) this[0x27] // BitMapInverseWipe/Leak (coolant leak) this[0x28] // TwoState x2 (status lamps) this[0x29],this[0x2A] // Reads CurrentTemperature/DegradationTemperature/FailureTemperature/ // CoolantMassLeakRate/OutputVoltage attribute indices off the subsystem. // Make resolves the named subsystem ("GeneratorCluster") via FindSubObject; // warns "Subsystem not found". //####################################################################### class GeneratorCluster : public GraphicGauge { public: // gauge wave P2: registered "GeneratorCluster" (engineering buttons 9-12, // GeneratorA..D). Corrected ctor param order == binary FUN_004c746c; only // the dtor is overridden (Execute/BecameActive/TestInstance inherited). static MethodDescription methodDescription; static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c7368 GeneratorCluster( // @004c746c (BINARY param order) ModeMask, L4GaugeRenderer *, int owner_ID, int graphics_port_number, int x, int y, Subsystem *subsystem, const char *background_image, int extra_color, const char *temp_tile, int temp_bg_color, int temp_fill_color, const char *voltage_tile, int voltage_fg_color, const char *leak_image, int leak_color_b, const char *lampA_image, const char *lampB_image, int lamp_on_color, int lamp_off_color, const char *identification_string); ~GeneratorCluster(); // @004c7778 // A container panel MUST override BecameActive + Execute: the engine base // Gauge::Execute is Fail("not overridden")->abort (GAUGE.cpp:598), and the // default BecameActive self-inactivates. The panel draws its static // background pixmap; the 5 self-registered child gauges draw the dynamic // content. (The decode's "only the dtor is overridden" was wrong: the // 1995 base Gauge::Execute was a no-op, the 2007 engine's aborts.) void BecameActive(); void Execute(); protected: char *backgroundImage; // @0x90 this[0x24] interned .pcc (pixelMap8Bin AddRef'd) int secondaryColor; // @0x94 this[0x25] = leak colorB (stored, unread here) GraphicGauge *temperatureBar, // @0x98 this[0x26] VertTwoPartBar *voltageBar, // @0x9C this[0x27] ScalarBarGauge (@004c72ac variant) *leakGauge, // @0xA0 this[0x28] BitMapInverseWipe *lampA, // @0xA4 this[0x29] TwoState *lampB; // @0xA8 this[0x2A] TwoState Subsystem *subsystem; // @0xAC this[0x2B] int _reserved0xB0; // @0xB0 this[0x2C] (trailing pad -> sizeof 0xB4) }; //####################################################################### // PrepEngrScreen (config keyword "prepEngr") -- the per-engineering-screen // STATIC LABEL overlay. @004c7b30 Make / @004c7bf0 ctor / @004c7d14 dtor / // @004c7e48 BecameActive. vtable PTR_FUN_0051a06c. // // A GraphicGaugeBackground (paint-on-activation, NOT an Execute gauge -- the // same base/vtable shape as the engine's BackgroundBitmap: only the dtor + // BecameActive slots are overridden). Interns 7 status .pcc's (font + 6 // labels) and, when its MFD-Eng screen (1..12) activates, paints the labels // for the ONE subsystem whose auxScreenNumber == this screen, dispatched by // the subsystem's ClassID. Was a MISLABELED stub (base Gauge, Execute, and // mech/screenNumber SWAPPED) with no methodDescription -> "prepEngr" was // parse-skipped (12 CFG calls never built). //####################################################################### class PrepEngrScreen : public GraphicGaugeBackground { public: static MethodDescription methodDescription; // "prepEngr" static Logical Make(int, Vector2DOf, Entity *, GaugeRenderer *); // @004c7b30 PrepEngrScreen( // @004c7bf0 ModeMask, L4GaugeRenderer *, unsigned int owner_ID, int graphics_port_number, Entity *mech, int screen_number, const char *img0/*font*/, const char *img1, const char *img2, const char *img3, const char *img4, const char *img5, const char *img6, const char *identification_string = "PrepEngr"); ~PrepEngrScreen(); // @004c7d14 void BecameActive(); // @004c7e48 (the paint slot -- NOT Execute) protected: int screenNumber; // @0x6C this[0x1B] (FIX: was mech) Entity *mech; // @0x70 this[0x1C] (FIX: was screenNumber) char *statusImage[7]; // @0x74 this[0x1D..0x23] (interned .pcc names) // sizeof == 0x90 (Make alloc); no offset locks (2007 GraphicGaugeBackground // base not byte-identical; every read is via named members / safe accessors). }; //####################################################################### // SubsystemCluster family -- the big composite panels. Each is a // GraphicGauge that builds a dozen child gauges into one cockpit instrument. // // SubsystemCluster @004c8140 (vtable 0051a020) -- base "engineering" // panel: HorizTwoPartBar + cooling/power loops + generator voltage + // OneOfSeveralInt + OneOfSeveralStates + 2x VertTwoPartBar + LeakGauge // + BackgroundBitmap. Uses the btXXloop / btXbus / evolt / btecmode / // eleak palette files. Reads InputVoltage/HeatSink/CurrentTemperature/ // DegradationTemperature/FailureTemperature attributes. // // HeatSinkCluster @004c8a6c (vtable 00519fd4) : SubsystemCluster // adds 4 failure-annunciator TwoStates (btehfail/btepfail/btesfail) // and a NumericDisplayScalar. Execute @004c8db0 scales this[0x35] by // _DAT_004c8df0 into the numeric read-out. // // WeaponCluster @004c8fc4 (vtable 00519f38) : SubsystemCluster // adds a SegmentArc270 (recharge dial, 0..360) + a ConfigMapGauge. // Make-time warns "WeaponCluster missing ". Reads "PercentDone". // Execute @004c9290 toggles a warning lamp when this[0x36] > _DAT_004c92e0. // // EnergyWeaponCluster @004c93b0 (vtable 00519ee8) : WeaponCluster // adds a SeekVoltageGraph ("EngrGraph", edestryd.pcc) and a // seek-step OneOfSeveralInt (bteseek.pcc, subsys+0x3F0). // BallisticWeaponCluster @004c9558 (vtable 00519e98) : WeaponCluster // adds 2x NumericDisplayInteger (ammo), jam/fire TwoStates // (btejam/btefire), NumericDisplayScalarTwoState, an eject // BitMapInverseWipeScalar (bteejtm) reading subsys+0x3F8, plus a // GraphicsViewRecord erase tracker (this[0x3F]). Execute @004c9a38 // tracks weaponAlarm==5 (Jammed) and the ammo-bin link (+0x43C). //####################################################################### class SubsystemCluster : public GraphicGauge { public: // @004c8140. Binary param order (rate/mode are hardcoded 0xFFFF/0xFFFFFFFF // in the base GraphicGauge ctor; the panel's two bit-plane MODE masks are // mfd_mode (MFD-port children) and eng_mode (engineering-port children)). SubsystemCluster( // @004c8140 ModeMask mfd_mode, L4GaugeRenderer *renderer, int owner_ID, int mfd_port, int x, int y, Subsystem *subsystem, ModeMask eng_mode, const char *eng_port_name, const char *tile_image, const char *label, char **image_names, const char *identification_string); ~SubsystemCluster(); // @004c87dc Logical TestInstance() const; void BecameActive(); // @004c88e4 (shared base Execute trampoline) void Execute(); // @004c88e4 protected: BackgroundBitmap *background; // @0x90 this[0x24] BackgroundBitmap GraphicGauge *generatorVoltageBar, // @0x94 this[0x25] ScalarBarGauge (evolt) *temperatureBar, // @0x98 this[0x26] HorizTwoPartBar *coolingLoopA, // @0x9C this[0x27] AnimatedSubsystemLamp *coolingLoopB, // @0xA0 this[0x28] *powerSourceA, // @0xA4 this[0x29] *powerSourceB, // @0xA8 this[0x2A] *vertBarA, // @0xAC this[0x2B] VertTwoPartBar *vertBarB, // @0xB0 this[0x2C] *modeLamp, // @0xB4 this[0x2D] OneOfSeveralInt *stateLamp, // @0xB8 this[0x2E] OneOfSeveralStates *leakGauge; // @0xBC this[0x2F] LeakGauge Subsystem *subsystem; // @0xC0 this[0x30] // POLARITY CORRECTED (PPC-dial fix, 2026-07-12): the binary's // *(subsystem+0x40)==1 means the subsystem FAILED -- it lights the // destroyed-X TwoStates (engine TwoState draws bright on NONZERO) and // selects the dead-panel look (GetDrawState 1 = black fill). The old // name `operating` had it backwards, inverting every consumer. Logical failedState; // @0xC4 this[0x31] 1 = subsystem destroyed int previousDrawState; // @0xC8 this[0x32] (Execute repaint key) // internal helpers (non-virtual; @004c89c4 / @004c8820 / @004c8a28) void DrawPanelFrame(int color); // @004c89c4 void ReleaseChildren(); // @004c8820 void SetChildrenEnable(int enable); // @004c8a28 public: int GetDrawState(); // @004c8990 (operational-state virtual, vtbl+0x48) protected: }; class HeatSinkCluster : // @004c8a6c public SubsystemCluster { public: HeatSinkCluster( // @004c8a6c ModeMask mfd_mode, L4GaugeRenderer *, int owner_ID, int mfd_port, int x, int y, Subsystem *subsystem, Subsystem *hud, ModeMask eng_mode, const char *eng_port_name, const char *tile_image, const char *label, const char *fail_lamp_image, char **image_names, const char *identification_string); ~HeatSinkCluster(); // @004c8d18 void Execute(); // @004c8db0 protected: Subsystem *failSubsystem; // @0xCC this[0x33] Logical failFlag; // @0xD0 this[0x34] Scalar heatLoad; // @0xD4 this[0x35] Scalar heatLoadScaled; // @0xD8 this[0x36] GraphicGauge *heatFailLamp, // @0xDC this[0x37] TwoState *hsFailLamp, // @0xE0 this[0x38] TwoState (btehfail) *powerFailLamp, // @0xE4 this[0x39] TwoState (btepfail) *structFailLamp, // @0xE8 this[0x3A] TwoState (btesfail) *heatNumeric; // @0xEC this[0x3B] NumericDisplayScalar }; // // MyomerCluster @004c8df4 (vtable 00519f88) : SubsystemCluster -- the myomer // (muscle) panel. Adds a SeekVoltageGraph ("EngrGraph", edestryd.pcc) fed by // an InputVoltage GeneratorVoltageConnection (writes seekValue@0x33) + a // seek-step OneOfSeveralInt (bteseek.pcc, subsys+0x800). Execute = base. // class MyomerCluster : // @004c8df4 public SubsystemCluster { public: MyomerCluster( // @004c8df4 ModeMask mfd_mode, L4GaugeRenderer *, int owner_ID, int mfd_port, int x, int y, Subsystem *subsystem, ModeMask eng_mode, const char *eng_port_name, const char *tile_image, const char *label, char **image_names, const char *identification_string); ~MyomerCluster(); // @004c8f54 protected: Scalar seekValue; // @0xCC this[0x33] (connection dst) GraphicGauge *seekGraph, // @0xD0 this[0x34] SeekVoltageGraph *seekStepLamp; // @0xD4 this[0x35] OneOfSeveralInt }; class WeaponCluster : // @004c8fc4 public SubsystemCluster { public: WeaponCluster( // @004c8fc4 ModeMask mfd_mode, L4GaugeRenderer *, int owner_ID, int mfd_port, int x, int y, Subsystem *subsystem, ModeMask eng_mode, const char *eng_port_name, const char *tile_image, const char *label, const char *cluster_image, char **image_names, const char *identification_string); ~WeaponCluster(); // @004c91d4 void BecameActive(); // @004c9258 void Execute(); // @004c9290 virtual void DrawWarningLamp(int on); // @004c932c (virtual: BallisticWeaponCluster overrides) protected: char *clusterImage; // @0xCC this[0x33] GraphicGauge *rechargeArc; // @0xD0 this[0x34] SegmentArc270 ConfigMapGauge *configMap; // @0xD4 this[0x35] Scalar percentDone; // @0xD8 this[0x36] (connection dst) int warningCenterX; // @0xDC this[0x37] int warningCenterY; // @0xE0 this[0x38] int warningState; // @0xE4 this[0x39] const char *diagWeaponName; // PORT diagnostic (appended; clusters are plain-new) }; class EnergyWeaponCluster : // @004c93b0 public WeaponCluster { public: EnergyWeaponCluster( // @004c93b0 ModeMask mfd_mode, L4GaugeRenderer *, int owner_ID, int mfd_port, int x, int y, Subsystem *subsystem, ModeMask eng_mode, const char *eng_port_name, const char *tile_image, const char *label, const char *cluster_image, char **image_names, const char *identification_string); ~EnergyWeaponCluster(); // @004c94dc protected: SeekVoltageGraph *seekGraph; // @0xE8 this[0x3A] GraphicGauge *seekStepLamp; // @0xEC this[0x3B] OneOfSeveralInt }; class BallisticWeaponCluster : // @004c9558 public WeaponCluster { public: BallisticWeaponCluster( // @004c9558 ModeMask mfd_mode, L4GaugeRenderer *, int owner_ID, int mfd_port, int x, int y, Subsystem *subsystem, ModeMask eng_mode, const char *eng_port_name, const char *tile_image, const char *label, const char *cluster_image, char **image_names, const char *font_a, const char *font_b, const char *identification_string); ~BallisticWeaponCluster(); // @004c9940 void BecameActive(); // @004c99cc void Execute(); // @004c9a38 void DrawWarningLamp(int on); // @004c9b50 (override: dot + ammo colour swap) Logical TestInstance() const; // @004c9adc protected: Logical jammed; // @0xE8 this[0x3A] Logical firing; // @0xEC this[0x3B] Logical reloading; // @0xF0 this[0x3C] int reloadStartTime; // @0xF4 this[0x3D] Scalar reloadSeconds; // @0xF8 this[0x3E] GraphicsViewRecord *ammoErase; // @0xFC this[0x3F] GraphicGauge *ammoNumeric, // @0x100 this[0x40] NumericDisplayScalarTwoState *destroyedLamp, // @0x104 this[0x41] TwoState *jamLamp, // @0x108 this[0x42] TwoState (btejam) *fireLamp, // @0x10C this[0x43] TwoState (btefire) *ejectWipe, // @0x110 this[0x44] BitMapInverseWipeScalar *ammoCountA, // @0x114 this[0x45] NumericDisplayInteger *ammoCountB; // @0x118 this[0x46] NumericDisplayInteger }; //####################################################################### // vehicleSubSystems -- the config primitive that builds the engineering- // screen (MFD) subsystem cluster panels. Make @004cbaf0 (methodDescription // @0x51c080, 8 typeString params = the 8 status strip bitmaps) is a per- // subsystem factory: it walks the mech roster (skipping slot 0), and for each // subsystem builds the right cluster (HeatSink/Myomer/Energy/Ballistic) onto // one of 12 auxiliary MFD positions selected by subsystem[0x1dc] (the aux- // screen position 1..12). This holder just carries the registered // MethodDescription + the static Make dispatcher (there is no instance). //####################################################################### class VehicleSubSystems { public: static MethodDescription methodDescription; static Logical Make( // @004cbaf0 int display_port_index, Vector2DOf position, Entity *entity, GaugeRenderer *gauge_renderer); }; #endif