Skip to content

Custom Buttons

XtraCube edited this page Aug 31, 2024 · 2 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, you need to create a class that inherits from CustomActionButton. This class should be decorated with the RegisterButton attribute. The RegisterButton attribute is used to register the button with the API. The button class should override the necessary properties and methods to define the button's behavior.

Here is an example of a custom ability button class:

[RegisterButton]
public class ExampleButton : CustomActionButton
{
    public override string Name => "Example";
    public override float Cooldown => 10f;
    public override float EffectDuration => 0f; // 0 means no effects.
    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 role.
    }

    protected override void OnClick()
    {
        Logger<MyPlugin>.Info("button clicked!"); // log a message when the button is clicked.
    }
}

In case you need to access your CustomActionButton instance from another class, you can use the CustomButtonSingleton class like this:

var myButton = CustomButtonSingleton<MyCoolButton>.Instance;
myButton.ResetCooldownAndOrEffect(); // Reset the cooldown and effect of the button.

Button Properties and Methods

The button API provides a lot of flexibility through various properties and methods. Here are the available properties you can override:

Property Type Description
Name string The name of the button.
Cooldown float The cooldown of the button in seconds.
EffectDuration float The duration of button's timed effect in seconds. When set to zero, the button will not have a timed effect.
MaxUses int The maximum number of times the button can be used.
Sprite LoadableAsset<Sprite> The sprite of the button.
Location ButtonLocation The location of the button on the screen. Currently supports BottomLeft and BottomRight.

Here are the overridable methods:

Method Signature Description
void OnClick() Called when the button is clicked. This is not the actual click handler! This method is only called if the button can be used.
bool Enabled(RoleBehaviour? role) Determines if a button should be enabled for a given role.
void OnEffectEnd() If the button has a timed effect, this method will be called when that effect has ended.
bool CanUse() Determines if the button is usable or not. Default behaviour is to check that the cooldown timer has ended and there is still uses remaining.
void FixedUpdate(PlayerControl playerControl) Called on the local player's FixedUpdate() if this button is enabled for the local player.
void SetActive(bool visible, RoleBehaviour role) Called when the HudManager.SetActive() method is called. This is needed so the button can be hidden in certain scenarios like when the map is opened.
void ClickHandler() Called when the button is clicked. This is the actual click handler. By default it checks the CanUse() method, reduces the remaining uses, calls the OnClick() method, then sets the necessary cooldown, either for button cooldown or effect.
void FixedUpdateHandler(PlayerControl playerControl) This method handles the Timer cooldown and other things bound to Update. After handling all the logic it calls FixedUpdate()

Button Utilities

There are various properties and methods available to interact with different parts of your button, like the timer or the max uses.

Here are the available properties on the CustomActionButton class:

Property Type Description
HasEffect bool Indicates if the button has a timed effect. Get only.
LimitedUses bool Indicates if the button has a limited number uses. Get only.
EffectActive bool Indicates if the button's timed effect is active. This property has a protected setter.
UsesLeft int The number of uses left for the button. This property has a protected setter, but there are various utility methods to interact with it.
Timer float The current timer value for the button. This property has a protected setter, but there are various utility methods to interact with it.
Button ActionButton? The actual button object. This property can only be read since it is set by Mira API automatically.

Here are the available methods on the CustomActionButton class:

Method Signature Description
void ResetCooldownAndOrEffect() Resets the timer to the cooldown value and disables an active effect if there is one. This is automatically called when meetings start and end.
void OverrideSprite(Sprite sprite) Overrides the button's sprite with the provided sprite.
void OverrideName(string name) Overrides the button's name text with the provided name.
void SetTimer(float value) Sets the timer value to the provided value.
void IncreaseTimer(float value) Increases the timer value by the provided value.
void DecreaseTimer(float value) Decreases the timer value by the provided value.
void SetUses(int value) Sets the uses left value to the provided value.
void IncreaseUses(int value) Increases the uses left value by the provided value.
void DecreaseUses(int value) Decreases the uses left value by the provided value.

Targeting Buttons

If you want your button to have a specific target type, like a button that targets players or dead bodies, you have to use the CustomActionButton<T> class, where T is a target type of type MonoBehaviour. This class is used to target specific objects in the game.

Targeting buttons have a couple extra methods to override and properties to set.

Property Type Description
Distance float The maximum distance the target can be from the player.
Method Signature Description
bool IsTargetValid(T? target) Determines if the target is valid for the button.
T? GetTarget() Gets the target for the button.
void SetOutline(bool active) Sets the outline of the target object.

In order to access your target from the button class, you can use the Target property, which is of type T?.

Here is an example of a custom targeting button class:

[RegisterButton]
public class FreezeButton : CustomActionButton<PlayerControl>
{
    public override string Name => "Freeze";
    public override float Cooldown => 5f;
    public override float EffectDuration => 0f;
    public override int MaxUses => 0;
    public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;

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

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

    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.

Clone this wiki locally