//===========================================================================// // File: btl4gau3.hpp // // Project: BattleTech Brick: Gauge Renderer Manager // // Contents: Cockpit instrument library, part 3 -- the MULTIPLAYER / TACTICAL // // HUD displays: the scoreboard, pilot roster, per-player status // // name-tags, the sector display and the message board. These read // // the shared "Players" roster and the live mech roster rather than // // a single subsystem. // // * PlayerStatusMappingGroup -- 28-zone armour colour-tint group // // * SectorDisplay -- grid-cell blit + dual numeric // // * TeamStatusDisplay -- 8-row scoreboard (DEFERRED) // // * PilotList -- 8-pilot KILLS/DEATHS roster // // * PlayerStatus -- single-player status name-tag // // * MessageBoard -- message / sender bitmap board // //---------------------------------------------------------------------------// // Date Who Modification // // -------- --- ---------------------------------------------------------- // // 02/22/96 CPB Initial coding. // //---------------------------------------------------------------------------// // Copyright (C) 1996, Virtual World Entertainment, Inc. All rights reserved // // PROPRIETARY AND CONFIDENTIAL // //===========================================================================// // // STAGED RECONSTRUCTION. No BTL4GAU3.HPP survived; recovered from // BTL4OPT.EXE and re-hosted onto the authentic 1995 engine headers // (MUNGA/GAUGE.HPP + GAUGREND.HPP, MUNGA_L4/L4GAUGE.HPP). Class names from // the per-instance identification strings near 0x51bb34: // "SectorDisplay" 0x51bb34 "PilotList" 0x51bb4a "PlayerStatus" 0x51bb54 // "MessageBoard" 0x51bb61 "PlayerStatusMappingGroup" 0x51bdb4 // "Players" 0x51bcba/0x51bd97 (shared roster node) // // Translation-unit extent (BTL4.MAK: btl4gau2 -> btl4gau3 -> btl4grnd): // first gau3 code @004c9bd0 (PlayerStatusMappingGroup builder) // last gau3 code @004cbea0-1 (MessageBoard::Execute @004cb82c) // btl4grnd begins @004cbea0 (BTL4GaugeRenderer ctor -- not this TU) // // Vtables (recovered from the ctors): SectorDisplay 0051beec, // TeamStatusDisplay 0051bea8, PilotList 0051be64, PlayerStatus 0051be20, // MessageBoard 0051bddc. All derive from GraphicGauge. // // The @0xNN member annotations are the BINARY object offsets (provenance // only): the reconstructed engine bases are not byte-identical to the // shipped objects, and every read in this TU is through named members. // #if !defined(BTL4GAU3_HPP) # define BTL4GAU3_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 //##################### Forward Class Declarations ####################### class Player; // // Reconstruction alias: the binary's per-player recoloured "Pixmap" is the // engine's 8-bit pixel map. (Only Pixmap* appears in this header / TU.) // typedef PixelMap8 Pixmap; //####################################################################### // PlayerStatusMappingGroup -- a colour-tint group of 28 ColorMapperArmor // gauges, one per named damage zone ("dz_door"... PTR_s_dz_door_0051a240, // 0x1C=28 entries). Built by PlayerStatus to tint a player's mech outline // bitmap by per-zone armour damage. @004c9bd0 build / @004c9ca8 destroy / // @004c9cf4 Execute-all / @004c9d18 SetColor-all. Each element is a // ColorMapperArmor (btl4gaug) wired to a resolved damage-zone index. // (palette files adpal.pcc / adpal2.pcc; name "PlayerStatusMappingGroup".) //####################################################################### enum { playerStatusZoneCount = 28 }; class PlayerStatusMappingGroup { public: PlayerStatusMappingGroup( // @004c9bd0 GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer, int graphics_port_number, Entity *mech, int base_color_index, const char *palette_a, const char *palette_b, const char *identification_string ); ~PlayerStatusMappingGroup(); // @004c9ca8 Logical TestInstance() const; void Execute(); // @004c9cf4 (run all 28) void SetColor(int color); // @004c9d18 (recolour all 28) protected: ColorMapperArmor *zone[playerStatusZoneCount]; // this[0..0x1B] }; //####################################################################### // SectorDisplay (config keyword "sectorDisplay") -- the radar SECTOR X/Z // read-out on the Secondary overlay: a one-shot grid-cell background blit + // two 3-digit NumericDisplays showing the linked mech's world sector coords // (Round(-Z*0.01)+500, Round(X*0.01)+500 -> 100-unit sectors). // @004c9d44 Make / @004c9e10 ctor / @004c9f94 dtor / @004ca038 BecameActive / // @004ca068 LinkToEntity (slot 9) / @004ca07c Execute. vtable 0051beec. // Was PROSE-ONLY (parse-skipped "sectorDisplay" line); reconstructed // byte-verified from the disassembly + methodDescription PE-parse. //####################################################################### class SectorDisplay : public GraphicGauge { public: static MethodDescription methodDescription; // "sectorDisplay" static Logical Make( // @004c9d44 int display_port_index, Vector2DOf position, Entity *entity, GaugeRenderer *gauge_renderer ); SectorDisplay( // @004c9e10 (owner folded to 0, like the siblings) GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer, int graphics_port_number, int x, int y, const char *image, int color, int ok_color, const char *identification_string ); ~SectorDisplay(); // @004c9f94 Logical TestInstance() const; void LinkToEntity(Entity *entity); // @004ca068 slot 9 -- caches the subject mech void BecameActive(); // @004ca038 slot 3 (non-inactivating) void Execute(); // @004ca07c protected: Entity *subject; // @0x90 LinkToEntity target (ctor=0) char *gridImage; // @0x94 interned image name (nameCopy; blit source) int cellWidth; // @0x98 imageWidth / 14 int gridLeft; // @0x9C cellWidth*12 int gridRight; // @0xA0 cellWidth*13 - 1 int gridHeight; // @0xA4 imageHeight int numericColor; // @0xA8 param color (both numerics' color) int gridColor; // @0xAC param okColor (blit color + numeric okColor) int sectorBaseA; // @0xB0 = 500 (added to the -Z numeric) int sectorBaseB; // @0xB4 = 500 (added to the +X numeric) int dirty; // @0xB8 redraw flag (BecameActive=1, Execute clears) NumericDisplay *numericA, // @0xBC -Z sector readout *numericB; // @0xC0 X sector readout // Binary sizeof == 0xC4 (the Make alloc). Provenance only: the // reconstructed GraphicGauge base is not byte-identical to 1995 and // every read here is via named members. }; //####################################################################### // TeamStatusDisplay -- the 8-slot multiplayer scoreboard. @004ca208 ctor / // @004ca39c dtor / @004ca424 SetEnable / @004ca438 BecameActive / // @004ca478 Execute. vtable 0051bea8. Each of the 8 rows owns a // NumericDisplay pair (player number + kill count). Execute reads the // shared "Players" node (FindByName @00403ad0, "Players" 0x51bcba), slots // players by their player index (entity+0x1cc), draws each player's name // bitmap / kill numeric and a selection highlight on the local player. // // DEFERRED: the donor reconstruction is PROSE-ONLY (no recovered bodies, // no methodDescription, no config keyword registered) -- declaration kept // so the binary class inventory stays visible; NO bodies exist in // BTL4GAU3.CPP and nothing constructs it. See the deferred note there. //####################################################################### class TeamStatusDisplay : public GraphicGauge { public: TeamStatusDisplay( // @004ca208 GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer, int graphics_port_number, int x, int y, const char *font_image, int row_spacing, int flags, const char *identification_string ); ~TeamStatusDisplay(); // @004ca39c Logical TestInstance() const; void SetEnable(Logical enable); // @004ca424 this[0x24] void BecameActive(); // @004ca438 void Execute(); // @004ca478 protected: Logical enabled; // @0x90 this[0x24] int selectedRow; // @0x94 this[0x25] (=999) int originX; // @0x98 this[0x26] int originY; // @0x9C this[0x27] (param y - 0x20) int flags; // @0xA0 this[0x28] int rowSpacing; // @0xA4 this[0x29] int highlightWidth; // @0xA8 this[0x2A] struct Row { // 8 rows starting at this[0x3B] NumericDisplay *numberDisplay; // player-number numeric NumericDisplay *killDisplay; // kill-count numeric (flags&4) } row[8]; }; //####################################################################### // PilotList (config keyword "pilotList") -- the Comm KILLS/DEATHS roster. // @004ca90c Make / @004ca958 ctor / @004cab10 dtor / @004caba4 BecameActive / // @004cabd0 Execute / @004cad70 DrawMechIcon. vtable 0051be64, binary // sizeof 0x178. Each entry has three NumericDisplays laid out by a // per-entry layout mode (0/1/2 -> the PE-parsed DAT_0051af88 table). // Execute walks the pilot roster ONE slot per frame (round-robin over 8). // Was PROSE-ONLY -> the "pilotList" line was parse-skipped and the Comm // surface showed only the baked btcomm.pcx labels. //####################################################################### class PilotList : public GraphicGauge { public: static MethodDescription methodDescription; // "pilotList" static Logical Make( // @004ca90c int display_port_index, Vector2DOf position, Entity *entity, GaugeRenderer *gauge_renderer ); PilotList( // @004ca958 (NO x,y: positions come from DAT_0051af88) GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer, int graphics_port_number, const char *font_image, const char *identification_string ); ~PilotList(); // @004cab10 Logical TestInstance() const; void BecameActive(); // @004caba4 void Execute(); // @004cabd0 protected: void DrawMechIcon(Player *pilot, int selected); // @004cad70 // (DrawAmmoCount @004cae20 -- documented, no recovered caller.) int currentSlot; // @0x90 this[0x24] (round-robin, =9 init) Logical built; // @0x94 this[0x25] struct Entry { // 8 entries (stride 0x1C) from this[0x26] int x; // +0x00 int y; // +0x04 int resolvedMech; // +0x08 (=-1 after BecameActive) int selected; // +0x0C NumericDisplay *nameDisplay; // +0x10 KILLS numeric NumericDisplay *mechDisplay; // +0x14 DEATHS numeric NumericDisplay *scoreDisplay; // +0x18 erase-only } entry[8]; }; //####################################################################### // PlayerStatus (config keyword "PlayerStatus") -- a single-player status // name-tag. @004cae90 Make / @004cb1a8 ctor / @004cb28c dtor / @004cb310 // BecameActive / @004cb358 Execute. vtable 0051be20, 200-byte alloc. // Make validates the player number (must be 1..8; warns "PlayerStatus: // Make player number "). Execute resolves player N from the shared // "Players" roster ("Players" 0x51bd97), recolours its mech-outline bitmap // per player palette via CreateMutantPixelmap8 (@004cafac, file-private) + // PlayerStatusMappingGroup (adpal.pcc/adpal2.pcc), and shows the player // score + an alive/dead colour state. //####################################################################### class PlayerStatus : public GraphicGauge { public: static MethodDescription methodDescription; // "PlayerStatus" static Logical Make( // @004cae90 int display_port_index, Vector2DOf position, Entity *entity, GaugeRenderer *gauge_renderer ); PlayerStatus( // @004cb1a8 (13 args; owner folded to 0 in base call) GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer, int graphics_port_number, int x, int y, int player_number, const char *font_image, int color, int okColor, int aliveColor, int deadColor, const char *identification_string ); ~PlayerStatus(); // @004cb28c Logical TestInstance() const; void BecameActive(); // @004cb310 void Execute(); // @004cb358 protected: int port; // @0x90 this[0x24] graphics_port_number int playerIndex; // @0x94 this[0x25] (player_number-1) Player *player; // @0x98 this[0x26] cached roster player (non-owned) BitMap *nameImage; // @0x9C this[0x27] name-cache BitMap (cache-owned) Pixmap *recoloredMech; // @0xA0 this[0x28] CreateMutantPixelmap8 result (owned) int color; // @0xA4 this[0x29] int okColor; // @0xA8 this[0x2A] int aliveColor; // @0xAC this[0x2B] int deadColor; // @0xB0 this[0x2C] PlayerStatusMappingGroup *mappingGroup; // @0xB4 this[0x2D] (owned; the binary LEAKED it) NumericDisplay *scoreDisplay; // @0xB8 this[0x2E] int dirty; // @0xBC this[0x2F] redraw flag int previousStatus; // @0xC0 this[0x30] last alive/dead state int previousMappingState; // @0xC4 this[0x31] }; //####################################################################### // MessageBoard (config keyword "messageBoard") -- the secondary-MFD comm/ // status message ticker. @004cb678 Make / @004cb704 ctor / @004cb788 dtor / // @004cb7fc BecameActive / @004cb818 SetSource / @004cb82c Execute. // vtable 0051bddc, binary sizeof 0xA4 (the Make alloc). Blits one cell of // the strip bitmap btsmsgs.pcx (message id -> cell (id&3)<<7, (id>>2)<<5) // plus the sender's name bitmap. Was PROSE-ONLY -> "messageBoard" was // parse-skipped. // // DEFERRED / EMPTY (authentic for bring-up): the source mech is never // bound (SetSource @004cb818 has no recovered caller) AND the per-player // status-message feed (Player::statusMessagePointer's producer pool) is // not reconstructed, so there are no messages -> Execute early-returns on // the NULL source (a safe no-op == the empty board). // // Field-order FIXes on record: trackedMech@0x90 (was decoded "int // enabled"); previousNameId@0x9C=-1 / previousMessageId@0xA0=-2 (were // swapped in the first decode). //####################################################################### class MessageBoard : public GraphicGauge { public: static MethodDescription methodDescription; // "messageBoard" static Logical Make( // @004cb678 int display_port_index, Vector2DOf position, Entity *entity, GaugeRenderer *gauge_renderer ); MessageBoard( // @004cb704 GaugeRate rate, ModeMask mode_mask, L4GaugeRenderer *renderer, int graphics_port_number, int x, int y, const char *strip_image, int color, const char *identification_string ); ~MessageBoard(); // @004cb788 Logical TestInstance() const; void BecameActive(); // @004cb7fc void SetSource(Entity *mech); // @004cb818 (binds trackedMech; no caller -> deferred) void Execute(); // @004cb82c protected: Entity *trackedMech; // @0x90 this[0x24] source mech (SetSource; ctor=0) char *stripImage; // @0x94 this[0x25] interned btsmsgs.pcx (held ref) int color; // @0x98 this[0x26] param (CFG 4th arg = 0) int previousNameId; // @0x9C this[0x27] BecameActive=-1 int previousMessageId; // @0xA0 this[0x28] BecameActive=-2 }; // NOTE: CreateMutantPixelmap8 (@004cafac) + ReadStreamString (@004caf50) // are file-PRIVATE in the binary -- declared static at the top of // BTL4GAU3.CPP, not here. #endif