-
Notifications
You must be signed in to change notification settings - Fork 26
Custom Buttons
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.
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();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. |
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. |
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;
}
}
The Freeze button targeting another player in the game.
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. |