Files
firestorm/OPTIONS-INI.md
T
f402e5becc Add OPTIONS-INI.md reference
options.ini had no documentation. This documents every section and key, compiled
by reading the actual read sites rather than by describing the shipped file, so
that settings which look active but are not are identified as such.

Covers [graphics options], [sound options], [special commands], [server],
[joystick], [Cameraship Params], [Battle Tech Misc], [RookieMission] and
[battle tech print], plus how the file is loaded, which parts the game writes
back, and the per-role options-game/cam/mr variants.

Notable findings, all verified against source:

- The entire [network options] section is DEAD. None of connectiontype,
  connectionspeed, packetsize, defaultconnection, playericon or teamicon is read
  by any code; the connection type actually used comes from the multiplayer
  connection wizard. These are stock MW4 leftovers.

- Several [Battle Tech Misc] keys have names that do not describe what they do,
  and the real meanings are now recorded: RuleBook sets g_nMechVariant, DawnWar
  sets g_nMechLabOp, BiggieSizeIt sets g_nMechPodNum (the console lobby's larger
  roster flag), and CanYouHearTheFootSteps sets g_nBlackMech.

- The shipped options.ini misspells two keys. It contains secmissionreplay and
  secmissionreport, but the code reads SecsMissionReplay and SecsMissionReport.
  The shipped values are therefore ignored and the compiled defaults apply.

- Three keys are read and then immediately overridden, so editing them does
  nothing: videodriverindex (device forced to 0), huddamagemode and
  hudtargetdamagemode (both forced false). Their GetEntry calls are commented out.

- [special commands] killgame is a self-clearing kill switch: if true at startup
  the game rewrites it to false, saves options.ini and exits immediately.

- maxplayers/maxbots are serialised to clients as 5-bit fields, so 31 is the
  maximum usable value; cross-referenced to RAISING-PLAYER-CAP.md.

Also records why a typo produces no diagnostic: GetEntry returns false and the
compiled default is kept silently. Page and key lookup were confirmed to be
case-insensitive (NotationFile::FindPage lowercases; Page::FindNote uses
_stricmp), so the capitalisation differences between the shipped file and the
code are harmless -- the misspellings above are not.

Co-authored-by: Claude Opus 5 (Anthropic) <noreply@anthropic.com>
Co-authored-by: GitHub Copilot <copilot@github.com>
2026-07-25 08:54:28 -05:00

15 KiB

options.ini reference

Complete reference for options.ini, the runtime configuration file that sits next to MW4.exe.

Compiled 2026-07-25 by reading the actual read sites in the source. Every key below was verified against code; keys that are shipped but not read by any code are called out explicitly rather than silently documented as working.

For command-line switches, run MW4.exe -help (writes mw4-help.txt next to the exe).


How the file is loaded

options.ini is a standard INI file read through the engine's own notation-file reader:

Stuff::NotationFile startup_ini("options.ini", NotationFile::Standard, true);
Stuff::Page* page = startup_ini.FindPage("graphics options");
page->GetEntry("bitdepth", &Environment.bitDepth);

Consequences of this design that matter in practice:

  • Section and key lookup is by name. A misspelled key is not an error ? GetEntry simply returns false and the compiled-in default is kept. There is no warning. This is why several shipped keys silently do nothing (see "Dead settings" below).
  • The file is read at startup, in GetGameOSEnvironment / InitializeGameEngine. Changing it while the game runs has no effect.
  • Parts of it are written back. [server] in particular is re-saved from the in-game host UI, and [special commands] killgame is cleared on use. Hand edits to those sections can be overwritten.
  • A few sections are read via the Win32 profile API (GetPrivateProfileInt / GetPrivateProfileString) instead ? noted per section.
File Purpose
options.ini This document. Main game configuration.
options-game.ini, options-cam.ini, options-mr.ini Per-role variants copied over options.ini by the pod launcher for game pods, cameraships, and mission-review machines. Same format.
options-*-var.ini Site-local variant overlays kept in the dev tree.
c:\ctcl.ini Arcade console configuration (pod IP list, launch command lines, voice macros). Hardcoded path. Not covered here.
banner.txt mw4print bottom-of-sheet banner text. Plain text, first line only.

[graphics options]

Read in MW4Application.cpp (GetGameOSEnvironment) and MWOptions.cpp.

Key Type Shipped Effect
bitdepth int 16 Display colour depth. The pods run 16; on modern Windows the DirectDraw 16-bit path additionally needs the DWM8And16BitMitigation compatibility shim.
antialias bool false Full-screen antialiasing (Environment.AntiAlias).
screenwidth int 800 Horizontal resolution, read by MWOptions.
screenheight int 600 Vertical resolution.

Read but overridden in this build ? editing has no effect:

Key Why
videodriverindex The GetEntry call is commented out and Environment.FullScreenDevice is forced to 0. Use the -tmon command-line switch to assign display devices instead.

Present in the shipped file and consumed by renderer subsystem initialisers (MidLevelRenderer::InitializeClasses, gosFX, ElementRenderer, Compost), which are handed the same notation file: noblend, shadowmode, mipbias, loadradius, compositing, lod, maxlights, hidesky, effectlod, detailtexture, multitexture, lightmaps, culturals, footsteps, fancywater, movietextures, simplelighting, missionmusic, vertexlighting, fontsmall, fontmedium, fontlarge, fontlarge2, fontlarge3.

These are stock MechWarrior 4 renderer/quality settings. They are passed through to the engine libraries rather than read in game code, so their exact clamping lives in those libraries. The shipped values above are the tested pod configuration; change them one at a time.


[sound options]

Key Type Shipped Effect
hardwaremixing bool false Use DirectSound hardware mixing (Environment.soundMixInHardware). The 2016 release build enabled this (true); the current tree ships false.
lowendsound bool false Stock low-quality audio path.
radius float 1.0 3D sound attenuation radius multiplier.

[special commands]

Key Type Shipped Effect
killgame bool false Self-clearing kill switch. If true at startup, the game sets it back to false, saves options.ini, and immediately calls ExitGameOS(). Intended as a remote "do not start" flag for a pod.
autotorsocenter int 2 Torso auto-centring mode (VehicleInterface::perminateTorsoMode). 0 = off, 1 = slow, 2 = fast.

Read but overridden in this build ? editing has no effect:

Key Why
huddamagemode GetEntry commented out; forced to false.
hudtargetdamagemode GetEntry commented out; forced to false.

[server]

Multiplayer host defaults. This section is written back by the host configuration UI ? do not hand-edit it while the game is running.

Verified read: playerlimit (Adept/Application.cpp, both GetEntry and SetEntry).

The remaining keys form the persisted NetMissionParameters set and correspond one-to-one with the in-game host options:

defaultservername, dedicated, visibility, joininprogress, joininprogresscutoff, joininprogresscutofftime, heaton, forcerespawn, splashon, weaponjamon, ammobayfireon, advancemodeon, armormodeon, splashpercentage, unlimitedammo, friendlyfirepercentage, allowzoom, allow3rdperson, allowdeadtochat, reportstats, serverrecycle, recycledelay, playmissionreview, deadmechcantsee, deadmechcantseeotherteam, ruletype, usemapcycle, maxplayers, maxbots, allowdecaltransfer, and the allowed*1 / allowed*2 bitmasks (allowedmech, allowedbeam, allowedmissile, allowedprojectile, allowedsubsystem).

Notes:

  • allowed*1 / allowed*2 are 32-bit hex masks covering items 0?31 and 32?63 respectively. ffffffff = everything permitted.
  • maxplayers and maxbots are serialised to clients as 5-bit fields, so the maximum usable value is 31. Writing 32 truncates to 0. See RAISING-PLAYER-CAP.md.
  • In arcade (CTCL) mode these are overwritten at mission launch by CTCL_DefaultHostSetup, so this section mainly affects standalone hosting.

[joystick]

Read and written by Adept/control_mapping.cpp. Also stores control bindings, which is why the file is saved from the controls UI.

Key Type Shipped Effect
bithrottlecenter float 0.3 Bidirectional throttle centre dead zone.
bithrottlelow float 0.25 Bidirectional throttle low dead zone.
bithrottlehigh float 0.06 Bidirectional throttle high dead zone.
onethrottlecenter float 0.3 One-way throttle centre dead zone.
onethrottlehigh float 0.06 One-way throttle high dead zone.
onewaythrottle bool false Treat the throttle axis as forward-only.

[Cameraship Params]

Read by CamerashipParams::LoadOptions (VehicleInterface.cpp). Controls the automatic spectator camera on cameraship pods. All distances are world units, all times are seconds, all offsets are axis offsets applied to the camera or its look-at point.

Behaviour

Key Type Effect
AllowChatDisplay bool Show chat on the cameraship view.
AllowBOTs bool Allow the camera to follow bots.
DisplayCameraStates bool Overlay the current camera state (debug aid).
DegreesPerSec float Camera orbit rate. Accepted range: strictly between -180 and 180.

Timing

Key Effect
TimeScoringInterval Interval between scoring cut-ins.
TimeScoringDuration How long a scoring cut-in is held.
TimeScoringAtEnd Scoring display duration at mission end.
TimeIdleChange Idle time before the camera picks a new subject.
TimeStandard Duration of the standard shot.
TimeDeathWatching Duration of the death-watch shot.
TimeDeathTransition Transition time into the death shot.
TimeFixedTracking Duration of the fixed-tracking shot.
TimeSideShot Duration of the side shot.
TimeFrontShot Duration of the front shot.
TimeOverShoulder Duration of the over-the-shoulder shot.

Framing

Key Effect
DistGroundLevel, DistGroundLevelShift Ground clearance and its shift.
DistStandard, HeightStandard, HeightStandardLookAt Standard shot distance/height/look-at height.
OffsDeathWatchingX/Y/Z Death-watch camera offsets.
OffsFixedTrackingX/Y/Z Fixed-tracking camera offsets.
DistSideShot, OffsSideShotX, OffsSideShotY, OffsSideShotHeadY Side shot framing.
DistFrontShot, OffsFrontShotHeadY, OffsFrontShotCameraY Front shot framing.
OffsOverShoulderHeroX/Y/Z, OffsOverShoulderEnemyY Over-the-shoulder framing.

[Battle Tech Misc]

Read by CamerashipParams::LoadOptions (VehicleInterface.cpp). Several key names in this section do not describe what they do ? they appear to be deliberately obscured. The mapping below is from the source and is the authoritative meaning.

Key Type Range / clamp Actually sets
SecsMissionReplay int <0 or >=100 ¡æ 60 g_nSecsMissionReplay ? mission replay duration.
SecsMissionReport float <0 or >=30 ¡æ 15 g_fSecsMissionReport ? mission report screen duration.
AutoPowerUpLevel float clamped to 0.0?1.0 g_fAutoPowerUpLevel ? auto power-up threshold.
NeedFlushLevel float clamped to 0.0?1.0 g_fNeedFlushLevel ? heat level at which flush is advised.
TimeMsgSender float clamped to 0.1?5.0 g_fTimeMsgSender ? how long a message sender name is shown.
TimeList_Index int <0 ¡æ 0, >=20 ¡æ 3 g_nTimeList_Index ? selected entry in the lobby time-limit dropdown.
TimeList_Value int <0 or >=100 ¡æ 7 g_nTimeList_Value ? lobby time limit in minutes.
RuleBook int 0 or 1 ?? g_nMechVariant ? mech variant feature flag. Nothing to do with a rule book.
DawnWar int 0 or 1 ?? g_nMechLabOp ? mechlab operation flag.
BiggieSizeIt int 0 or 1 ?? g_nMechPodNum ? mech pod count flag, used by the console lobby to enable the larger roster (USE_O_MORE_PODS).
CanYouHearTheFootSteps int 0 or 1 ?? g_nBlackMech ? black mech flag.

?? The shipped file misspells two of these

The shipped options.ini contains:

secmissionreplay=30.0
secmissionreport=15.0

but the code reads SecsMissionReplay and SecsMissionReport (note the s in Secs). The shipped keys therefore do nothing and the compiled defaults are used. If you want these to take effect, correct the spelling.

Other keys in this section

Key Read by Notes
MinShift logreport.cpp via GetPrivateProfileInt, default 0 Torso shift minimum used by the match report.
lrpt logreport.cpp via GetPrivateProfileString, and written back Opaque report cache/registration value. Do not hand-edit.

[RookieMission]

Read by CTCL_SetCDSP (MW4Shell.cpp) at startup and exposed to the console lobby as script globals. Defines what the arcade "Rookie Mission" / Default button loads. The whole section is optional; omitting it uses the defaults below.

Key Type Default Effect
MissionName string ScarabStronghold - Attrition Mission loaded by default.
GameType int 2 Game type index (2 = Attrition).
TimeLimit int -1 Minutes. -1 = use the server's current time setting (TimeList_Value).
Visibility int 0 0 clear, 1 light, 2 medium, 3 heavy.
Weather int 0 0 off, 1 rain.
TimeOfDay int 0 0 day, 1 night.
Radar int 0 0 novice, 1 off, 2 bars, 3 unlimited.
HeatOn int 0 Heat management.
FriendlyFire int 0 Percentage; 0 = off, 100 = full.
SplashDamage int 0 Splash damage on/off.
UnlimitedAmmo int 1 Unlimited ammo on/off.
WeaponJam int 0 Weapon jamming on/off.
AdvanceMode int 0 Advanced gyro on/off.
ArmorMode int 0 Advanced armor on/off.
NoReturn int 0 No respawn (respawn limit) on/off.

[battle tech print]

Read by mw4print.exe, not by the game. Uses GetPrivateProfileInt. All values are in the printer's logical units; the defaults are in recscore.cpp.

Page layout: PaperMarginL, PaperMarginT, PaperMarginR, PaperMarginB, TopImageHeight, GapColumn, ImageTitleHeight, GapTopImageTable.

Table layout: CellMarginLR, CellMarginTV, TableTextHeight, GapFFA, GapTableMH.

Mission highlights: MHHeight, MHTextHeight, GapMHText.

Text block: TextMarginL, TextMarginT, TextMarginR, TextMarginB, TextHeight, InfoTextHeight.

Key Notes
BannerText Legacy fallback only. The banner is now read from banner.txt (first line) next to mw4print.exe; this key is only consulted if that file is missing or empty. It was moved because the game rewrites options.ini and dropped unknown keys.

Dead settings

These appear in the shipped options.ini but are not read by any code in this tree. They are stock MechWarrior 4 leftovers. Editing them does nothing.

[network options] ? entire section is dead

connectiontype, connectionspeed, packetsize, defaultconnection, playericon, teamicon.

Verified: no GetEntry/GetPrivateProfile* call anywhere references these key names. The connection type actually used at runtime comes from conDefault.connectiontype, which is populated from the multiplayer connection wizard, not from this file.

Individual dead keys

Key Section Why dead
videodriverindex [graphics options] Read call commented out; device forced to 0.
huddamagemode [special commands] Read call commented out; forced false.
hudtargetdamagemode [special commands] Read call commented out; forced false.
secmissionreplay [battle tech misc] Misspelled; code reads SecsMissionReplay.
secmissionreport [battle tech misc] Misspelled; code reads SecsMissionReport.

Practical notes

  • Back up options.ini before experimenting. The game rewrites parts of it, and an unknown key is silently ignored rather than reported, so a typo produces no diagnostic ? just default behaviour.
  • Per-role files. On a pod, the launcher copies options-game.ini, options-cam.ini or options-mr.ini over options.ini depending on the machine's role. Edit the role file, not the live one, or your change will be overwritten at next launch.
  • The 2016 release drop shipped hardwaremixing=true, BiggieSizeIt=1 and RuleBook=1, where the current dev tree ships different values. If you are chasing a behavioural difference against that release, compare these first.
  • Case. Section and key names are matched case-insensitively by the notation reader, but the spelling must otherwise be exact.