# ============================================================================ # pack-dist.ps1 - assemble a runnable BattleTech 4.12 package into dist\ # ============================================================================ # # Collects everything the game needs at run time: # - build-steam\Release\btl4.exe (Steam build; Release so it runs on a # machine WITHOUT Visual Studio -- the Debug CRT is not redistributable) # - steam_api.dll + OpenAL32.dll beside the exe # - game data from content\ (AUDIO, GAUGE, VIDEO, BTL4.RES, BTDPL.INI, # the VREND manifests, bindings.txt, a few eggs) -- NOT the DOS-era # arcade launch scripts / 16-bit stubs # - steam_appid.txt = 480 (Spacewar) so Steam init works for TESTING; a # real Steam release replaces this with the title's AppID # - tools\btconsole.py for the classic (non-Steam) console-feed MP path # - a self-documenting environ.ini + start.bat + README # # Usage: powershell -ExecutionPolicy Bypass -File pack-dist.ps1 [-Zip] # param( [switch]$Zip ) $ErrorActionPreference = 'Stop' $root = Split-Path -Parent $MyInvocation.MyCommand.Path $dist = Join-Path $root 'dist' $content = Join-Path $root 'content' $relDir = Join-Path $root 'build-steam\Release' $exe = Join-Path $relDir 'btl4.exe' if (-not (Test-Path $exe)) { throw "build-steam\Release\btl4.exe not found - build the Steam Release first:`n" + " cmake -S . -B build-steam -G `"Visual Studio 17 2022`" -A Win32 -DBT412_STEAM=ON`n" + " cmake --build build-steam --config Release --target btl4" } # Refuse to touch a dist the game is currently running from. $running = Get-Process btl4 -ErrorAction SilentlyContinue | Where-Object { $_.Path -like "$dist\*" } if ($running) { throw "btl4.exe is running from $dist (PID $($running.Id)) - close the game first." } Write-Host "Packing into $dist" if (Test-Path $dist) { Remove-Item -Recurse -Force $dist } New-Item -ItemType Directory -Force $dist | Out-Null New-Item -ItemType Directory -Force "$dist\tools" | Out-Null # --- game binary + runtime DLLs -------------------------------------------- Copy-Item $exe $dist $pdb = Join-Path $relDir 'btl4.pdb' if (Test-Path $pdb) { Copy-Item $pdb $dist } # steam_api.dll + OpenAL32.dll are staged beside the exe by the build. foreach ($dll in 'steam_api.dll', 'OpenAL32.dll') { Copy-Item (Join-Path $relDir $dll) $dist } # --- game data ------------------------------------------------------------- foreach ($dir in 'AUDIO', 'GAUGE', 'VIDEO') { Write-Host " copying $dir..." Copy-Item -Recurse (Join-Path $content $dir) $dist } # Required loose files: resources, renderer/DPL config, geometry+texture # manifests (VREND.MNG is loaded by bgfload/L4VIDEO), the input bindings, and # a handful of eggs (DEV = the -egg dev shortcut, MP = the console-feed target). $files = 'BTL4.RES', 'BTDPL.INI', 'bindings.txt', 'VREND.MNG', 'VRENDMON.BTL', 'VRNOSTEX.MNG', 'DEV.EGG', 'MP.EGG', 'MP1.EGG' foreach ($file in $files) { $src = Join-Path $content $file if (Test-Path $src) { Copy-Item $src $dist } else { Write-Warning "content\$file missing - skipped" } } # --- OpenAL fallback installer + the console feeder ------------------------ $oalinst = Join-Path $root '..\RP412\assets\RP411\oalinst.exe' if (Test-Path $oalinst) { Copy-Item $oalinst $dist } else { Write-Warning "oalinst.exe not found (OpenAL fallback installer) - OpenAL32.dll still ships beside the exe" } Copy-Item (Join-Path $root 'tools\btconsole.py') "$dist\tools" # --- steam_appid.txt (TEST ONLY) ------------------------------------------- # 480 = Valve's Spacewar test app. Steamworks (SteamAPI_Init, FakeIP, lobbies) # works against it so multiplayer can be tested before the title has a real # AppID. A shipping Steam build replaces this with the real AppID (and Steam # supplies it, so the file is removed). Set-Content -Path "$dist\steam_appid.txt" -Encoding ascii -NoNewline -Value "480" # --- desktop configuration ------------------------------------------------- Set-Content -Path "$dist\environ.ini" -Encoding ascii -Value @" # ============================================================================ # environ.ini - BattleTech 4.12 configuration # ============================================================================ # One KEY=VALUE per line, read at game start. Lines starting with # or ; # are comments; anything without an = is ignored. Delete a line (or comment # it out) to fall back to the built-in default. # # Input bindings live in bindings.txt beside the exe. # ---- Core (the shipped desktop configuration) ------------------------------ # Control stack: tokens separated by ; or , processed left to right. # PAD the virtual RIO (XInput controller + keyboard, rebindable) # KEYBOARD the engine keyboard handler # RIO real serial cockpit hardware (pod only) L4CONTROLS=PAD;KEYBOARD # Renderer bring-up argument (presence checked; any non-empty value works). DPLARG=1 # DPL (renderer/scene) config file, searched beside the exe. L4DPLCFG=BTDPL.INI # Gauge/MFD canvas (a page of GAUGE\L4GAUGE.INI). Needed for the cockpit. L4GAUGE=640x480x16 # Single-window cockpit: the 3D viewscreen framed by the six MFD surfaces # (green) with their on-screen RIO button banks, on a 1920x1080 canvas # auto-scaled to your monitor. 0/unset = the old 800x600 dev view. L4MFDSPLIT=1 # Plasma glass rendered in-window (rank/ordinal readout). Unset = none. L4PLASMA=SCREEN # Simulation/render frame rate (fps). Desktop default 60; the pods ran 30. TARGETFPS=60 # 1 = Steam networking (the lobby + FakeIP mesh). Needs the Steam client # running and steam_appid.txt beside the exe; without them the game logs the # reason and falls back to plain TCP. 0 = TCP only (use this for the classic # btconsole.py console-feed multiplayer path -- see the README). BT412STEAM=1 # ---- Optional -------------------------------------------------------------- # Mission-length override, integer seconds (short test missions). The menu's # LENGTH choice sets this; uncomment to force it. #BT_MISSION_SECONDS=120 # Anti-aliasing sample count passed to Direct3D 9 (0 = off, else 2..16). #MULTISAMPLE=0 # Particle budget (default 8192). #MAXPARTICLES=8192 # Fixed random seed for repeatable runs (any unsigned integer). #RANDOM=12345 # ---- Classic LAN / console-feed multiplayer (BT412STEAM=0) ----------------- # The host-as-console egg feed for the STEAM lobby is not finished yet (see # the README). The proven multiplayer path is the external console emulator # feeding -net pods over TCP -- run tools\btconsole.py (Python 3). Example: # Machine A: btl4.exe -egg MP.EGG -net 1501 # Machine B: btl4.exe -egg MP.EGG -net 1601 # Feeder: python tools\btconsole.py MP.EGG A_ip:1501 B_ip:1601 # Set BT412STEAM=0 above for this path. "@ Set-Content -Path "$dist\start.bat" -Encoding ascii -Value @" @echo off rem BattleTech 4.12 - desktop build. No cockpit hardware needed. rem Boots into the in-game mission setup menu (front end). With Steam rem running (BT412STEAM=1 in environ.ini) the menu shows HOST / JOIN. rem Add "-egg DEV.EGG" to skip the menu and run the canned solo mission. cd /d "%~dp0" start btl4.exe "@ Set-Content -Path "$dist\README.txt" -Encoding ascii -Value @" BattleTech 4.12 (desktop / Steam build) ======================================== Run start.bat. No cockpit hardware needed. If there is no sound, run oalinst.exe once (installs the OpenAL runtime). You boot into the in-game MISSION SETUP MENU (green-on-black): pick the map, mech, color, time, weather, and mission length, type a pilot name, and press LAUNCH. The single-window cockpit comes up -- the 3D viewscreen framed by six green MFD surfaces with the pod's RIO button banks (click them with the mouse; they light as the game commands their lamps). At the chosen length the mission stops and a MISSION COMPLETE scoreboard shows, then it returns to the menu. Controls (XInput controller and/or keyboard) - rebindable in bindings.txt: Left stick / WASD drive (throttle holds; A/D steer) X all stop Space / A fire mouse click the on-screen cockpit buttons (see bindings.txt for the full default layout) MULTIPLAYER - please read ------------------------- This build is for testing STEAM multiplayer end to end. Steam lobby + networked mission. With Steam running and BT412STEAM=1, the menu shows HOST STEAM MISSION and JOIN STEAM MISSION. HOST creates a room; JOIN finds and enters one. Everyone in the room sees the member list (name, mech, color) and exchanges their FakeIP + loadout. The host presses LAUNCH MISSION: it then acts as the in-process console -- it feeds every member the mission over the wire, holds the whole mesh until all are staged, launches them together, and stops the mission at the chosen length. The member pods mesh with the host and each other; kills/deaths are collected and the same results screen shows on every machine. -> Test: two (or three) machines, each signed into a DIFFERENT Steam account, all running this build. Confirm they find each other in the room, the launch fires, everyone drops into the SAME mission and can see/fight each other, and results show everywhere. -> The host->member mission feed is NEWLY IMPLEMENTED. The console protocol + launch handshake are loopback-verified here, but the full multi-machine Steam mesh has not been lab-tested. If a member does not drop in, grab btl4.log from each machine (grep [marshal], [frontend], net-tx / net-rx) so it can be diagnosed. CLASSIC MULTIPLAYER (no Steam, proven): the external console emulator feeding -net pods over TCP. Needs Python 3. Set BT412STEAM=0 in environ.ini, then: Machine A: btl4.exe -egg MP.EGG -net 1501 Machine B: btl4.exe -egg MP.EGG -net 1601 Feeder: python tools\btconsole.py MP.EGG :1501 :1601 Drive, fire, cross-pod kills and respawn all replicate on this path. Steam notes (for the lobby test): - steam_appid.txt (480 = Valve's Spacewar test app) ships beside the exe so Steam init works before the title has its own AppID. Keep it for testing. - Use a DIFFERENT Steam account per machine (Steam allows one running game per account). Disable Steam Input for app 480 if the controller misbehaves. - If Steam is not running, the game logs the reason and stays on TCP. Logs: the game writes btl4.log beside the exe (set BT_LOG to rename). Grep it for [frontend], [marshal], [steam], net-tx / net-rx when reporting an issue. Source: https://gitea.mysticmachines.com/VWE/BT412 "@ # --- summary / optional zip ------------------------------------------------ $size = (Get-ChildItem $dist -Recurse | Measure-Object Length -Sum).Sum Write-Host ("dist ready: {0:N1} MB -> $dist" -f ($size / 1MB)) if ($Zip) { $zipPath = Join-Path $root 'BattleTech-4.12.zip' Write-Host "zipping to $zipPath..." if (Test-Path $zipPath) { Remove-Item -Force $zipPath } Compress-Archive -Path "$dist\*" -DestinationPath $zipPath -Force Write-Host "zip ready: $zipPath" }