Config integration

A script can read settings that the user controls. The Config global is your mod's own settings namespace, shown to players in the settings menu and persisted to a config file. Use it to give players a number that they can adjust, or a list of choices. Players then do not have to edit your Lua.

Config is available to every patch script with PM and J. CampaignConfig is also available. It works the same way, but it keeps a separate value for each campaign.

Defining an entry

You declare an entry with Config:Define(section, name), chain a few descriptors, and finish with :Bind(). Binding returns a live handle you read through:

local thrustScale = Config:Define("Tweaks", "ThrustScale")
    :Type(Double)
    :Default(1.0)
    :Range(0.5, 2.0)
    :Desc("Scales the thrust readout in the engine window.")
    :Bind()

Define takes a section and a name, which is how the entry is grouped and labeled in the settings menu. The following builder members are then used to fill it out:

  • :Type(...) sets the value type. The built-in types are the globals String, Integer, Double, Boolean, and Color. This one is required.

  • :Default(value) sets the value used on first launch, before the player changes anything.

  • :Range(min, max) constrains a number to a slider. Optional extra arguments set the slider step count and number format.

  • :Values({...}) constrains the value to a fixed set of choices.

  • :Desc(text) sets the description shown in the settings menu. :NameLoc(key) and :DescLoc(key) set localization keys instead, for translated text.

  • :Feature(id) and :NoFeature(id) show the entry only while a feature is on, or off. See below.

  • :Tag(name) attaches a metadata tag.

  • :Bind() finalizes the entry and returns the handle.

Entry definition is idempotent. If you define the same entry in multiple Lua files for your mod, it will not create multiple config entries, and if the form of all the entries is the same then it does not matter which one runs first. This means that you are safe to define config handles in a library file for your mod.

Reading and writing the value

The handle has a value field. Read it to get the current setting, assign it to change the setting (which is automatically persisted):

if thrustScale.value ~= 1.0 then
    -- the player has changed it
end

If you only need to read an entry you defined elsewhere, Config:Get(section, name) returns a handle for an existing entry, or nil if it was never defined.

Settings and patches

PatchManager keeps a cache for each feature set. The cache does not monitor settings. When a patch reads a setting, the cache keeps the value from the last build of that set. A change to the setting does not cause a rebuild. Thus, do not make the output of your patches depend on a setting.

Content that a player turns on or off for each campaign is a feature. Gate the patch on the feature, not on a setting:

PM.Parts:Patch("BuffHeavyEngines")
        :Feature("BuffHeavyEngines")
        :Named("engine_2v_methalox_mainsail")
        :Do(function(part) ... end)

The player turns the feature on for a campaign in the feature editor. Each set has its own patch run and its own cache, so no cache becomes stale. Use settings only for runtime behaviour: values that the code of your mod reads while the game runs.

Showing an entry only with a feature

:Feature(id) on the builder shows the entry in the settings menu only while that feature is on in the active set. :NoFeature(id) shows the entry only while that feature is off. An id without a mod prefix is a feature of your mod. An entry that you define inside PM:WithFeature automatically gets the feature of that scope:

local hardModeMultiplier = Config:Define("HardMode", "CostMultiplier")
    :Type(Double):Default(2.0)
    :Feature("HardMode")
    :Bind()

All entries are also hidden while the default feature of your mod is off.

Per-campaign settings

CampaignConfig has the same Define, Get and Mod members as Config, but each campaign keeps its own values:

  • The values are saved with the campaign.

  • A new campaign starts with the default values.

  • Players change the values in the settings of your mod, under a Campaign heading. This heading shows when they open the settings from the pause menu of a campaign that has your mod on.

Use CampaignConfig for choices that apply to one playthrough, not to the player:

local startingFunds = CampaignConfig:Define("Campaign", "StartingFunds")
    :Type(Integer):Default(10000)
    :Bind()

As with Config, use CampaignConfig in runtime code. A patch serves all campaigns that have the same set, so a patch cannot read the values of one campaign.

Using another mod's config

Config:Mod(modId) gives you read and write access to the config of a different mod. A script can use it to react to a setting of that mod. Do not use it for your own settings. Use Config:Define and Config:Get as shown on this page.

Config file location

Your mods config file location depends on whether or not it is a "standalone" Lua mod. If it is standalone, then the config file will be in the mods folder right next to your Lua file. If not then the config file will be in the root of your mod's folder next to its SWInfo manifest. The game stores CampaignConfig values in the save of each campaign.