Skip to content

Custom Roles

XtraCube edited this page Jun 25, 2025 · 14 revisions

Roles are straightforward in Mira API. There are two things you need to do to create a custom role:

  1. Create a class that inherits from a base game role (like CrewmateRole, ImpostorRole, etc.)
  2. Implement the ICustomRole interface from Mira API.
  3. Make sure your plugin class has the following attribute [ReactorModFlags(ModFlags.RequireOnAllClients)] or else your roles will not register correctly.

Note: For step 1, it is recommended to use CrewmateRole for neutral roles, but you can inherit directly from RoleBehaviour if you'd like. However, you must override the IsDead property, otherwise Il2Cpp will throw an error!

Mira API handles everything else, from adding the proper options to the settings menu, to managing the role assignment at the start of the game. There are no extra steps on the developer's part.

Example Role

Here is an example of a role class:

public class FreezerRole : ImpostorRole, ICustomRole
{
    public string RoleName => "Freezer";
    public string RoleLongDescription => "Freeze another player for a duration of time.";
    public string RoleDescription => this.RoleLongDescription;
    public Color RoleColor => Palette.Blue;
    public ModdedRoleTeams Team => ModdedRoleTeams.Impostor;
    public LoadableAsset<Sprite> OptionsScreenshot => ExampleAssets.Banner;
    public CustomRoleConfiguration Configuration => new CustomRoleConfiguration {
        MaxRoleCount = 2,
    };
}

And an in-game screenshot of the role:
freezeButton

Using Custom Roles

Since custom roles inherit from the vanilla RoleBehaviour class, you can usually use them in the same way you would use a vanilla role. For example, you can check a player's role like this:

PlayerControl player = ...;
if (player.Data.Role is FreezerRole freezer)
{
    // Do something with the freezer role
}

However, there are some issues due to strange Il2Cpp behavior. One notable example is accessing the RoleManager.Instance.AllRoles list. Checking the type of the role using the same code as above will fail. Instead, you can compare the RoleId using the RoleId utility.

foreach (var role in RoleManager.Instance.AllRoles)
{
    if ((RoleTypes)RoleId.Get<FreezerRole>() == role.Role)
    {
        // Do something with the freezer role
    }
}

Role Utilities

Mira API provides a few utilities to help you with your role development.

CustomRoleSingleton

The CustomRoleSingleton class is a singleton that gives you access to any custom role you registered with Mira. This will not give you a PLAYER's role, this is simply the INSTANCE of the role inside the RoleManager class. Example uses for this are getting the role's configuration, color, name, or the Chance and Count of the role.

It is used like this:

var role = CustomRoleSingleton<FreezerRole>.Instance;
Logger<MyPlugin>.Info($"Role Name: {role.RoleName}");
Logger<MyPlugin>.Info($"Role Color: {role.RoleColor}");
Logger<MyPlugin>.Info($"Role Chance: {role.GetChance()}");
Logger<MyPlugin>.Info($"Role Count: {role.GetCount()}");

RoleId

The RoleId class is a utility class that helps you get the id as a ushort of a role. The base game uses IDs in various locations related to roles, so this class is useful for converting your custom role to an ID. You will likely have to cast the ushort returned by this class to a RoleTypes enum.

RoleId provides two methods to get an ID:

  • Get<T>() - Gets the ID of a role as a type parameter.
  • Get(Type type) - Gets the ID of a role by its type object.

Example usage:

var roleID = RoleId.Get<FreezerRole>();
var roleType = (RoleTypes)roleID;
RoleManager.Instance.SetRole(somePlayer, roleType); // Set the role of somePlayer to the FreezerRole using the ID.

ICustomRole Interface

The ICustomRole interface contains various properties and methods that can be implemented to customize your role.

Keep in mind that since custom roles are required to inherit from the vanilla RoleBehaviour class, you can also override any of the methods from RoleBehaviour to further customize your role.

The following properties can be implemented to customize your role:

Property Type Required Default Value Description
RoleName string Yes None The name of the role.
RoleDescription string Yes None A short description of the role.
RoleLongDescription string Yes None A longer description of the role.
RoleColor UnityEngine.Color Yes None The color of the role.
OptionsMenuColor UnityEngine.Color No RoleColor The color of the role in the options menu.
Team ModdedRoleTeams Yes None The team of the role.
Configuration CustomRoleConfiguration Yes None The configuration of the role.
RoleOptionGroup RoleOptionsGroup No Based on team. The group this role should be placed with in the role settings.
IntroConfiguration TeamIntroConfiguration No Based on team. Defines custom parameters for the Team part of the IntroCutscene.

The following methods exist to customize and interact with your role:

Method Signature Required Default Behavior Description
void BindConfig(ConfigFile config) No Binds the configuration options for this role to the provided ConfigFile.
void SaveToPreset(ConfigFile presetConfig, bool useDefault=false) No Saves the role's configuration to a preset ConfigFile.
void LoadFromPreset(ConfigFile presetConfig) No Loads the role's configuration from a preset ConfigFile.
int? GetChance() No Returns the role chance option as set in the config file for your plugin by Mira. Get the chance from 0-100 for this role to appear in role selection.
int? GetCount() No Returns the role count option as set in the config file for your plugin by Mira. Get the amount of players who should receive this role.
void SetChance(int chance) No Sets the role chance option in your plugin's config file. Set the chance for this role to appear in role selection.
void SetCount(int count) No Sets the role count option in your plugin's config file. Set the amount of players who should receive this role.
bool CanLocalPlayerSeeRole(PlayerControl player) No Impostors can see other impostors, but other players only see white. Determines whether the local player should see the role color.
bool SetupIntroTeam(IntroCutscene instance, ref Il2CppSystem.Collections.Generic.List<PlayerControl> yourTeam) No Use vanilla team setup, except for "custom team" roles, which will display alone. Set up the players who are visible in the intro sequence.
void HudUpdate(HudManager hudManager) No None Runs on the HudManager.Update method for the LOCAL player only!
string? GetCustomEjectionMessage(NetworkedPlayerInfo player) No Returns $"{player.PlayerName} was The {this.RoleName}" if the role is an Impostor role. Otherwise returns null. Gets a custom ejection message for when a player with this role is voted out.
StringBuilder SetTabText() No Returns Helpers.CreateForThisRole(this) Gets a StringBuilder to get the text for this role on the role tab.
bool IsModifierApplicable(BaseModifier modifier) No Returns true. Checks if a given modifier is applicable to this role.

CustomRoleConfiguration Struct

Property Type Default Value Description
MaxRoleCount int 15 Gets the hard limit of players that can have this role. This property is used to set a limit in the Role Options menu. If set to 0, the role will not be assigned at start.
DefaultRoleCount int 0 Gets the default number of players that will have this role.
DefaultChance int 0 Gets the default chance of this role being assigned to a player.
CanModifyChance bool true Whether the chance of this role being assigned to a player can be modified in the Role Options menu.
OptionsScreenshot LoadableAsset<Sprite>? null Gets the sprite used for the screenshot that will be displayed in the settings menu.
Icon LoadableAsset<Sprite>? null Gets the sprite used for the role's icon.
IntroSound LoadableAsset<AudioClip>? null Gets the AudioClip used for the role sequence in the intro cutscene.
AffectedByLightOnAirship bool Team == Crewmate Whether the role is affected by light effects on Airship.
CanGetKilled bool Team == Crewmate Whether the role can be killed by the vanilla murder system.
UseVanillaKillButton bool Team == Impostor Whether the role can use the vanilla kill button.
KillButtonOutlineColor UnityEngine.Color Palette.ImpostorRed for Impostor, Palette.CrewmateBlue for Crewmate, RoleColor for Neutrals Gets the Outline Color for kill button if the Vanilla Kill button is being used.
CanUseVent bool Team == Impostor Whether the role is able to use vents.
CanUseSabotage bool Team == Impostor Whether the role is able to sabotage.
TasksCountForProgress bool Team == Crewmate Whether the role's tasks count towards task progress.
HideSettings bool RoleBehaviour.IsDead == True Whether the role should be hidden in the role settings menu.
ShowInFreeplay bool RoleBehaviour.IsDead == False Whether the role should be shown in the freeplay menu.
RoleHintType RoleHintType RoleHintType.RoleTab The type of hint that should be displayed for this role. See RoleHintType for more info.
GhostRole RoleTypes Team == Crewmate ? CrewmateGhost : ImpostorGhost The RoleTypes/RoleId of the Ghost Role that this Role should become on death.

Clone this wiki locally