Modding:Options

From Caves of Qud Wiki
Jump to navigation Jump to search
This page is about modding. See the modding overview for an abstract on modding.
This page is about modding. See the modding overview for an abstract on modding.
For best results, it's recommended to have read the following topics before this one:

In some cases, it may be desirable to add tunable settings to your mod so that players may configure it to their liking. In these cases, you can piggyback off of Qud's built-in Options menu by creating new options via XML.

Adding new options

Any XML file with a root of <options /> will be parsed for options, but only files with the word Option in their file name will be considered for conditional content loading.

Here's an example of a custom options file:

<?xml version="1.0" encoding="utf-8" ?>
<options>
  <option ID="Option_MyName_MyMod_EnableFoo" DisplayText="Enable Foo" Category="Mods: MyMod"
    Type="Checkbox" Default="Yes" Restart="true">
    <helptext>
      Controls whether Foo is enabled.
    </helptext>
  </option>
  <option ID="Option_MyName_MyMod_FooSelector" DisplayText="Foo, Bar, or Baz?" Category="Mods: MyMod"
    Type="Combo" Values="Foo,Bar,Quux|Baz" Default="Foo" />
  <option ID="Option_MyName_MyMod_FooAmount" DisplayText="Amount of foo to use" Requires="Option_MyName_MyMod_EnableFoo==Yes" Category="Mods: MyMod"
    Type="Slider" Min="0" Max="100" Increment="2" Default="50" />
</options>

This produces a new section in the options menu, which appears as follows:

Example of custom settings added to the Options menu by a mod. This settings menu includes three new options: a checkbox for "Enable Foo", a combo selector for "Foo, Bar, or Baz?", and a slider labeled "Amount of foo to use".

XML Structure

The <option/> XML tag defines a new setting in Options.xml. This tag can have the following attributes:

Attribute Meaning
ID A unique ID corresponding to the option. This ID is used when retrieving the value of the configured setting. By convention, this ID starts with Option, and per best practices it is encouraged to have it also include the mod's ID.

If this attribute is set to an already existing option, it will overwrite it.

DisplayText The text that should be displayed alongside the option in the settings menu.
Category The section under which the option appears in the settings menu. In general, all of your options should go under a single custom category for your mod.
Type Affects the widget that is rendered for the option, and the values that it can take on. The following widget types are currently supported:
  • Checkbox
  • Combo
  • BigCombo
  • Slider
  • Button

Each of these types has custom attributes that are specific to them; see #Option Types below.

Default The default value that the option should be set to, before any user configuration.
Requires Hides the option unless the #Requirements Specification is met.
SearchKeywords Additional keywords that players can use to find an option in the settings menu.
Restart When set to true, changes to the value of the option require the game to restart. Players will be prompted to restart their game when they change these options.

This can be useful in conjunction with conditional path loading. For example, if an option allows some XML to be loaded that merges new content into an object blueprint, the game will need to be restarted before that merge will take effect.

Options can also contain a <helptext /> node, whose contents are used as a helpful tooltip when hovering over the option.

Option Types

Type Description Additional Attributes
Checkbox A box that can be checked and unchecked. When checked, the option's value is Yes; when unchecked, No. N/A
Combo / BigCombo A collection of options that can be selected from. The Values attribute specifies the options as a comma-delimited list, and the selected option is set as the value. If any entry contains the pipe character (e.g., 0|None), the left value is used as the option value while the right value is used for display.

In the Modern UI, there is no visual distinction between Combo and BigCombo options.

  • Values
Slider A slider that can be used to select an integer. Min and Max indicate the range of the slider, while Increment controls how big each "step" is.
  • Min
  • Max
  • Increment
Button A button that calls OnClick when pressed.

OnClick must be a fully-named method (e.g., Qud.UI.KeybindsScreen.ShowKeybindsClick), and may be an async function.

  • OnClick

Requirement Specification

A requirement specification is a comma-delimited list of entries of the form OptionID==Value, which is satisfied when the option OptionID is equal Value; or OptionID!=Value, which is satisfied when the option OptionID is not equal to Value. A specification is only satisfied when all entries are satisfied.

For instance, from the example above, adding Requires="Option_MyName_MyMod_EnableFoo==Yes,Option_MyName_MyMod_FooSelector!=Quux" to an option will hide that option unless the checkbox for the "Enable Foo" option is selected and the "Foo, Bar, or Baz?" option is not set to Baz.

Using configured options in code

Once you've added your own custom options, you can retrieve them in code in a couple of different ways.

OptionFlag attribute

TODO: explanation

using System;
using XRL;

namespace MyName.MyMod
{
  [HasOptionFlagUpdate(Prefix="Option_MyName_MyMod_")]
  public static class Options
  {
    [OptionFlag] public static bool EnableFoo;
    
    public static FooTypes FooVariant;
    [OptionFlag("FooSelector")]
    private static string _FooVariantBind
    {
      set
      {
        FooVariant = value switch
        {
          "Foo" => FooTypes.Foo,
          "Bar" => FooTypes.Bar,
          "Quux" => FooTypes.Quux,  // internal value for Baz
          _ => FooTypes.Foo
        };
      }
    }
    
    [OptionFlag] public static int FooAmount;
  }
}

Options.GetOption

Traditionally, options were obtained using the XRL.UI.Options.GetOption method. This method always returns a string, but you may want to convert them into a different type before using them in your code. One way of doing so is to create a thin wrapper around XRL.UI.Options that calls GetOption under the hood, for instance:

using System;

namespace MyName.MyMod {
    public static class Options {
        private static string GetOption(string ID, string Default = "") {
            return XRL.UI.Options.GetOption(ID, Default: Default);
        }

        public static bool EnableFoo => GetOption("Option_MyName_MyMod_EnableFoo").EqualsNoCase("Yes");
        public static int FooAmount => Convert.ToInt32(GetOption("Option_MyName_MyMod_FooAmount"));
    }
}

Enabling and disabling XML

Options can be used to conditionally enable XML using the Directories array in the mod's manifest.json.

Type Errors

If an options file contains a syntax error, it will be listed in the Player.log as normal. However, type errors are only evaluated on opening the in-game options menu. The menu will fail to open and you'll see an error in the Player.log: ---> (Inner Exception #0) System.FormatException: Input string was not in a correct format.. If you save the game without opening the options menu, this erroneous value will then be stored in PlayerOptions.json and, because those values are only regenerated on close of the options menu, you will need to manually edit and correct the file.