developers / latest

Mod.Call API

Register Settings Overhaul rows, sub-toggle items, Quick Access entries, and feature gates from another tModLoader mod.

Settings Overhaul Mod.Call API

Settings Overhaul exposes a registration API through Mod.Call. Use it from a mod that has a modReference on SettingsOverhaul when you want to add rows to the overhauled settings menu or add buttons to the Quick Access inventory cluster.

Important

Register during your mod’s PostSetupContent. The settings menu builds its category tree lazily, but registrations are intended to be complete before the menu is first opened.

public override void PostSetupContent()
{
	if (!ModLoader.TryGetMod("SettingsOverhaul", out Mod settings))
		return;

	settings.Call("EnableFeature", "screenshake");
}

Project Setup

Add SettingsOverhaul as a mod reference, then import the public model types you need:

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SettingsOverhaul.Modules.Common.Overhaul.Interface;
using SettingsOverhaul.Modules.Common.Overhaul.QuickAccess;
using SettingsOverhaul.Modules.Common.Overhaul;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;

The API uses the public SettingDefinition, SubToggleItem, DropdownHelpers, OverhaulIcon, and QuickAccessRender types from Settings Overhaul. Build rows with the SettingDefinition static factories instead of object initializers unless you need a custom control shape. The Microsoft.Xna.Framework/.Graphics usings are only needed if you supply a custom render for AddQuickAccessEntry.

Command Summary

The first Mod.Call argument is always a command string. Invalid commands or invalid argument types throw ArgumentException.

Command Purpose Return

AddRow

Add or replace one row in a settings category/group.

true

AddSubToggleItem

Add one item to a master sub-toggle row.

true

AddQuickAccessEntry

Add one selectable Quick Access inventory button.

bool

EnableFeature

Reveal a feature-gated built-in row.

true

DisableNativeButtonHook

Opt a mod out of Settings Overhaul’s native inventory-button takeover.

true

GetHideNextAchievement

Read the client preference for hiding the next achievement.

bool

SetHideNextAchievement

Update and save that client preference.

true

AddRow

settings.Call("AddRow", categoryId, groupId, row, sortAfterId?, sortBeforeId?)

Adds or replaces one settings row in a category/group. If another row in that group already has the same row.Id, the new row replaces it in place. Otherwise the row is inserted before sortBeforeId, then after sortAfterId, then appended if no anchor matches. The sort anchors are row IDs, not numeric order values.

Table 1. Common target groups
Category Groups

general

volume, zoom, basic_gameplay

gameplay

gameplay, hotkeys

interface

in_game, map, hud_ui, meters

video

display, comfort, graphics, effects

cursor

cursor_color, border_color, smart_cursor

multiplayer

multiplayer

Toggle Row Example

private static string T(string suffix) =>
	Language.GetTextValue("Mods.ExampleMod.UI.OverhaulSettings." + suffix);

public override void PostSetupContent()
{
	if (!ModLoader.TryGetMod("SettingsOverhaul", out Mod settings))
		return;

	SettingDefinition row = SettingDefinition.Toggle(
			"example_effects",
			OverhaulIcon.Item(ItemID.Sunflower),
			() => ExampleClientConfig.Get().EffectsEnabled,
			value =>
			{
				ExampleClientConfig config = ExampleClientConfig.Get();
				config.EffectsEnabled = value;
				config.Save();
			},
			resetTo: true,
			badge: OverhaulIcon.ModRoot("ExampleMod"))
		.WithLocalizedText(
			() => T("Settings.ExampleEffects.Name"),
			() => T("Settings.ExampleEffects.Desc"));

	settings.Call("AddRow", "video", "effects", row, "storm_effects");
}

Dropdown Row Example

private static readonly string[] QualityKeys =
[
	"Settings.ExampleQuality.Low",
	"Settings.ExampleQuality.Medium",
	"Settings.ExampleQuality.High",
];

private static SettingDefinition BuildQualityRow()
{
	return DropdownHelpers.EnumDropdown(
			"example_quality",
			SettingDefinition.SettingNameKey("example_quality"),
			SettingDefinition.SettingDescKey("example_quality"),
			OverhaulIcon.ModRoot("ExampleMod"),
			index => T(QualityKeys[index]),
			QualityKeys.Length,
			() => (int)ExampleClientConfig.Get().Quality,
			index =>
			{
				ExampleClientConfig config = ExampleClientConfig.Get();
				config.Quality = (ExampleQuality)index;
				config.Save();
			},
			resetDefault: () =>
			{
				ExampleClientConfig config = ExampleClientConfig.Get();
				config.Quality = ExampleQuality.Medium;
				config.Save();
			},
			badge: OverhaulIcon.ModRoot("ExampleMod"))
		.WithLocalizedText(
			() => T("Settings.ExampleQuality.Name"),
			() => T("Settings.ExampleQuality.Desc"));
}

AddSubToggleItem

settings.Call("AddSubToggleItem", masterRowId, item)

Adds one option to an existing master sub-toggle row. The currently supported master row is photosensitivity. It appears in video / comfort once at least one mod registers a sub-option.

settings.Call("AddSubToggleItem", "photosensitivity", new SubToggleItem
{
	Label = () => T("Settings.Photosensitivity.ExampleMod"),
	Badge = OverhaulIcon.ModRoot("ExampleMod"),
	Get = () => ExampleClientConfig.Get().ReduceMotion,
	Set = value =>
	{
		ExampleClientConfig config = ExampleClientConfig.Get();
		config.ReduceMotion = value;
		config.Save();
	},
});

AddQuickAccessEntry

settings.Call("AddQuickAccessEntry", id, label, tooltip, onClick, texturePath?, textureFrames?, defaultEnabled?, render?, menuIcon?)

Registers one selectable Quick Access button. The return value is a bool; valid calls currently return true. Missing or wrongly typed required arguments throw before registration.

texturePath

A content path loadable by ModContent.Request<Texture2D> or a vanilla texture path such as Images/UI/Bestiary. Only used to derive the in-world button draw and/or the settings-menu icon when render/menuIcon aren’t supplied for that part; if both are given, texturePath can be left null. When it’s still needed and null or blank, Settings Overhaul uses Images/UI/Bestiary.

textureFrames

When greater than one, texturePath is treated as a horizontal spritesheet (ignored once render is supplied).

defaultEnabled

When true, the entry is added to the default Quick Access order if there is room.

render

Overrides the in-world button draw. Accepts a QuickAccessRender (built via .Swap, .Frames, .Outlined, or .Custom) or a raw Action<SpriteBatch, Rectangle, bool hovered>, which is wrapped in QuickAccessRender.Custom for you.

menuIcon

Overrides the icon shown for this entry in the settings menu’s Quick Access picker. Accepts an OverhaulIcon, a Texture2D (wrapped via OverhaulIcon.Raw), or an int vanilla item id (wrapped via OverhaulIcon.Item).

settings.Call(
	"AddQuickAccessEntry",
	"example_panel",
	(Func<string>)(() => T("QuickAccess.ExamplePanel.Name")),
	(Func<string>)(() => T("QuickAccess.ExamplePanel.Tooltip")),
	(Action)(() => ExampleUiSystem.TogglePanel()),
	"ExampleMod/Assets/UI/ExamplePanelButton",
	2,
	false);

Custom Render and Menu Icon

render and menuIcon are independent — supply either, both, or neither. When both are supplied, texturePath isn’t needed at all:

settings.Call(
	"AddQuickAccessEntry",
	"example_panel",
	(Func<string>)(() => T("QuickAccess.ExamplePanel.Name")),
	(Func<string>)(() => T("QuickAccess.ExamplePanel.Tooltip")),
	(Action)(() => ExampleUiSystem.TogglePanel()),
	null,
	1,
	false,
	QuickAccessRender.Custom((sb, rect, hovered) =>
	{
		Color color = hovered ? Color.White : Color.White * 0.88f;
		QuickAccessRender.DrawTexture(sb, ExampleUiSystem.PanelIcon, rect, color);
	}),
	OverhaulIcon.Item(ItemID.Sunflower));

EnableFeature

settings.Call("EnableFeature", featureId)

Reveals a feature-gated built-in row.

Feature ID Effect

screenshake

Shows the shared screen-shake slider in video / comfort.

DisableNativeButtonHook

settings.Call("DisableNativeButtonHook", modName)

Opts a mod out of Settings Overhaul’s native inventory-button takeover. Use this when your mod has its own official Settings Overhaul integration and you want Settings Overhaul to leave your existing inventory button or interface layer alone.

Achievement Visibility

bool hidden = (bool)settings.Call("GetHideNextAchievement");
settings.Call("SetHideNextAchievement", true);

GetHideNextAchievement returns the current client-side HideNextAchievement preference (default: false). SetHideNextAchievement takes a required bool, saves the client config immediately, and returns true. A missing or non-boolean value throws ArgumentException. These calls read or update a preference and do not register a settings row.

Localization

Rows contributed by another mod should usually call WithLocalizedText. Without it, the UI resolves NameKey and DescKey against Settings Overhaul’s own localization prefix, which is only correct for rows owned by Settings Overhaul.

SettingDefinition.Toggle(...)
	.WithLocalizedText(
		() => Language.GetTextValue("Mods.ExampleMod.UI.OverhaulSettings.Settings.Example.Name"),
		() => Language.GetTextValue("Mods.ExampleMod.UI.OverhaulSettings.Settings.Example.Desc"));

If you use SettingDefinition.SettingNameKey("example") and SettingDefinition.SettingDescKey("example"), those produce suffixes like Settings.Example.Name and Settings.Example.Desc. You still decide which mod localization prefix to apply by using WithLocalizedText.

Icons

OverhaulIcon supports several useful shapes:

OverhaulIcon.Item(ItemID.Sunflower);
OverhaulIcon.Texture("Images/UI/Camera_1");
OverhaulIcon.Mod("SettingsOverhaul/Modules/Common/Overhaul/Interface/Icons/Portrait");
OverhaulIcon.ModRoot("ExampleMod");
OverhaulIcon.None;

Use OverhaulIcon.ModRoot("YourModName") for source badges. It resolves the mod’s root icon_small.png lazily on the draw thread, which avoids GPU texture creation during load.

Lifecycle and Persistence

All registered rows are cleared on Settings Overhaul load, so register them every session from PostSetupContent.

Delegate getters and setters run from the UI. If a row edits a ModConfig, update the config object and call Save() in the setter or reset action.

Quick Access order is player-local and capped at nine enabled entries. Entries with defaultEnabled: true are added to the default order when there is room. Saved preferences survive sessions without the entry’s provider. Absent entries do not consume the nine-button limit or a step in the editor’s reorder controls. If returning providers exceed that limit, the first nine present entries in the saved order are active; the remaining preferences are retained. Entries temporarily hidden by an availability predicate (for example, while a chest is open) still count as enabled in the editor.