Skip to content

Custom Buttons

XtraCube edited this page Feb 27, 2026 · 5 revisions

Mira API provides a simple, yet customizable, interface for adding custom ability buttons to the game. Almost everything traditionally needed to create custom buttons is handled by the API, making it easy to create custom buttons with minimal effort.

Creating Buttons

To create a custom button, create a class that inherits from CustomActionButton. The API will automatically discover and register any class that extends CustomActionButton in your plugin assembly. Override the necessary properties and methods to define the button's behavior.

Here is an example of a custom ability button class:

public class ExampleButton : CustomActionButton
{
    public override string Name => "Example";
    public override float Cooldown => 10f;
    public override float EffectDuration => 0f; // 0 means no effect.
    public override int MaxUses => 0; // 0 means unlimited uses.
    public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;

    public override bool Enabled(RoleBehaviour? role)
    {
        return role is MyCustomRole; // only show button when the player has MyCustomRole.
    }

    protected override void OnClick()
    {
        Logger<MyPlugin>.Info("button clicked!");
    }
}

To access your CustomActionButton instance from another class, use the CustomButtonSingleton class:

var myButton = CustomButtonSingleton<ExampleButton>.Instance;
myButton.ResetCooldownAndOrEffect();

Button Properties and Methods

The following properties can be overridden to define the button's behavior:

Property Type Default Description
Name string (abstract) The name and label text of the button.
Cooldown float (abstract) The cooldown duration in seconds.
InitialCooldown float Cooldown The cooldown applied at the start of the game.
Sprite LoadableAsset<Sprite> (abstract) The sprite of the button.
EffectDuration float 0 The duration of the button's timed effect in seconds. When set to zero, the button will not have a timed effect.
MaxUses int 0 (infinite) The maximum number of times the button can be used. Set to 0 for unlimited uses when ZeroIsInfinite is true.
UsesMode ButtonUsesMode ButtonUsesMode.PerGame Controls whether uses reset each round or persist for the whole game.
Keybind BaseKeybind? null An optional keybind that triggers the button. If null, no keybind is registered. Consider using MiraGlobalKeybinds for cross-mod compatibility. See Keybinds.
CooldownTimerFormatString string "0" The format string for the cooldown timer text.
PauseTimerInVent bool false When true, the cooldown and effect timer will not decrease while the player is venting.
TextOutlineColor Color Color.clear The color of the text outline on the button. Set to Color.clear to disable.
Location ButtonLocation ButtonLocation.BottomLeft The location of the button on the screen. Supports BottomLeft and BottomRight.
ZeroIsInfinite bool true When true, MaxUses of 0 means unlimited. When false, unlimited is indicated by -1.

The following properties cannot be overridden but can be read to access the button's current state:

Property Type Description
HasEffect bool True if EffectDuration is greater than zero. Get only.
LimitedUses bool True if the button has a finite number of uses. Get only.
EffectActive bool True if the button's timed effect is currently active.
TimerPaused bool True if the timer is currently paused.
UsesLeft int The number of uses remaining. Use the utility methods below to modify this.
Timer float The current timer value. Use the utility methods below to modify this.
Button ActionButton? The underlying game button object, created automatically by the API.
KeybindIcon GameObject? The keybind icon game object, available when a keybind is assigned.

The CustomActionButton class provides the following methods. Most have default implementations that can be overridden to customize behavior:

Method Signature Description
void CreateButton(Transform parent) Creates the button object in the HUD. Should not normally be overridden.
void SetButtonLocation(ButtonLocation location, bool moveButton = true) Changes the button's location in the HUD.
void ResetCooldownAndOrEffect() Resets the timer to the cooldown value and ends any active effect. Called automatically when meetings start and end.
void SetTextOutline(Color color) Sets the outline color of the button's label text.
void OverrideSprite(Sprite sprite) Replaces the button's sprite.
void OverrideName(string name) Replaces the button's label text.
void SetTimer(float value) Sets the timer to the given value.
void IncreaseTimer(float value) Increases the timer by the given value.
void DecreaseTimer(float value) Decreases the timer by the given value.
void SetTimerPaused(bool val) Pauses or unpauses the timer.
void SetUses(int value) Sets the remaining uses to the given value.
void IncreaseUses(int value) Increases the remaining uses by the given value.
void DecreaseUses(int value) Decreases the remaining uses by the given value.
void OnClick() Called when the button is successfully clicked. This is a callback, not the click handler itself. Only called when the button is able to be used.
bool Enabled(RoleBehaviour? role) Determines whether the button should be active for the given role.
void OnEffectEnd() Called when the button's timed effect ends.
bool IsEffectCancellable() Returns whether the player can cancel the active effect early by clicking the button again. False by default.
bool CanClick() Determines if the button can be clicked. By default checks the timer, effect state, and uses.
bool CanUse() Determines whether the button should be lit up. Does not include the timer check; that is handled by CanClick().
void SetActive(bool visible, RoleBehaviour role) Called by HudManager.SetHudActive(). Controls button visibility in scenarios like when the map is open.
void ClickHandler() The actual click handler. Checks CanUse(), reduces remaining uses, calls OnClick(), then sets the cooldown or starts the effect. Can be overridden for custom click behavior.
void FixedUpdate(PlayerControl playerControl) Called each fixed update tick on the local player if this button is enabled. Override for per-tick logic.
void FixedUpdateHandler(PlayerControl playerControl) Handles the timer countdown and button state each tick, then calls FixedUpdate(). Should not normally be overridden.

Button Uses Mode

The UsesMode property controls how limited uses behave across rounds. It accepts a ButtonUsesMode enum value:

Value Description
PerGame Uses are tracked for the entire game. (default)
PerRound Uses reset at the start of each meeting round.

Targeting Buttons

If your button needs to target a specific object such as a player or a dead body, use CustomActionButton<T>, where T is a MonoBehaviour type. The API handles finding and tracking the target each update tick.

To access your target from inside the button, use the Target property of type T?.

The following additional property is available on targeting buttons:

Property Type Description
Distance float The maximum distance the target can be from the player. Defaults to the role's ability distance.

The following additional methods must or can be overridden:

Method Signature Description
T? GetTarget() Returns the current target, or null if none. Must be overridden.
void SetOutline(bool active) Sets the visual outline on the target object. Must be overridden.
bool IsTargetValid(T? target) Returns whether the given target is valid. Defaults to checking for non-null.
void ResetTarget() Clears the target and removes its outline.

Here is an example of a targeting button:

public class FreezeButton : CustomActionButton<PlayerControl>
{
    public override string Name => "Freeze";
    public override float Cooldown => 5f;
    public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
    public override bool PauseTimerInVent => true;

    protected override void OnClick()
    {
        Target?.RpcAddModifier<FreezeModifier>();
    }

    public override PlayerControl? GetTarget()
    {
        return PlayerControl.LocalPlayer.GetClosestPlayer(true, Distance);
    }

    public override void SetOutline(bool active)
    {
        Target?.cosmetics.SetOutline(active, new Il2CppSystem.Nullable<Color>(Palette.Blue));
    }

    public override bool IsTargetValid(PlayerControl? target)
    {
        return true;
    }

    public override bool Enabled(RoleBehaviour? role)
    {
        return role is FreezerRole;
    }
}

freezeButton
The Freeze button targeting another player in the game.

Multi-Target Buttons

For buttons that operate on multiple targets at once, use MultiTargetButton<T>, where T is a MonoBehaviour type. Targets are stored in the Targets array property.

The following additional properties are available:

Property Type Description
Distance float The maximum distance targets can be from the player.
MaxTargets int The maximum number of targets the button will track. Defaults to unlimited.

The following additional methods must or can be overridden:

Method Signature Description
T[] GetTargets() Returns the array of current targets. Must be overridden.
void SetOutline(T target, bool active) Sets the visual outline on a given target. Must be overridden.
bool IsTargetValid(T target) Returns whether a given target is valid. Defaults to checking for non-null.
void ResetTarget() Clears all targets and removes their outlines.

Clone this wiki locally