288 lines
21 KiB
Markdown
288 lines
21 KiB
Markdown
# GLASS_COCKPIT — running ledger (desktop developer layer)
|
||
|
||
Detailed running log for the `glass-cockpit` branch work: PadRIO, on-screen panel/plasma,
|
||
miniconsole, Steam transport/lobby. Curated digest: `context/glass-cockpit.md` (read that
|
||
first); this file carries the step-by-step detail, evidence, and verification transcripts.
|
||
|
||
---
|
||
|
||
## 2026-07-17 — Step 1: branch + compile gates + scaffolding
|
||
|
||
- Branch `glass-cockpit` created from master @ `e2c21c4`.
|
||
- `CMakeLists.txt`: `option(BT_GLASS OFF)` + `option(BT_STEAM OFF)`; `BT_STEAM` without
|
||
`BT_GLASS` is a configure-time FATAL_ERROR; gates append to `BT_DEFS` (flows to all three
|
||
targets); `STATUS` line prints gate state at configure. Gated `target_sources` blocks will be
|
||
added per-TU as they land (CMake would reject nonexistent source files now).
|
||
- `.gitignore`: `build-pod/`, `build-steam/`, `content/bindings.txt`, `content/frontend.egg`,
|
||
`content/steam_appid.txt`.
|
||
- Verification (this step): defaults configure prints `BT_GLASS=OFF BT_STEAM=OFF` and builds
|
||
(purity build); `-DBT_GLASS=ON` and ON/ON configures print correct gate state; the
|
||
BT_STEAM-without-BT_GLASS negative test FATAL_ERRORs. Full 3-config BUILD matrix becomes
|
||
meaningful from step 2 (first gated code) and is re-run there.
|
||
|
||
## 2026-07-17 — Step 2a: the .CTL positional-attribute off-by-one — CONFIRMED and FIXED (ungated)
|
||
|
||
**The bug [T2, live-verified]:** the streamed `.CTL` "L4" mapping resource carries the 1995
|
||
binary's positional attribute ids (stick=3, throttle=4, ...), resolved at install time by
|
||
`Simulation::GetAttributePointer(id)` → `AttributeIndexSet::Find(id)` = `attributeIndex[id-1]`
|
||
(positional). `MechControlsMapper` chained its enum on `Subsystem::NextAttributeID == 2`, but
|
||
the binary's chain reaches 3 (one base attribute we don't publish) — so EVERY streamed mapper
|
||
record landed one member late.
|
||
|
||
**Evidence (new `BT_CTRLMAP_LOG=1` diagnostic in `LBE4ControlsManager::CreateStreamedMappings`,
|
||
`engine/MUNGA_L4/L4CTRL.cpp` — permanent, env-gated, default off).** Before the fix
|
||
(`build-pod` Debug, `-egg DEV.EGG`, dev platform):
|
||
```
|
||
rec 0 subsys 0 group 1(Joy) elem 0 attrID 3 -> +0xe4 (= throttlePosition: WRONG, stick intended)
|
||
rec 1 subsys 0 group 0(Scalar) elem 0 attrID 4 -> +0xe8 (= pedalsPosition: WRONG, throttle intended)
|
||
rec 2 subsys 0 group 3(Button) elem 63 attrID 6 -> +0xf0 (= speedDemand: WRONG, reverse intended)
|
||
rec 4-6 attrID 10/11/12 -> lookRight/lookBehind/lookDown (one late; LookLeft/Right/Behind intended)
|
||
```
|
||
Spacing attr3→attr4 was 4 bytes (Scalar) where stick→throttle must be 8 (ControlsJoystick).
|
||
The weapons chain (attrID 19 → +0x31c TriggerState) was already correct — mechweap was
|
||
pad-aligned in task #16 (gotcha #11). Torso (subsys 17) also aligned (MechSubsystem publishes
|
||
binary id 2). ONLY the mapper chain (subsys 0) was off. On the dev box the keyboard INPUT
|
||
BRIDGE (writes the mapper members directly, after the engine push) masked it; on a REAL POD the
|
||
serial RIO throttle scalar would have driven `pedalsPosition` and the stick x/y would have
|
||
driven throttle+pedals — the Phase-8 landmine prior art predicted.
|
||
|
||
**The fix (ungated, pod-correctness — user-approved 2026-07-17):** `mechmppr.hpp` pins the enum
|
||
to the binary numbering (`MechControlsMapperPadFirstAttributeID = 2`, stick=3 ... PilotArray=
|
||
0x16); `mechmppr.cpp` pads id 2 with a valid never-bound entry (the mech.cpp attrPad idiom) and
|
||
locks the base + pinned ids with `static_assert`s. `L4MechControlsMapper::TargetRangeExponent`
|
||
(chained) moves 0x16→0x17, matching the binary's own arithmetic; it is bound by name (audio
|
||
zoom-blip), so no consumer shifts.
|
||
|
||
**After the fix:** `attrID 3 -> +0xdc` (stick), `attrID 4 -> +0xe4` (throttle, 8-byte spacing
|
||
✓), `attrID 6 -> +0xec` (reverse), `10/11/12 -> +0xfc/+0x100/+0x104` (the look trio); torso +
|
||
weapons unchanged. Regression: headless forced-walk run (`BT_FORCE_THROTTLE=1`) drives normally
|
||
— `[mppr] thr=1 -> speedDemand=61.501`, gait cycles, position advances, 31/31 subsystems
|
||
simulated, no faults.
|
||
|
||
## 2026-07-17 — Steps 2b-2e: PadRIO, stand-downs, displays, preset — DONE + verified
|
||
|
||
**2b (RIOBase + PadRIO, commit ac57a47):** `L4RIO.h` splits abstract `RIOBase` (enums, the five
|
||
analog Scalars, pure `GetNextEvent`/`SetLamp`, no-op serial ops, NEW `IsOperational()`) out of
|
||
serial `RIO` (`: PCSerialPacket, RIOBase` — ctor assigns as before, zero behavioral delta);
|
||
`L4CTRL.h` `rioPointer` retyped `RIOBase*`; gated `L4CONTROLS=PAD` factory arm. NEW gated TUs
|
||
`L4PADRIO.*` (XInput+keyboard → the surface; 3s hot-plug; focus-guarded keys; per-poll
|
||
AnalogEvent heartbeat time-gated so the manager's drain loop terminates; `lampState[]`;
|
||
static `SetScreenButton` — button addresses AND the keypad space 0x50-0x6F → KeyEvents) and
|
||
`L4PADBINDINGS.*` (`content\bindings.txt`, default written on first run; deflect/slew/set axis
|
||
model; addresses validated vs ButtonCount).
|
||
|
||
**2c (stand-downs, commit 9f35a80):** engine query `BTRIODevicePresent()` (ungated —
|
||
pod-correct); both dev bridges (`mech4.cpp` attr writes, `mechmppr.cpp` BT_KEY_BRIDGE) gate
|
||
their WRITES: unset=auto / "0"=off / else on; forced harness always rides. **Definitive live
|
||
test:** OS-injected LSHIFT hold slewed PadRIO throttle 0→0.33→1.0 with `pre==thr` every frame —
|
||
the value arrives via the ENGINE push through the streamed `.CTL` binding (bridge stood down),
|
||
`speedDemand=61.501` from authentic InterpretControls.
|
||
|
||
**2d/2e (displays + preset, commits db9ac94 + 418acf0):** the on-screen panel follows **vRIO**
|
||
(`C:\VWE\vrio` — `CockpitLayout.cs`/`PanelCanvas.cs`, per Cyd): five 4x2 MFD clusters
|
||
(descending addresses), Throttle/Secondary/Screen/Joystick 1x8 columns, two 4x4 hex keypads
|
||
(0x50 internal→pilot unit, 0x60 external→operator unit), physical names, red/yellow/blue
|
||
coloration, 500/250/125ms flash, right-click latch — 104 controls. `PlasmaWindow :
|
||
Video8BitBuffered` renders the 128x32 plasma via the SAME gauge-renderer path as serial
|
||
(buffer is TOP-DOWN — the flip rendered it upside down, user-reported + fixed). MFD surfaces =
|
||
the EXISTING dev-gauge modes (no new code, no L4VB16 exposure). `-platform glass` preset +
|
||
run.cmd token. **Button-trap guard (e2c21c4 pattern):** the authentic base
|
||
`ConfigureMappableMessageHandler` FAIL trap is `abort()` under DEBUGOFF — any aux/zoom button
|
||
without its reconstructed L4 override KILLED the game on press (panel makes all reachable).
|
||
Default now log+ignore; `BT_BUTTON_TRAP=1` restores the hard trap. Verified: synthetic panel
|
||
click → 2 `[FAIL]` (press+release through panel→PadRIO→ProcessRIOEvent→streamed mapping), game
|
||
survives. NOTE: each `[FAIL]` marks a missing L4 override — reconstruction backlog, see
|
||
[[open-questions]].
|
||
|
||
**Step-2 verification matrix (all passed 2026-07-17):**
|
||
1. Purity: defaults `build-pod/` compiles (known mech3 /FORCE externals only); seam audit —
|
||
`BT_GLASS`/`BT_STEAM` mentions ONLY in CMakeLists, btl4main.cpp preset region, L4CTRL.cpp
|
||
(include+PAD arm), L4GREND.cpp (include+SCREEN branch), gated TUs, run.cmd docs.
|
||
2. Pod solo forced-walk clean (§2a).
|
||
3. **2-node loopback MP on the pod build:** A `-egg MP.EGG -net 1501` + B `-net 1601` +
|
||
`btconsole.py` relay — both nodes launch into the running mission (77/76 ticks, mechs at
|
||
their drop zones, gait/target loops live).
|
||
4. Glass build: PadRIO drives through the authentic mapper path; panel click path live; plasma
|
||
window; all boot lines present.
|
||
Deferred to the user (visual-only): panel/plasma appearance vs vRIO on screen, XInput stick
|
||
feel, `L4PADFLIP` polarity.
|
||
|
||
## 2026-07-17 — Step 3: the miniconsole — DONE + verified (commit c4ca87b)
|
||
|
||
**Architecture: the console stays a wire peer.** `game/glass/btl4fe.*` (GDI catalog menu + the
|
||
console-shape egg writer) and `btl4console.*` (the LocalConsole marshal: a worker-thread console
|
||
CLIENT speaking the `tools/btconsole.py` protocol verbatim — 1040-byte chunked
|
||
`ReceiveEggFileMessage`, 20s settle, `RunMission`×2, stay connected, own the clock,
|
||
`StopMission`(id 6)@expiry; logs `content\marshal.log`). The engine runs the 100% stock console
|
||
ladder — ZERO engine hooks; the planned `L4APP.H` setters proved unnecessary (launches pass real
|
||
argv on relaunch). WinMain: one gated block — zero-mission-arg glass launch → menu → relaunch
|
||
self with mission argv (`BT_FE_EGG/PODS/SECS` arm the marshal; `BT_FE_LOOP` returns exits to the
|
||
menu; menu relaunches CLEAR the handoff — the leak re-armed a marshal in cycle test 1).
|
||
|
||
**Verified (synthetic menu drives, all autonomous):**
|
||
- Golden egg: `frontend.egg` section sequence + line offsets IDENTICAL to `MP.EGG`; ordinal
|
||
pages verbatim; GDI name-glyph pages in MP.EGG framing (32/8 rows, 16 bytes/line).
|
||
- Solo cycle: menu → egg → relaunch → marshal → stock ladder → mission RUNS (58+ ticks) → 60s
|
||
clock → stop → menu returns with clean env.
|
||
- **HOST LAN 2-node:** peer started manually (`-net 1601`); menu-hosted launch → marshal feeds
|
||
BOTH pods (2-pilot egg, 10 chunks each) → both in-mission (65/18 ticks) → stop both → host
|
||
returns to the menu, peer idles at console-wait.
|
||
|
||
## 2026-07-17 — Step 4 pre: Steamworks SDK 1.64 vendored (commit 23c0019)
|
||
|
||
Official Valve zip (provided by Cyd at the repo root), extracted to
|
||
`extern/steamworks_sdk_164/` and trimmed to `public/` + `redistributable_bin/` + Readme
|
||
(12.5 MB); zip removed. Consumed only under `-DBT_STEAM=ON`.
|
||
|
||
## 2026-07-17/18 — Step 4: the Steam wire — CODE COMPLETE (commits e79e8fa, 48ede2f, f703bb1)
|
||
|
||
**4a (e79e8fa) — the wire seam:** file-local `BTNetSend/Recv/Accept/Close` wrappers around the
|
||
9 raw Winsock sites in `L4NET.CPP`; OFF builds are pure code motion. Regression: 2-node loopback
|
||
MP through the seam — mesh forms, full 31/31 mission on both nodes.
|
||
|
||
**4b (48ede2f) — the transport:** gated TU `L4STEAMNET` — pseudo-SOCKETs (0x5EA0xxxx) behind the
|
||
seam; the engine's TCP byte stream rides reliable-NoNagle Steam messages re-assembled into
|
||
per-connection rings (recv semantics preserved: empty→WSAEWOULDBLOCK, closed→0); seam
|
||
completions: `CheckSocket` (peer = token address), `OpenConnection` TCP_OPEN delegate,
|
||
`GetMyAddress` self-token. Install on `BT_STEAM_NET=1`; graceful degrade to Winsock at every
|
||
step. BOTH pumps needed (`SteamAPI_RunCallbacks` + sockets `RunCallbacks`).
|
||
|
||
**4c (f703bb1) — the lobby + THE FAKEIP LESSON [T2]:** prior art assumed FakeIP survives the
|
||
per-mission process relaunch — DISPROVEN live (menu process got 169.254.124.110, the mission
|
||
process got 169.254.54.234; the pod timed out connecting to its own stale address). Redesign:
|
||
roster addresses are opaque ipv4-shaped TOKENS (`169.254.77.N`, ports 1501 console / 1502 game)
|
||
minted by the host at GO and mapped to Steam IDENTITIES; connections ride
|
||
`ConnectP2P(identity, channel)` (console=0, game=1); the map hands off via env
|
||
(`BT_FE_MYFAKE`/`BT_FE_STEAMMAP`). `btl4lobby`: ISteamMatchmaking room (`btl4=1` filter),
|
||
pilots publish name/mech/color, host GO mints tokens + writes `btl4map` + `btl4go`.
|
||
|
||
**Verified single-machine (ON/ON, live Steam client):** menu → HOST STEAM LOBBY → room → GO →
|
||
map `169.254.77.1=<steamID64>` → egg roster carries the token → mission process
|
||
`[steamnet] up ... 1 roster token(s) incl. self` → pod self-matches → stock console ladder →
|
||
mission RUNS (46 ticks). 3-config build matrix green throughout. **Remaining (user hardware):**
|
||
the live 2-account cross-machine session — procedure in `docs/STEAM_TEST.md`.
|
||
|
||
## 2026-07-20 — Glass input-coverage audit + keyboard reconciliation
|
||
|
||
**Trigger:** making BT_GLASS the permanent player experience — familiar desktop keys dead, "most
|
||
panel buttons do nothing". Full audit of every input surface (bindings.txt keys, the 72-button
|
||
panel, the streamed .CTL EventMapping records, the typed 1995 channel), then the fix set.
|
||
|
||
### Finding 1 — THE panel-dead-buttons root cause: MechRIOMapper message ids shifted [T1→T2 fixed]
|
||
`MechRIOMapper`'s enum chained `Aux1QuadMessageID = L4MechControlsMapper::NextMessageID` (=0x19),
|
||
registering all 18 RIO handlers at ids 0x19-0x2a. The binary RIO table @0051dd30 RE-REGISTERS the
|
||
base aux/zoom ids **3..0x13** with the override handlers (Hotbox = 0x1a @0051de98) — that
|
||
re-registration over the base FAIL-trap ids is the whole point of the derived table. Streamed
|
||
`.CTL` events carry the binary ids, so every MFD-bank/zoom press found only the base
|
||
`ConfigureMappableMessageHandler` → `[FAIL]` (26 of 72 panel buttons dead; on a real pod with the
|
||
hard trap, an abort()). Hotbox worked by accident (sender + entry both used the same wrong 0x2a).
|
||
Fixed: ids pinned to the binary numbering + static_assert locks (`btl4mppr.hpp`). Verified live:
|
||
panel 0x0F/0x08/0x27/0x20 → `[mode] preset` lines, 0x10/0x11 zoom no longer FAIL. (Residual
|
||
fidelity gap: the binary RIO table also carries its OWN Keypress id 0x19 → @004d2514,
|
||
unreconstructed; we still register the shared L4 Keypress 0x17 — works, logged in the backlog.)
|
||
|
||
### Finding 2 — the always-active msg-4 records IDENTIFIED [T1] (closes the #9 open question)
|
||
Binary message tables decoded from section_dump (16-byte {id,name,fn,0} entries): per-receiver-
|
||
class id spaces. Roster (ARENA1 MadCat): subs 3=Reservoir, 4-9=Condenser1-6, 10-13=GeneratorA-D.
|
||
So: **0x2C = the COOLANT FLUSH button** (Reservoir InjectCoolant, WORKS), **0x2F/0x2E/0x2D/0x2B/
|
||
0x2A/0x29 = per-condenser VALVE buttons** (MoveValve, WORK), **0x1A-0x1D = Generator A-D ON/OFF**
|
||
(`ToggleGeneratorOnOff` id 4, table @0050fb90 fn @004b1ed0 — DEAD, unreconstructed). Also new:
|
||
0x13 → Mech **DuckRequest** (0x1a @0049fa00 — the manual's CROUCH button!), 0x28 → Mech
|
||
**BalanceCoolant** (0x16 @0049f728), 0x12 → ThermalSight toggle (id 3), 0x14 → Searchlight +
|
||
Searchlight2 **ToggleLamp** (id 3 @004b860c — body reconstructed but `Searchlight::
|
||
MessageHandlers` is default-constructed EMPTY, so it never fires: the quick win). Weapon
|
||
Eng-page extras: msg 0x3 = **ToggleCooling** (HeatableSubsystem @0050e41c fn @004ad6f8, unwired),
|
||
msg 0xb = **ToggleSeekVoltage** (energy @004ba478) / **EjectAmmo** (ammo weapons @004bb9b8),
|
||
Myomers msg 9 = ToggleSeekVoltage (@004b8a48; body exists, unwired). Unhandled messages are
|
||
SILENT (Receiver::Receive ignores an unfound id) — the dead-button census cannot come from
|
||
[FAIL] logs alone; it comes from the BT_CTRLMAP_LOG record dump × the handler tables.
|
||
|
||
### Finding 3 — glass keyboard: stand-down + double dispatch [T2]
|
||
ALL btinput actions (drive keys, M/N/J/K/L/H/C/V/B/G/F5-F9) stand down when PadRIO owns the path
|
||
— nothing on the game side polls keys directly (BTInputPoll is the only GetAsyncKeyState
|
||
consumer). Meanwhile the typed 1995 channel stays LIVE (glass preset = `PAD,KEYBOARD`) with NO
|
||
suppression — so Cyd's old bindings double-dispatched: W (keypad row) also typed 'w' = pilot
|
||
select 0; C (fire middle) also typed 'c' = MFD3 Eng3; NUMPAD key-UPS alias to letter hotkeys
|
||
(VK_NUMPAD2=0x62='b' = MFD3 Quad, VK_F5=0x74='t' = pilot select 3). This is the historic
|
||
pre-btinput double-dispatch, back on the glass side.
|
||
|
||
### The fix set (landed)
|
||
1. `btl4mppr.hpp` — RIO id pinning (ungated, pod-correctness; the step-2a idiom).
|
||
2. `L4PADRIO.*` — typed-channel suppression tables built from the loaded bindings (+hardcoded
|
||
keys), `PadRIO::SuppressKey` consumed by a `#ifdef BT_GLASS` arm next to the btinput hook in
|
||
`L4CTRL.cpp:1506` block; V joins backtick on the view-toggle edge; J/K/L fire
|
||
`gBTPresetCycle[3]` (the same seam the dev poll feeds — no binary analog exists for a "cycle"
|
||
button; the body is the authentic SetPresetMode).
|
||
3. `L4PADBINDINGS.cpp` + `content\bindings.txt` — the MERGED default map (user decision:
|
||
keyboard = the ~20 core gameplay actions on the CONTROLS.MAP keys; the PANEL covers all 72
|
||
pod buttons by click/latch). W/S throttle, A/D pedals, Q/E twist, R/F elevation, X all-stop,
|
||
1-4/Space/Ctrl fire + LALT reverse + B look-behind, M=0x18, N=0x15, H=0x2C (flush hold),
|
||
C=0x2F (Condenser1 valve), G=0x0E (weapon-1 configure, Mfd1-Quad-gated), F5-F9=Mfd2 bank
|
||
0x27-0x24+0x22 (page-gated gen A-D/mode), numpad flight cluster kept. DISPLACED from Cyd's
|
||
map (each reachable on the panel or by editing bindings.txt): number row→secondary panel,
|
||
QWERTY row→pilot keypad (dropped), arrows→hat looks (arrows now drive), V/C/B→fire
|
||
0x47/0x46/0x45, LCTRL→throttle-down. XInput pad section untouched.
|
||
NOTE (control modes, authentic): in BAS mode the pod turns with the STICK (Q/E here) and the
|
||
pedals are inactive; A/D turn in MID/ADV — exactly the manual's behavior, unlike the desktop
|
||
bridge which re-routes A/D per mode.
|
||
4. Un-touched: CONTROLS.MAP, btinput defaults, pod serial path. `bindings.txt` is read only by
|
||
`PadBindingProfile` inside the gated PadRIO TU — the pod build never opens it.
|
||
|
||
### Verification (2026-07-20, build-glass2, ARENA1 solo, all logs in-session)
|
||
- Panel: 0x0F→preset(0,1), 0x08→(0,0), 0x27→(1,1), 0x20→(1,0), zoom no-FAIL; 0x15 display
|
||
1→2→0; 0x2C hold → `[flush] Reservoir level 6→0`; dead-class buttons (0x13/0x1A/0x12/0x14)
|
||
silent as predicted. ZERO [FAIL] lines in the whole session (was 2 per bank press).
|
||
- Keyboard: W hold → thr 0→1, speedDemand 61.501, gait advances; Q → turnDemand 0.94 (BAS);
|
||
M → `control mode -> 1`; A hold → turnDemand 1.0 (MID); Space → `[emitter] FIRED`; N →
|
||
`display notify 1`; J/K/L → presets (0,1)/(1,1)/(2,1); H → reservoir drain; C → condenser#1
|
||
valveState 1→5. BT_SHOT frame confirms visually: MID lit on the control-mode column, CRITICAL
|
||
DAMAGE schematic up, MFDs on Eng pages, heading moved. V not re-injected (user took
|
||
foreground mid-run) — code-identical to the verified backtick edge [T3].
|
||
- Suppression: typed 'w' swallowed (no [keych]), typed 't' flows ([keych] 0x74), WM_KEYUP
|
||
VK_F5 swallowed (the 't'-alias hazard).
|
||
- Un-regression: build-pod (gates OFF) compiles 0 errors; forced-walk run drives
|
||
(speedDemand=61.501, 32 subsystems, streamed ids 3→+0xdc / 4→+0xe4 unchanged).
|
||
|
||
## 2026-07-18 — Merge origin/master (commit f889e24): btinput meets PadRIO
|
||
|
||
Master's 33-commit run landed (D1 relay/operator-console line, CONTROLS.MAP+XInput binding
|
||
engine `btinput.cpp`, camera seats, torso pitch, sign fixes, the 1995 manual, version stamping).
|
||
**The reconciliation:** btinput (ungated, dev/pod desktops) joined the stand-down convention —
|
||
`BTInputPoll` yields and `BTInputSuppressKey` claims nothing when an operational cockpit device
|
||
(serial RIO / PadRIO) owns the input path (`BTRIODevicePresent`; `BT_KEY_BRIDGE` override;
|
||
forced harness exempt). **One input system per mode:** `CONTROLS.MAP`/btinput on dev+pod
|
||
desktops, `bindings.txt`/PadRIO on glass. The D1 relay keeps its own raw sockets by design
|
||
(relay and Steam are alternative wires; the BTNet seam covers the arcade mesh both need).
|
||
Verified: 3-config build, glass stand-down live, pod forced-walk with btinput active, 2-node
|
||
loopback MP 31/31.
|
||
|
||
## 2026-07-19 — Mission-control options: the AUTHORITATIVE catalog (TeslaSuite console.ini)
|
||
|
||
Source: `C:\VWE\TeslaSuite\410console\4_10-console-extracted\Console.ini`, the Mac 4.10 operator
|
||
console's `BT::` adventure tree (the `tag=` values are the egg field values; display names are the
|
||
console's). Cross-checked vs `410console/battletech-port/BATTLETECH-PORT-SPEC.md` + `reference/
|
||
cavern.egg`. This is every option the original console exposed for a BattleTech mission.
|
||
|
||
**Mission-level** — `[mission]`: `adventure=BattleTech` (fixed), `temperature=27` (fixed),
|
||
`scenario=freeforall` (the tag is always freeforall; the RESPAWN choice is the ROLE):
|
||
- map (8): cavern, grass, rav, polar3, polar4, arena1, arena2, dbase
|
||
- time (4): morning, day, evening, night ← was day/night/morning/**dusk** (wrong: evening)
|
||
- weather (3): clear, fog (light), soup (heavy)
|
||
- role (2): Default (`model=dfltrole`, respawn) / NoReturn (`model=noreturn`, one life)
|
||
- length: seconds
|
||
|
||
**Per-pilot** — participant block:
|
||
- experience (4 [T1 game decode]): novice, standard, veteran, expert ← was hardcoded `expert`
|
||
- vehicle (18, friendly→tag): Black Hawk=blkhawk, Loki=loki, Nova=bhk1, Mad Cat=madcat, Thor=thor,
|
||
Owens=owens, Kotori=own1, Summoner=thr1, Hellbringer=lok1, Timber Wolf=mad1, Avatar=avatar,
|
||
Satyr=ava1, Sunder=sunder, Sunder V1=snd1, Vulture=vulture, Mad Dog=vul1, Mischief=lok2,
|
||
Zanin Neko=mad2 (the 18 ModelList names; matches the 2026-07-18 vehicle sweep)
|
||
- color/camo (7, display→tag): White=White, Black=Black, Brown=Brown, Red=**Crimson**, Green=Green,
|
||
Gray=**Grey**, Tan=Tan ← was White/Black/Crimson only
|
||
- badge/emblem (7, the `badge=` field): VGL, Davion, Kurita, Liao, Marik, None, Steiner ← was `VGL`
|
||
- patch/badge-color (8, the `patch=` field): Yellow, Blue, Grey, Green, Violet, Red, White, Black
|
||
← was `Yellow`
|
||
- dropzone (5, the `dropzone=` field): one, two, three, four, five ← was `one`
|
||
- advancedDamage (0/1): the advanced damage model toggle ← was hardcoded `1`
|
||
- vehicleValue: 1000 (const), loadzones=1 (const), bitmapindex (per-pilot ordinal)
|