Skip to main content

Options

Options are the controls your module exposes in the menu — toggles, sliders, dropdowns, text fields, color pickers. You declare them in phase 1, and each declaration returns a live Option handle you read and observe from your listeners.

defineModule({ name: "Example", category: ModuleCategory.Client }, (options) => {
const enabled = options.boolean("Particles", true);
const count = options.number("Count", 8, { min: 1, max: 64, step: 1, displayResolution: 0 });
const mode = options.enum("Mode", ["Spin", "Pulse", "Wave"] as const, "Spin");
const color = options.color("Tint", [255, 0, 0, 255]);

return (ctx) => {
ctx.on("tick", () => {
if (!enabled.value) return;
render(count.value, mode.value, color.value);
});
};
});

Declaring options — ModuleOptions

The options object passed to build has one method per kind:

MethodReturnsDescription
boolean(name, def?)Option<boolean>A toggle. def defaults to false.
number(name, def, props)Option<number>A slider; props is NumberOptionProps.
string(name, def?)Option<string>A free-text field. def defaults to "".
enum(name, values, def?)Option<T>A single choice over a fixed list of strings. def defaults to values[0].
color(name, def)Option<Color>An RGBA color picker.

NumberOptionProps

interface NumberOptionProps {
min: number;
max: number;
step?: number;
displayResolution: number; // decimal places shown in the UI
}

Color

type Color = [r: number, g: number, b: number, a: number]; // each channel 0-255

Enums

Pass as const on the values array so the option's type narrows to the literal union:

const mode = options.enum("Mode", ["Spin", "Pulse", "Wave"] as const, "Spin");
// mode.value : "Spin" | "Pulse" | "Wave"

Reading & observing — Option<T>

Every declaration returns an Option<T>. Because options are declared once and shared across sessions, you can close over the handle in any listener.

MemberTypeDescription
valueTThe current value. Read it, or set it to change the option as if edited in the UI.
namestringDisplay name.
defaultValueTThe value reset() restores.
subscribe(listener, notifyFirst?)() => voidObserve changes; returns an unsubscribe fn. Pass notifyFirst: true to fire once immediately.
reset()voidRestore the default value.
isDefault()booleanWhether the current value is the default.
get typestringThe option kind, e.g. "boolean", "number".

Reading

Read option.value inside a listener — it always reflects the current menu state:

ctx.on("tick", () => {
if (speed.value > 0) applySpeed(speed.value);
});

Writing

Setting option.value applies the change and notifies subscribers, exactly as if the user moved the slider:

ctx.onEnable(() => { speed.value = 1.5; });

Subscribing

To react the moment an option changes (rather than polling each tick):

return (ctx) => {
const unsub = color.subscribe(() => rebuildPalette(color.value), true);
ctx.onDisable(unsub);
};

Tip — subscriptions vs. ctx.on. option.subscribe is not tied to the module's enabled state — it fires whenever the value changes. If you only want to react while enabled, unsubscribe in onDisable (as above), or just read option.value inside a ctx.on listener.