-
Notifications
You must be signed in to change notification settings - Fork 23
Custom Roles
Roles are straightforward in Mira API. There are two things you need to do to create a custom role:
- Create a class that inherits from a base game role (like
CrewmateRole,ImpostorRole, etc.) - Implement the
ICustomRoleinterface from Mira API. - 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.
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:

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
}
}Mira API provides a few utilities to help you with your role development.
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()}");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.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. |
| 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. |