Modding Tutorials/ModSettings

From RimWorld Wiki
Jump to navigation Jump to search

Modding Tutorials

Mod settings allow you to offer customisation options to your users.

Requirements[edit]

What you'll learn[edit]

You'll learn how to write, save and use mod settings.

Setting up[edit]

Adding mod settings requires two classes, one that inherits from Mod and one that inherits from ModSettings.

The code[edit]

//inspired by https://gist.github.com/erdelf/84dce0c0a1f00b5836a9d729f845298a
using System.Collections.Generic;
using Verse;
using UnityEngine;

namespace MyExampleMod
{
    public class ExampleSettings : ModSettings
    {
        /// <summary>
        /// The three settings our mod has.
        /// </summary>
        public bool exampleBool;
        public float exampleFloat = 200f;
        public List<Pawn> exampleListOfPawns = new List<Pawn>();

        /// <summary>
        /// The part that writes our settings to file. Note that saving is by ref.
        /// </summary>
        public override void ExposeData()
        {
            Scribe_Values.Look(ref exampleBool, "exampleBool");
            Scribe_Values.Look(ref exampleFloat, "exampleFloat", 200f);
            Scribe_Collections.Look(ref exampleListOfPawns, "exampleListOfPawns", LookMode.Reference);
            base.ExposeData();
        }
    }

    public class ExampleMod : Mod
    {
        /// <summary>
        /// A reference to our settings.
        /// </summary>
        ExampleSettings settings;

        /// <summary>
        /// A mandatory constructor which resolves the reference to our settings.
        /// </summary>
        /// <param name="content"></param>
        public ExampleMod(ModContentPack content) : base(content)
        {
            this.settings = GetSettings<ExampleSettings>();
        }

        /// <summary>
        /// The (optional) GUI part to set your settings.
        /// </summary>
        /// <param name="inRect">A Unity Rect with the size of the settings window.</param>
        public override void DoSettingsWindowContents(Rect inRect)
        {
            Listing_Standard listingStandard = new Listing_Standard();
            listingStandard.Begin(inRect);
            listingStandard.CheckboxLabeled("exampleBoolExplanation", ref settings.exampleBool, "exampleBoolToolTip");
            listingStandard.Label("exampleFloatExplanation");
            settings.exampleFloat = listingStandard.Slider(settings.exampleFloat, 100f, 300f);
            listingStandard.End();
            base.DoSettingsWindowContents(inRect);
        }

        /// <summary>
        /// Override SettingsCategory to show up in the list of settings.
        /// Using .Translate() is optional, but does allow for localisation.
        /// </summary>
        /// <returns>The (translated) mod name.</returns>
        public override string SettingsCategory()
        {
            return "MyExampleModName".Translate();
        }
    }
}

ExampleSettings[edit]

ExposeData[edit]

Writes settings to disk. For more info on saving, see ExposeData.

ExampleMod[edit]

Refer to the source above for practical information; snippets here are supplemental.

ExampleSettings[edit]

An easy reference to our settings.

ExampleMod[edit]

A mandatory constructor.

DoSettingsWindowContent[edit]

It's not mandatory to implement, but since the point of most settings is the provide customisation to the end user, it makes sense to make them available somehow.

The GUI[edit]

Listing_Standard is a barebones but useful class for making a GUI, and it does most of the positioning for you. Listing_Standard.Begin and Listing_Standard.End is required: every GUIGroup in Unity you start has to end. If you want more options to Listing_Standard, there's a good SettingsHelper available.

The Widgets class is a powerful alternative to Listing_Standard that gives you more fine-grained control, at the cost of more effort. You'll have to set the size and position of each Rect manually. You can use TweakValues to do this more easily.

Saving[edit]

Saving (altered) settings is done automatically by closing the window. You can optionally override WriteSettings() to add additional functionality to writing settings.

SettingsCategory[edit]

RimWorld will only make your settings accessible if SettingsCategory returns a string that isn't null or empty.

Using your settings[edit]

  • One easy way to call settings is to make them all static and load their values with ExampleSettings.exampleBool. In certain cases, this is not practical.
  • If you can't (or don't want to) make your settings static, you can obtain your settings through the LoadedModManager like so:
 LoadedModManager.GetMod<ExampleMod>().GetSettings<ExampleSettings>().exampleBool
  • As the above is a lot of code, you can simple add a reference to your settings and resolve it once in a constructor or otherwise.

On the necessity of HugsLib[edit]

Some people think HugsLib is a necessity for implementing mod settings. This is not true; the above is 100% supported by vanilla, since A17. HugsLib offers an alternative way of using settings.

See also[edit]

SettingsHelper - A lightweight MIT-licensed dll with various extension methods for Listing_Standard.
HugsLib - HugsLib is a popular dependency that aims to ease using settings.