MP live-play wave: collision economy, missiles, radar transform, panel polarity, comm ticker
The interactive 2-node playtest wave -- every fix decomp-grounded and live-verified: COLLISION ECONOMY (the ram one-shot): StaticBounce mutates worldLinearVelocity per contact and ProcessCollisionList walks EVERY touched solid per frame; with 2007 terrain-as-solids the reflections compounded x4-x40 within one frame and a walking bump one-shot a pristine mech for 112,375 pts (62-pt authentic economy). Fix: frameEntryWorldVelocity restore per contact (damage always priced at the real approach speed -- all the binary's physics ever saw); Mech::Reset zeroes the mover motion (respawn = teleport); [collide-tx]/[mp-hdlr] telemetry. Gotcha #16 (engine-facility drift class). MISSILES: peer-visible salvos (the launcher record extension carries a salvo counter + aim point; ForceUpdate actually enqueues it -- the dirty flag alone never serialized), the authentic arc (authored MuzzleVelocity vector + the Seeker's 200m/0.1/300 loft + gain-4 steering, decoded from @004beae4/@004bef78), world-impact bursts (rounds detonate on cave geometry instead of phasing through), contact-only damage (flight-cap expiry = fizzle, no more teleport damage), live re-lead, and ballistic (unguided) shells for autocannons. projweap's stale BTPushProjectile extern (the /FORCE signature trap, gotcha #6 corollary) crashed the Avatar's first AFC100 shot -- fixed + sweep rule recorded. RADAR: two transcription bugs made the scope permanently empty -- FUN_0040b244 is the affine INVERSE (not a copy) and FUN_0040adec writes ONLY the 3x3 rotation (never the translation); worldToView now Invert(view) built rotation-first. CulturalIcons sorted out of the moving grid (the phantom red pips were map props), visible-radius culls on all three draw passes, live pip verified at |delta| x ppm px. Gotcha #17 (verify the FUN_ body, not its call shape). WEAPON PANELS (the frozen-dial hunt): the binary's *(subsystem+0x40) means FAILED -- the recon's 'operating' name was backwards, inverting the destroyed-X lamps, the panel look, the children enable and the ready-lamp gate (which had NEVER executed). Polarity chain corrected end-to-end (failedState, fed by real damage saturation). Root cause of the freezes: MFD page-mode gating -- the dev composite shows ALL pages at once, so off-page dials legitimately stopped; under BT_DEV_GAUGES the 15 page-plane bits stay active (the exclusive secondary trio untouched). The SEH gauge guard now names its kills; repaint-heal resets the incremental arc after panel repaints; [panel]/[arc] probes added. COMM/SCORE: MessageBoard LIVE (the engine already shipped the whole Player__StatusMessage queue; wired the binary's one producer -- the kill branch, victim's name, 6s -- plus the consumer bridge and a lazy source bind); MP DEATHS counted via the observed-death tally (each node scores every pilot from locally observed events, the same model as the KILLS credit) and the -2/-1 engine seed clamped for display. DEV UX: node-tagged window titles (-net port), gauge panel reworked (1320x480, true 4:3 MFD cells, the portrait secondary UNROTATED upright, linear filtering, BT_GAUGE_SCALE), fixed close spawns via BT_SPAWN_XZ, Boreas flies an Avatar (first second-chassis live outing). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
dd27238ceb
commit
bb795e2805
@@ -579,7 +579,17 @@ Logical
|
||||
if (s_devGaugesUpd)
|
||||
{
|
||||
if (!GuardedExecute())
|
||||
{
|
||||
// LOUD KILL (2026-07-12): the silent version made a faulted
|
||||
// gauge simply FREEZE on screen (user-hit: a weapon panel's
|
||||
// dial + lamp died mid-session with no trace). Name the
|
||||
// casualty so the log convicts the faulting Execute.
|
||||
DEBUG_STREAM << "[gauge-fault] '"
|
||||
<< (identificationString ? identificationString : "?")
|
||||
<< "' Execute FAULTED -> gauge DISABLED (this="
|
||||
<< (void *)this << ")\n" << std::flush;
|
||||
Disable(True);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -3628,15 +3628,24 @@ void
|
||||
// Radar contacts are the DYNAMIC vehicles (mechs), not the props/terrain/
|
||||
// projectiles that AllEntityIterator would flood the grid with -- iterate the
|
||||
// dynamic masters (the local + AI/dummy vehicles) plus the dynamic replicants
|
||||
// (peer vehicles in multiplayer). Static beacons/props (a separate
|
||||
// classification) are left for a follow-up.
|
||||
// (peer vehicles in multiplayer).
|
||||
// CLASSIFICATION (the phantom-red-pip fix, 2026-07-12): the dynamic
|
||||
// iterators ALSO surface non-Mover world entities (the map's CulturalIcon
|
||||
// props, class 0x5E, register dynamic on this port) -- unsorted, they drew
|
||||
// through the radar's MOVING loop as RED contacts ("multiple pips with one
|
||||
// player"). Sort by Mover derivation: vehicles into the moving grid (red
|
||||
// pips), everything else into the static grid (the dim silhouette layer
|
||||
// DrawStatic draws) -- the follow-up the old note deferred.
|
||||
{
|
||||
HostManager::DynamicMasterEntityIterator master_iterator(host_manager);
|
||||
master_iterator.First();
|
||||
Entity *entity;
|
||||
while ((entity = master_iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
movingEntities.Add(entity);
|
||||
if (entity->IsDerivedFrom(*Mover::GetClassDerivations()))
|
||||
movingEntities.Add(entity);
|
||||
else
|
||||
staticEntities.Add(entity);
|
||||
}
|
||||
}
|
||||
{
|
||||
@@ -3645,7 +3654,10 @@ void
|
||||
Entity *entity;
|
||||
while ((entity = replicant_iterator.ReadAndNext()) != NULL)
|
||||
{
|
||||
movingEntities.Add(entity);
|
||||
if (entity->IsDerivedFrom(*Mover::GetClassDerivations()))
|
||||
movingEntities.Add(entity);
|
||||
else
|
||||
staticEntities.Add(entity);
|
||||
}
|
||||
}
|
||||
Check_Fpu();
|
||||
@@ -3665,6 +3677,22 @@ void
|
||||
Check(application->GetModeManager());
|
||||
ModeMask
|
||||
current_mode_mask = application->GetModeManager()->GetModeMask();
|
||||
// DEV-COMPOSITE (2026-07-12, the frozen-dial fix): page-gated gauges (mode
|
||||
// = their MFD page bit) freeze when their page isn't mode-active -- on the
|
||||
// pod you FLIP pages, but the dev window shows every page surface at once,
|
||||
// so six of seven weapon dials sat frozen on screen (user-hit; the arcs
|
||||
// executed exactly 8 times at startup then never again). Under
|
||||
// BT_DEV_GAUGES force the 15 MFD page-plane bits (BTL4 mode bits 0..14 =
|
||||
// MFD1/2/3 Quad+Eng1-4) active so every visible page runs. The secondary
|
||||
// trio (bits 18-20) stays authentic -- those views SHARE pixels and are
|
||||
// exclusive by design.
|
||||
{
|
||||
static int s_devAllPages = -1;
|
||||
if (s_devAllPages < 0)
|
||||
s_devAllPages = (getenv("BT_DEV_GAUGES") != NULL) ? 1 : 0;
|
||||
if (s_devAllPages)
|
||||
current_mode_mask |= (ModeMask)0x7FFF;
|
||||
}
|
||||
ModeMask
|
||||
previous_mode_mask = application->GetModeManager()->GetPreviousModeMask();
|
||||
ModeMask
|
||||
|
||||
@@ -912,6 +912,19 @@ void
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (getenv("BT_MAP_LOG"))
|
||||
{
|
||||
static int s_gi = 0;
|
||||
if ((s_gi++ % 30) == 0)
|
||||
{
|
||||
DEBUG_STREAM << "[gauima] lodVal=" << LOD_value
|
||||
<< " lodCount=" << LODCount << " chosen=" << lod_index
|
||||
<< " scales={";
|
||||
for (int gi = 0; gi < LODCount && gi < 4; ++gi)
|
||||
DEBUG_STREAM << LODScales[gi] << (gi + 1 < LODCount ? "," : "");
|
||||
DEBUG_STREAM << "} verts=" << vertexCount << "\n" << std::flush;
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------
|
||||
// Continue if the index is within range
|
||||
//-------------------------------------------------------------
|
||||
|
||||
+123
-19
@@ -127,7 +127,8 @@ static bool DevGaugeDocked()
|
||||
// render-state save/restore is needed (the next frame resets device state).
|
||||
//===========================================================================//
|
||||
void SVGA16::DrawDevSurface(LPDIRECT3DDEVICE9 device, int slot, int mask, int paletteID,
|
||||
int monoTint, float dstX, float dstY, float dstW, float dstH)
|
||||
int monoTint, float dstX, float dstY, float dstW, float dstH,
|
||||
int rotateCCW)
|
||||
{
|
||||
int w = pixelBuffer.Data.Size.x; // 640
|
||||
int h = pixelBuffer.Data.Size.y; // 480
|
||||
@@ -181,6 +182,10 @@ void SVGA16::DrawDevSurface(LPDIRECT3DDEVICE9 device, int slot, int mask, int pa
|
||||
}
|
||||
|
||||
// Draw the surface quad at (dstX,dstY,dstW,dstH) in the current render target.
|
||||
// rotateCCW: the pod's SECONDARY screen was a physically ROTATED portrait
|
||||
// CRT -- the game authors its content sideways in the landscape buffer and
|
||||
// the cabinet monitor unrotated it. On the dev panel WE unrotate: display
|
||||
// the texture turned 90 degrees so the radar/secondary reads upright.
|
||||
struct InsetVert { float x, y, z, rhw, u, v; };
|
||||
InsetVert quad[4] =
|
||||
{
|
||||
@@ -189,8 +194,26 @@ void SVGA16::DrawDevSurface(LPDIRECT3DDEVICE9 device, int slot, int mask, int pa
|
||||
{ dstX + dstW, dstY + dstH, 0.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ dstX, dstY + dstH, 0.0f, 1.0f, 0.0f, 1.0f },
|
||||
};
|
||||
if (rotateCCW == 1) // screen corner <- texture corner, turned CCW
|
||||
{
|
||||
quad[0].u = 1.0f; quad[0].v = 0.0f; // TL <- TR
|
||||
quad[1].u = 1.0f; quad[1].v = 1.0f; // TR <- BR
|
||||
quad[2].u = 0.0f; quad[2].v = 1.0f; // BR <- BL
|
||||
quad[3].u = 0.0f; quad[3].v = 0.0f; // BL <- TL
|
||||
}
|
||||
else if (rotateCCW == 3) // the other direction (CW), env-selectable
|
||||
{
|
||||
quad[0].u = 0.0f; quad[0].v = 1.0f; // TL <- BL
|
||||
quad[1].u = 0.0f; quad[1].v = 0.0f; // TR <- TL
|
||||
quad[2].u = 1.0f; quad[2].v = 0.0f; // BR <- TR
|
||||
quad[3].u = 1.0f; quad[3].v = 1.0f; // BL <- BR
|
||||
}
|
||||
device->SetTexture(0, tex);
|
||||
device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
|
||||
// LINEAR sampling: the cells scale the 8-bit surfaces (sec runs 0.75x at
|
||||
// scale 1.0); point sampling drops the radar's 1px strokes entirely.
|
||||
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
@@ -218,18 +241,27 @@ struct BTGaugeSurfaceDesc
|
||||
int monoTint; // -1 = palette (sec); else R5G6B5 tint
|
||||
float cellX, cellY; // normalized cell origin within the panel (y down)
|
||||
float cellW, cellH; // normalized cell size
|
||||
int rotateCCW; // 1 = unrotate (portrait secondary CRT)
|
||||
};
|
||||
|
||||
// PANEL LAYOUT (2026-07-12 rework): the old 3x2 equal grid DOWNSCALED every
|
||||
// 640x480 surface into a 320x192 cell (blurry) and showed the SECONDARY
|
||||
// (radar) sideways -- on the pod that screen was a physically ROTATED
|
||||
// portrait CRT. New layout, logical 1320x480: a 2x2 block of mono MFDs on
|
||||
// the left at 320x240 (correct 4:3), the secondary UNROTATED in a portrait
|
||||
// 360x480 cell in the middle, Comm top-right. Scale the whole window with
|
||||
// BT_GAUGE_SCALE (e.g. 1.5) for more pixels -- content is a 1995 8-bit
|
||||
// buffer, so past ~1.5x you magnify, not sharpen.
|
||||
static const float kBTPanelW = 1320.0f;
|
||||
static const float kBTPanelH = 480.0f;
|
||||
static const BTGaugeSurfaceDesc kBTGaugeSurfaces[6] =
|
||||
{
|
||||
// top row: Heat (UL) | Mfd2 (UC) | Comm (UR)
|
||||
{ "Heat", 0xFFFF, 0.0f / 3, 0.0f, 1.0f / 3, 0.5f },
|
||||
{ "Mfd2", 0xFFFF, 1.0f / 3, 0.0f, 1.0f / 3, 0.5f },
|
||||
{ "Comm", 0xFFFF, 2.0f / 3, 0.0f, 1.0f / 3, 0.5f },
|
||||
// bottom row: Mfd1 (LL) | sec/radar (center) | Mfd3 (LR)
|
||||
{ "Mfd1", 0xFFFF, 0.0f / 3, 0.5f, 1.0f / 3, 0.5f },
|
||||
{ "sec", -1, 1.0f / 3, 0.5f, 1.0f / 3, 0.5f },
|
||||
{ "Mfd3", 0xFFFF, 2.0f / 3, 0.5f, 1.0f / 3, 0.5f },
|
||||
{ "Heat", 0xFFFF, 0.0f / kBTPanelW, 0.0f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
{ "Mfd2", 0xFFFF, 320.0f / kBTPanelW, 0.0f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
{ "Mfd1", 0xFFFF, 0.0f / kBTPanelW, 0.5f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
{ "Mfd3", 0xFFFF, 320.0f / kBTPanelW, 0.5f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
{ "sec", -1, 640.0f / kBTPanelW, 0.0f, 360.0f / kBTPanelW, 1.0f, 1 },
|
||||
{ "Comm", 0xFFFF, 1000.0f / kBTPanelW, 0.0f, 320.0f / kBTPanelW, 0.5f, 0 },
|
||||
};
|
||||
|
||||
//
|
||||
@@ -243,6 +275,16 @@ void BTDrawGaugeSurfaces(LPDIRECT3DDEVICE9 device, float px, float py, float pw,
|
||||
GaugeRenderer *gr = application ? application->GetGaugeRenderer() : NULL;
|
||||
if (gr == NULL) return;
|
||||
|
||||
// DEVICE-STATE ISOLATION (the "floating cavern rocks" bug): the per-surface
|
||||
// quad draw disables Z (D3DRS_ZENABLE=FALSE), culling and lighting, binds a
|
||||
// pre-transformed FVF and rewrites texture stage 0 -- and the world pass
|
||||
// does NOT re-assert these each frame, so the NEXT frame's world rendered
|
||||
// WITHOUT DEPTH TESTING (geometry resolved in submission order; rock
|
||||
// columns drew "floating / unconnected"). Snapshot the whole device state
|
||||
// and restore it after the composite -- dev-only path, cost irrelevant.
|
||||
IDirect3DStateBlock9 *stateBlock = NULL;
|
||||
device->CreateStateBlock(D3DSBT_ALL, &stateBlock);
|
||||
|
||||
// Reach the shared display once (any present port shares the same SVGA16/pixelBuffer).
|
||||
SVGA16 *svga = NULL;
|
||||
for (int i = 0; i < 6 && svga == NULL; i++)
|
||||
@@ -257,9 +299,30 @@ void BTDrawGaugeSurfaces(LPDIRECT3DDEVICE9 device, float px, float py, float pw,
|
||||
const BTGaugeSurfaceDesc &d = kBTGaugeSurfaces[i];
|
||||
L4GraphicsPort *port = static_cast<L4GraphicsPort*>(gr->GetGraphicsPort(d.portName));
|
||||
if (port == NULL) continue; // this surface's port isn't configured -> skip
|
||||
// Secondary-CRT unrotation direction is env-flippable (BT_GAUGE_SEC_ROT=3
|
||||
// for the other way) in case the assumed pod mounting is mirrored.
|
||||
int rot = d.rotateCCW;
|
||||
if (rot != 0)
|
||||
{
|
||||
static int s_secRot = -1;
|
||||
if (s_secRot < 0)
|
||||
{
|
||||
// Default 3 (CW): user-verified upright (the first guess, 1,
|
||||
// showed the secondary upside down). Env still overrides.
|
||||
const char *rv = getenv("BT_GAUGE_SEC_ROT");
|
||||
s_secRot = (rv != NULL && rv[0] == '1') ? 1 : 3;
|
||||
}
|
||||
rot = s_secRot;
|
||||
}
|
||||
svga->DrawDevSurface(
|
||||
device, i, port->GetBitMask(), port->paletteID, d.monoTint,
|
||||
px + d.cellX * pw, py + d.cellY * ph, d.cellW * pw, d.cellH * ph);
|
||||
px + d.cellX * pw, py + d.cellY * ph, d.cellW * pw, d.cellH * ph, rot);
|
||||
}
|
||||
|
||||
if (stateBlock != NULL)
|
||||
{
|
||||
stateBlock->Apply();
|
||||
stateBlock->Release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,7 +336,8 @@ void BTDrawGaugeInset(LPDIRECT3DDEVICE9 device)
|
||||
{
|
||||
if (!DevGaugeComposite() || !DevGaugeDocked() || device == NULL) return;
|
||||
// DOCKED mode only: draw into the main backbuffer (this runs before EndScene).
|
||||
BTDrawGaugeSurfaces(device, 2.0f, 300.0f, 540.0f, 296.0f);
|
||||
// Keep the new panel's 1320:480 aspect (2.75) so nothing distorts.
|
||||
BTDrawGaugeSurfaces(device, 2.0f, 400.0f, 540.0f, 540.0f / 2.75f);
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
@@ -286,13 +350,32 @@ void BTDrawGaugeInset(LPDIRECT3DDEVICE9 device)
|
||||
//===========================================================================//
|
||||
static HWND s_gaugeHwnd = NULL;
|
||||
static IDirect3DSwapChain9 *s_gaugeSwap = NULL;
|
||||
static const int s_gaugeW = 960;
|
||||
static const int s_gaugeH = 384;
|
||||
// Window = the logical 1320x480 panel (see kBTGaugeSurfaces) x BT_GAUGE_SCALE.
|
||||
// Resolved once at first ensure; default 1.0 (surfaces at/near native pixels).
|
||||
static int s_gaugeW = 1320;
|
||||
static int s_gaugeH = 480;
|
||||
static bool s_gaugeSized = false;
|
||||
|
||||
static void BTGaugeResolveSize()
|
||||
{
|
||||
if (s_gaugeSized) return;
|
||||
s_gaugeSized = true;
|
||||
const char *sv = getenv("BT_GAUGE_SCALE");
|
||||
float scale = (sv != NULL) ? (float)atof(sv) : 1.0f;
|
||||
if (scale < 0.5f || scale > 3.0f) scale = 1.0f;
|
||||
s_gaugeW = (int)(1320.0f * scale);
|
||||
s_gaugeH = (int)(480.0f * scale);
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK BTGaugeWndProc(HWND h, UINT m, WPARAM w, LPARAM l)
|
||||
{
|
||||
if (m == WM_CLOSE) { ShowWindow(h, SW_HIDE); return 0; } // hide, never quit the app
|
||||
return DefWindowProc(h, m, w, l);
|
||||
// Fully-WIDE window (class + create + proc all W; the class/create below
|
||||
// are RegisterClassW/CreateWindowExW): mixed A/W pairings mangled the
|
||||
// title -- A-class + W-proc painted the ANSI bytes as UTF-16 (CJK-looking
|
||||
// mojibake), W-class + A-proc truncated at the first thunked NUL ("B").
|
||||
// One consistent character set ends the thunk roulette.
|
||||
return DefWindowProcW(h, m, w, l);
|
||||
}
|
||||
|
||||
// Lazily create the window + its additional swap chain (on the MAIN device).
|
||||
@@ -301,26 +384,47 @@ static bool BTGaugeWindowEnsure(LPDIRECT3DDEVICE9 device)
|
||||
if (s_gaugeSwap != NULL) return true;
|
||||
if (device == NULL) return false;
|
||||
|
||||
BTGaugeResolveSize(); // BT_GAUGE_SCALE -> window dims
|
||||
HINSTANCE hInst = GetModuleHandle(NULL);
|
||||
static bool s_classReg = false;
|
||||
if (!s_classReg)
|
||||
{
|
||||
WNDCLASSA wc;
|
||||
// WIDE APIs throughout: this TU compiles UNICODE, so BTGaugeWndProc's
|
||||
// DefWindowProc resolves to the W variant -- registering the class
|
||||
// with RegisterClassA made Windows reinterpret the ANSI title bytes
|
||||
// as UTF-16 (the "Korean garbage title" bug: byte-pairs of
|
||||
// "BattleTech - Cockpit MFDs" land in the CJK plane, only the
|
||||
// trailing 's'+NUL survives readable).
|
||||
WNDCLASSW wc;
|
||||
memset(&wc, 0, sizeof(wc));
|
||||
wc.lpfnWndProc = BTGaugeWndProc;
|
||||
wc.hInstance = hInst;
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
|
||||
wc.lpszClassName = "BTGaugeWnd";
|
||||
RegisterClassA(&wc);
|
||||
wc.lpszClassName = L"BTGaugeWnd";
|
||||
RegisterClassW(&wc);
|
||||
s_classReg = true;
|
||||
}
|
||||
if (s_gaugeHwnd == NULL)
|
||||
{
|
||||
RECT r = { 0, 0, s_gaugeW, s_gaugeH };
|
||||
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE);
|
||||
s_gaugeHwnd = CreateWindowExA(
|
||||
0, "BTGaugeWnd", "BattleTech - Cockpit MFDs", WS_OVERLAPPEDWINDOW,
|
||||
// Window identity (MP dev): tag with the -net port so two side-by-side
|
||||
// nodes' MFD windows are distinguishable (matches the main window tag).
|
||||
wchar_t gaugeTitle[64];
|
||||
{
|
||||
int netPort = 0;
|
||||
const char *cmd = GetCommandLineA();
|
||||
const char *np = (cmd != NULL) ? strstr(cmd, "-net") : NULL;
|
||||
if (np != NULL)
|
||||
sscanf(np + 4, " %d", &netPort);
|
||||
if (netPort > 0)
|
||||
swprintf(gaugeTitle, 64, L"BattleTech MFDs \x2014 node %d", netPort);
|
||||
else
|
||||
wcscpy(gaugeTitle, L"BattleTech - Cockpit MFDs");
|
||||
}
|
||||
s_gaugeHwnd = CreateWindowExW(
|
||||
0, L"BTGaugeWnd", gaugeTitle, WS_OVERLAPPEDWINDOW,
|
||||
40, 40, r.right - r.left, r.bottom - r.top, NULL, NULL, hInst, NULL);
|
||||
if (s_gaugeHwnd == NULL) return false;
|
||||
ShowWindow(s_gaugeHwnd, SW_SHOWNOACTIVATE);
|
||||
|
||||
@@ -300,8 +300,11 @@ public:
|
||||
// dstW,dstH). monoTint < 0 -> palette-expand (sec/radar, case-0 LUT); monoTint >= 0
|
||||
// -> mono bit-plane expand ((word & mask) ? tint : 0) for an MFD plane. See
|
||||
// BTDrawGaugeSurfaces (L4VB16.cpp).
|
||||
// rotateCCW: 0 = as-is; 1/3 = display the texture turned 90 degrees (the
|
||||
// pod's portrait-mounted secondary CRT; the dev panel unrotates it).
|
||||
void DrawDevSurface(LPDIRECT3DDEVICE9 device, int slot, int mask, int paletteID,
|
||||
int monoTint, float dstX, float dstY, float dstW, float dstH);
|
||||
int monoTint, float dstX, float dstY, float dstW, float dstH,
|
||||
int rotateCCW = 0);
|
||||
};
|
||||
|
||||
//########################################################################
|
||||
|
||||
Reference in New Issue
Block a user