diff --git a/CMakeLists.txt b/CMakeLists.txt index 741bed6..6a26664 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -278,6 +278,21 @@ target_sources(munga_engine PRIVATE # /Zp, so that part does not apply -- see the file header.) set_source_files_properties("engine/MUNGA_L4/L4KEYLIGHT.cpp" PROPERTIES COMPILE_OPTIONS "/std:c++17;/permissive-") +# ... and only where the SDK can actually compile it. SDK 10.0.19041's +# bundled cppwinrt fails inside winrt/base itself (C2039 'wait_for'), so on a +# machine with only an older SDK the TU builds its dormant stub instead -- +# same interface, logs once, everything else identical. Dynamic Lighting is +# a Windows 11 22H2 feature anyway, so nothing real is lost on such a machine. +set(_bt_sdk "${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") +if(NOT _bt_sdk) + set(_bt_sdk "${CMAKE_SYSTEM_VERSION}") +endif() +if(_bt_sdk VERSION_LESS "10.0.22000") + message(STATUS "keylight: Windows SDK ${_bt_sdk} too old for C++/WinRT " + "Dynamic Lighting -- building the dormant stub") + set_property(SOURCE "engine/MUNGA_L4/L4KEYLIGHT.cpp" APPEND PROPERTY + COMPILE_DEFINITIONS BT_KEYLIGHT_STUB) +endif() target_include_directories(munga_engine BEFORE PRIVATE "${CMAKE_SOURCE_DIR}/engine/shim" "${DXSDK}/Include") diff --git a/docs/CONTROLS.md b/docs/CONTROLS.md index ece9804..437e693 100644 --- a/docs/CONTROLS.md +++ b/docs/CONTROLS.md @@ -23,7 +23,7 @@ Flight lives on the number pad so the board stays free. | NumPad 0, Space | main trigger | | NumPad 1 / 3 / . | pinky / middle / upper | | Shift / Ctrl | throttle up / down (the lever sticks) | | Alt | reverse thrust | | ← ↓ → | look left / behind / right | | ↑ | torso centre | -| ` | cockpit / chase camera | | − / = *(see below)* | — | +| ` | cockpit / chase camera | | PgUp / PgDn | volume up / down (saved) | **You spawn in BASIC control mode.** In BASIC the stick steers and the pedals do nothing. Press **F7** once for MID, where the pedals steer and the stick twists the torso — the full @@ -66,7 +66,8 @@ ammo bay before it detonates). Binding a key removes it from the authentic 1995 typed-hotkey channel so it cannot double-dispatch. This board binds nearly everything, so those hotkeys are given up by design: `5` = MFD1 Quad page, `z` = MFD3 Eng1, `t/y/u/i/o` = pilot select, `+`/`-` = target zoom. -Unbind a key in `bindings.txt` to get its 1995 meaning back. Same rule for the built-ins: +Unbind a key in `bindings.txt` to get its 1995 meaning back. (The old `-`/`=` VOLUME keys +moved to **PgUp/PgDn** -- they no longer share a key with anything, in any layout.) Same rule for the built-ins: **`** is the view toggle (V is a board button now), and J/K/L cycle the MFD preset pages only while unbound. diff --git a/engine/MUNGA_L4/L4KEYLIGHT.cpp b/engine/MUNGA_L4/L4KEYLIGHT.cpp index d08aee7..9d39bb7 100644 --- a/engine/MUNGA_L4/L4KEYLIGHT.cpp +++ b/engine/MUNGA_L4/L4KEYLIGHT.cpp @@ -20,6 +20,40 @@ // on-screen cockpit buttons blink in step). //===========================================================================// +// +// BUILD-TIME STUB GATE (merge 2026-07-26). The C++/WinRT body below needs a +// Windows SDK whose cppwinrt headers are new enough for Dynamic Lighting -- +// SDK 10.0.19041's fail inside winrt/base itself (C2039 'wait_for'). On a +// build machine with only an older SDK, CMake defines BT_KEYLIGHT_STUB and +// this TU compiles the dormant stub instead: same five-function scalar +// interface, logs once at Start(), the game runs identically otherwise. +// This extends the feature's own runtime philosophy (no Dynamic Lighting -> +// log once, stay dormant) to build time, and keeps the link closed on every +// machine without demanding an SDK upgrade. +// +#if defined(BT_KEYLIGHT_STUB) + +#include "l4keylight.h" + +static void (*s_stubLogger)(const char *line) = 0; + +void KeyLight_SetLogger(void (*logger)(const char *line)) +{ + s_stubLogger = logger; +} +void KeyLight_SetMap(const int *, const int *, const unsigned char *, int) {} +void KeyLight_UpdateLamps(const unsigned char *, int) {} +void KeyLight_Start() +{ + if (s_stubLogger) + s_stubLogger("[keylight] built without Dynamic Lighting support " + "(Windows SDK too old at COMPILE time) -- RGB mirror " + "dormant on this build"); +} +void KeyLight_Stop() {} + +#else // the real C++/WinRT mirror + #include #include @@ -404,3 +438,5 @@ void gWorker.join(); } } + +#endif // BT_KEYLIGHT_STUB diff --git a/engine/MUNGA_L4/L4PADBINDINGS.cpp b/engine/MUNGA_L4/L4PADBINDINGS.cpp index af68103..38849f1 100644 --- a/engine/MUNGA_L4/L4PADBINDINGS.cpp +++ b/engine/MUNGA_L4/L4PADBINDINGS.cpp @@ -277,6 +277,9 @@ static const char *defaultProfileText = "key LALT button 0x3F\n" "key RALT button 0x3F\n" "\n" +"# PgUp/PgDn are the VOLUME keys (built in; they produce no typed character\n" +"# so they can never collide with a hotkey) -- leave them unbound.\n" +"\n" "# --- the four mappable fire buttons ------------------------------------\n" "# The mouse's side buttons are free if you want them on the trigger:\n" "# key MOUSE4 button 0x40\n" diff --git a/engine/MUNGA_L4/L4PADRIO.cpp b/engine/MUNGA_L4/L4PADRIO.cpp index 40229a0..51f23bf 100644 --- a/engine/MUNGA_L4/L4PADRIO.cpp +++ b/engine/MUNGA_L4/L4PADRIO.cpp @@ -649,8 +649,15 @@ void // exists to prevent. Bind the key, and the built-in stands down. { static int s_backtickWas = 0; + // BOTH halves are KeyHasBinding-guarded (merge review 2026-07-26): the + // V half already was, but backtick polled unconditionally -- and + // BACKTICK is a nameable, unbound key, so a player who bound it to a + // button got a double-dispatch (button + camera toggle), the exact + // hazard the bindings-row-wins rule exists to prevent, in the one poll + // it had not been applied to. int backtick_held = focused && - (((GetAsyncKeyState(VK_OEM_3) & 0x8000) != 0) || + ((!KeyHasBinding(VK_OEM_3) + && (GetAsyncKeyState(VK_OEM_3) & 0x8000) != 0) || (!KeyHasBinding('V') && (GetAsyncKeyState('V') & 0x8000) != 0)); if (backtick_held && !s_backtickWas) { diff --git a/game/btl4main.cpp b/game/btl4main.cpp index 3d60afd..85820b9 100644 --- a/game/btl4main.cpp +++ b/game/btl4main.cpp @@ -254,6 +254,12 @@ static const char *kEnvironIniDefault = "# a launcher .bat can override anything here. Delete a line to fall back to\n" "# the built-in default.\n" "#\n" +"# This file is for PERSISTENT settings only. One-shot switches (BT_JOYCONFIG\n" +"# -- use joyconfig.bat instead) are ignored here on purpose: they are designed\n" +"# to clear themselves after running once, and a file line would re-arm them at\n" +"# every mission start. Test/debug hooks (BT_MP_FORCE_DMG and friends) do not\n" +"# belong here either -- they would silently persist across every session.\n" +"#\n" "# Input bindings live in bindings.txt beside this file (written with the\n" "# full documented layout on first run; delete it to restore defaults).\n" "\n" @@ -483,6 +489,20 @@ static void BTLoadEnvironIni(void) if (getenv(key) != NULL) continue; + // ONE-SHOT variables never load from the file (merge review + // 2026-07-26). BT_JOYCONFIG is deliberately DELETED from the process + // environment after the wizard runs (the #66 one-shot) so the + // front-end relaunch chain cannot re-run it -- but a file line would + // re-arm it in every relaunched child, since by then there is no real + // env var left to win over the file. Result: the capture wizard at + // every mission start. environ.ini is for persistent settings; + // anything designed to clear itself cannot live in it. + if (_stricmp(key, "BT_JOYCONFIG") == 0) + { + ++skipped; + continue; + } + putenv(p); ++applied; } diff --git a/players/README.txt b/players/README.txt index 0ff9e82..2198994 100644 --- a/players/README.txt +++ b/players/README.txt @@ -46,31 +46,43 @@ around the view (one window). The red MFD buttons, radar rails and joystick buttons are all MOUSE-CLICKABLE -- right-click a button to latch it held. Press V any time to toggle the external camera. -CONTROLS (keyboard): - W/S or Up/Down ....... throttle lever X / NumPad5 ... all stop - A/D or Left/Right .... turn pedals Alt ........... reverse thrust - Q/E .................. torso twist R/F ........... torso aim - NumPad 8/2/4/6 ....... torso aim/twist (alt) Shift ......... throttle up - 1 or Space ........... main trigger 2 ............. middle thumb - 3 or Ctrl ............ upper thumb (missiles) 4 ............ pinky - V view | B look-behind | M control mode | N schematic | J/K/L MFD pages +CONTROLS (keyboard) -- NEW DEFAULT LAYOUT THIS BUILD: + The keyboard IS the cockpit button board now: the letter and number + rows are the MFD button banks laid out where they sit on the panel, + and FLIGHT LIVES ON THE NUMBER PAD. Full map: CONTROLS.txt. + + UPGRADING? Your saved content\bindings.txt is kept, so YOUR KEYS DO + NOT CHANGE (W/S throttle etc. still works for you). Delete + bindings.txt to switch to the new board described below. + + FLIGHT (number pad -- NUMLOCK ON): + NumPad 8/2 ........... torso aim up/down NumPad 7/9 .... left/right pedal + NumPad 4/6 ........... torso twist NumPad 5 ...... all stop + NumPad 0 or Space .... main trigger NumPad 1/3/. .. pinky/middle/upper + Shift/Ctrl ........... throttle up/down Alt ........... reverse thrust + Left/Down/Right ...... look left/behind/right Up .......... torso centre + ` (backtick) ......... cockpit / chase camera + PgUp / PgDn .......... game volume up/down (saved between sessions) + + THE PANEL ON YOUR KEYS: 1-4/QWER = heat & coolant, 5-8/TYUI = + engineering, 9-0-minus-equals/OP[] = comm, ASDF/ZXCV = left weapons, + HJKL/NM,. = right weapons, F1-F12 = the map columns (F1/F2 zoom, + F4 crouch, F7 CONTROL MODE, F9-F12 Generators A-D). G and B are + deliberately unbound -- feel for the gap. Every button also stays + mouse-clickable on screen (right-click latches it held). + NOTE: you SPAWN IN BASIC control mode (the pod's rookie setting) -- - in BASIC the stick steers and the pedal keys (A/D, arrows) do - NOTHING. Press M once for MID (pedals steer, stick twists the - torso -- the full experience). If 'turning does not work', it is - this, not a bug. - CONTROL MODE (BAS/MID/ADV, the M key IN the cockpit) is NOT the + in BASIC the stick steers and the pedals do NOTHING. Press F7 once + for MID (pedals steer, stick twists the torso -- the full + experience). If 'turning does not work', it is this, not a bug. + CONTROL MODE (BAS/MID/ADV, the F7 key IN the cockpit) is NOT the menu's EXPERIENCE setting (novice/standard/veteran/expert) -- that one changes the simulation (heat, damage), not your controls. - Numpad aim keys (8/2/4/6) need NUMLOCK ON; with it off they act as - arrow keys instead. - - / = ................ game volume down/up (saved between sessions) - H (hold) ............. coolant flush (dumps reservoir to cool everything) - C .................... cycle a coolant valve. CAREFUL: the detents go - 1 - 5 - 50 (max) - 0 (CLOSED!) - back to 1. One press past max - SHUTS THE LOOP OFF and everything on it will overheat -- watch the - valve dial on the coolant screen. Boosting one loop starves the - others (the coolant supply is shared). + 1/2/3/Q/W/E are the six coolant valves and 4 (hold) is the flush. + CAREFUL with the valves: the detents go 1 - 5 - 50 (max) - + 0 (CLOSED!) - back to 1. One press past max SHUTS THE LOOP OFF and + everything on it will overheat -- watch the valve dial on the coolant + screen. Boosting one loop starves the others (the supply is shared). A weapon gone quiet with ammo left has probably JAMMED (heat makes ballistic weapons jam -- authentic!). Check its panel's ENG DATA page for the jam lamp (a cocked round with warning bolts). The pod's fix