Skip to content

Custom Command Settings

ekudram edited this page Jul 4, 2026 · 2 revisions

Custom Command Settings for Modders

RICS supports adding per-command custom settings using the <CustomData> section inside your <CAP_ChatInteractive.ChatCommandDef> in your mod's Commands.xml.

This lets you expose toggles, numbers, text fields, headers, and spacing directly in the Command Editor without polluting global settings or requiring code changes to the core mod.

Settings are stored in the command's CommandSettings.CustomData (as JSON) and accessed at runtime with GetCustom<T>().

Basic Structure

Inside your command definition:

<CAP_ChatInteractive.ChatCommandDef>
  <defName>MyAwesomeCommand</defName>
  <commandText>myawesome</commandText>
  <label>my awesome</label>
  <enabled>true</enabled>
  <commandClass>YourMod.YourCommandClass</commandClass>
  <commandDescription>Does cool stuff!</commandDescription>
  <cooldownSeconds>30</cooldownSeconds>
  <useCommandCooldown>true</useCommandCooldown>

  <!-- Custom per-command settings appear in the Command Editor -->
  <CustomData>
    <!-- Add your UI elements here (order matters) -->
  </CustomData>
</CAP_ChatInteractive.ChatCommandDef>

Supported Types

Type matching is case-insensitive. Order in <CustomData> determines display order in the Command Editor under "Command Specific Settings".

HeaderLabel (or header)

Medium font header / section title. Use for grouping. A small extra gap (~4px) is added after for descenders.

<li>
  <type>HeaderLabel</type>
  <label>My Section</label>
</li>

You can nest multiple HeaderLabels for subsections (see Passion command).

Label

Small/regular text label (for notes or descriptions).

<li>
  <type>Label</type>
  <label>Some helpful note here</label>
</li>

CheckBox (or bool)

Boolean toggle. Renders as a standard checkbox.

<li>
  <type>CheckBox</type>
  <name>enableCoolFeature</name>
  <label>Enable Cool Feature</label>
  <defaultValue>true</defaultValue>
  <description>Turn this on to do the cool thing.</description>
</li>

NumericTextBox (NumericTextBox, int, or float)

Number input. Supports optional min/max. Use <type>int</type> or <type>float</type> for typed parsing.

<li>
  <type>NumericTextBox</type>
  <name>myValue</name>
  <label>My Number Value</label>
  <defaultValue>42</defaultValue>
  <min>0</min>
  <max>1000</max>
  <description>Some number between 0 and 1000.</description>
</li>

LabelTextBox (or any other / string fallback)

Free text input field (fallback for unrecognized types or explicit text).

<li>
  <type>LabelTextBox</type>
  <name>myText</name>
  <label>Custom Message</label>
  <defaultValue>Hello World</defaultValue>
</li>

Gap (or spacer)

Pure vertical spacing (great for breathing room between groups). The pixel amount comes from defaultValue.

<li>
  <type>Gap</type>
  <defaultValue>12</defaultValue>
</li>

Button (or action)

A clickable button inside the command's custom settings. Primarily intended for "Reset to Defaults", but can be used for any action your command understands.

  • The dialog automatically resets all this command's CustomData values to the defaults declared in your XML.
  • It then calls OnCustomDataButtonClicked(buttonName, settings) on your command instance so you can perform additional reset work (clear lists, other state, etc.).
  • name is passed as buttonName so you can support multiple buttons on one command.
<li>
  <type>Button</type>
  <name>resetToDefaults</name>
  <label>Reset to Defaults</label>
  <description>Restores all custom settings for this command to the values defined in the mod XML.</description>
</li>

C# hook (put this in the class you reference from <commandClass>):

public override void OnCustomDataButtonClicked(string buttonName, CommandSettings settings)
{
    if (buttonName == "resetToDefaults")
    {
        // CustomData values have already been reset by the editor.
        // Do extra work here if needed, e.g.:
        // settings.AllowedRaidTypes.Clear();
        // settings.AllowedRaidStrategies.Clear();
    }
}

Buttons only execute inside the in-game Command Editor (on the streamer's machine).

Accessing Values in Your Code

In your ChatCommand subclass or handler:

public override string Execute(ChatMessageWrapper messageWrapper, string[] args)
{
    var settings = GetCommandSettings();   // Preferred if inside ChatCommand subclass

    // Or explicitly (works from any handler or static method):
    // var settings = CommandSettingsManager.GetSettings("myawesome");

    bool coolFeature = settings.GetCustom<bool>("enableCoolFeature", true);
    int value = settings.GetCustom<int>("myValue", 42);
    string text = settings.GetCustom<string>("myText", "default");

    if (!coolFeature)
        return "That feature is disabled for this command.";

    // ... your logic using the values ...
}
  • GetCustom<T>(key, defaultValue) safely returns the stored value or your provided default.
  • Values are stored as strings in JSON but GetCustom parses to bool/int/float/string.
  • Use SetCustom<T>(key, value) if you need to persist changes from code (rare for modder commands; most changes come from the in-game Command Editor).
  • Call settings.EnsureCustomDefaults(def.CustomData) if you need defaults populated manually (the editor and initializer normally do this for you).

Best Practices

  • Order matters: Elements are rendered top-to-bottom exactly as they appear in <CustomData>.
  • Use HeaderLabel for section titles inside your custom settings. You can use multiple HeaderLabels for subsections.
  • Use Gap (4–16 pixels is common) to separate groups.
  • Provide good <description> text — it becomes a tooltip in the editor.
  • For sub-commands (e.g. !mypawn body, !mypawn mech), use enabled checkboxes and check them early in your handler. Return a friendly message like "Sub Command body is disabled."
  • Keep names consistent and descriptive (enableX, costY, multiplierZ).
  • Add your CustomData after the standard fields (cooldownSeconds, useCommandCooldown, etc.).
  • For simple on/off social-style interactions, a single top-level <CheckBox name="enabled"> + early return check is sufficient (see Social Commands).

Handler Examples (Sub-Command Disables & Settings)

MyPawn sub-commands (many checkboxes)

In XML (excerpt):

<CustomData>
  <li><type>HeaderLabel</type><label>MyPawn Sub-Commands</label></li>
  <li><type>CheckBox</type><name>enableBody</name><label>Body</label><defaultValue>true</defaultValue></li>
  <li><type>CheckBox</type><name>enableHealth</name><label>Health</label><defaultValue>true</defaultValue></li>
  ... (gear, skills, psycasts, mechs, etc.)
</CustomData>

Early check in handler (MyPawnCommandHandler.cs):

var cmdSettings = CommandSettingsManager.GetSettings("mypawn");
string settingKey = null;
switch (sub)
{
    case "body": settingKey = "enableBody"; break;
    case "health": settingKey = "enableHealth"; break;
    // ... map other subs
    case "psycasts": settingKey = "enablePsycasts"; break;
    case "mechs": settingKey = "enableMechs"; break;
}
if (settingKey != null && !cmdSettings.GetCustom<bool>(settingKey, true))
{
    return $"Sub Command {subCommand} is disabled.";
}

Social interactions (per-command enabled flag)

Many social commands (chitchat, deeptalk, flirt, etc.) declare a tiny CustomData:

<CustomData>
  <li>
    <type>CheckBox</type>
    <name>enabled</name>
    <label>chitchat</label>
    <defaultValue>true</defaultValue>
  </li>
</CustomData>

Check early (EnhancedInteractionCommandHandler.cs style):

var cmdSettings = CommandSettingsManager.GetSettings(cmdName); // "chitchat", "flirt", etc.
if (!cmdSettings.GetCustom<bool>("enabled", true))
{
    return $"Sub Command {cmdName} is disabled.";
}

Complex numeric settings (Passion / Raid wagers)

Passion uses many grouped numerics + headers:

<CustomData>
  <li><type>HeaderLabel</type><label>Wager Limits and Scaling</label></li>
  <li><type>int</type><name>minPassionWager</name> ... </li>
  ...
  <li><type>HeaderLabel</type><label>Success Chance Scaling</label></li>
  ...
</CustomData>

Usage:

var s = CommandSettingsManager.GetSettings("passion");
int minW = s.GetCustom<int>("minPassionWager", 500);
float bonus = s.GetCustom<float>("passionWagerBonusPer100", 1.0f);

Raid and MilitaryAid store only their three wager fields (default/min/max) via CustomData so they don't bloat the shared settings object.

Full Example

<CustomData>
  <li>
    <type>HeaderLabel</type>
    <label>Advanced Options</label>
  </li>
  <li>
    <type>CheckBox</type>
    <name>enableFeature</name>
    <label>Enable Special Feature</label>
    <defaultValue>true</defaultValue>
    <description>Does the special thing when on.</description>
  </li>
  <li>
    <type>Gap</type>
    <defaultValue>8</defaultValue>
  </li>
  <li>
    <type>NumericTextBox</type>
    <name>bonusAmount</name>
    <label>Bonus Amount</label>
    <defaultValue>50</defaultValue>
    <min>0</min>
    <max>500</max>
  </li>
</CustomData>

Accessing from Handlers (non-ChatCommand classes)

Static handlers or other classes can fetch settings by the commandText (or defName lowercased in some cases):

var settings = CommandSettingsManager.GetSettings("myawesome");
bool feature = settings.GetCustom<bool>("enableFeature", true);

Where to Put Your CustomData (Modders)

Place the <CAP_ChatInteractive.ChatCommandDef> (with its <CustomData>) inside a Defs/Commands/Something.xml in your own mod.

Example folder structure:

YourMod/
  About/
    About.xml
  Defs/
    Commands/
      MyCommands.xml

Your mod must load after (or be compatible with) RICS so the Def type is recognized. Use the same <commandClass> pointing to your handler code.

You can also patch existing commands from RICS to add CustomData via XML patches if desired (advanced).

Notes

  • These settings only affect your command — they do not appear for other commands.
  • The Command Editor will automatically show a "Command Specific Settings" section when your command has CustomData.
  • Changes are saved in the user's CommandSettings.json under your command's entry.
  • Core RICS commands (raid, mypawn, passion, surgery, socials, etc.) already use this system extensively.

This system is designed so addon authors and custom command creators can add rich, per-command configuration without touching global settings or core RICS code.

Happy modding! If you create cool commands, consider sharing them on the RICS Discord or GitHub discussions.

Clone this wiki locally