Skip to content

Game Over

XtraCube edited this page Feb 27, 2026 · 1 revision

Custom game overs let you define your own win conditions that trigger the end-game screen with a custom reason. Mira assigns each registered game over a unique GameOverReason ID extending beyond the vanilla enum values, and handles all the networking automatically.

Mira automatically registers any non-abstract class that inherits from CustomGameOver and has a parameterless constructor.

Creating a Custom Game Over

Create a class that inherits from CustomGameOver.

public class NeutralKillerGameOver : CustomGameOver
{
    public override bool VerifyCondition(PlayerControl playerControl, NetworkedPlayerInfo[] winners)
    {
        // Only trigger if the sole winner has the NeutralKillerRole.
        return winners is [{ Role: NeutralKillerRole }];
    }

    public override void AfterEndGameSetup(EndGameManager endGameManager)
    {
        endGameManager.WinText.text = "Outcast Killer Wins!";
        endGameManager.WinText.color = Color.magenta;
        endGameManager.BackgroundBar.material.SetColor(ShaderID.Color, Color.magenta);
    }
}

Triggering a Game Over

Call the static Trigger<T> method on CustomGameOver, passing the list of winning players. This sends an RPC to all clients, so it should only be called on the host.

// End the game with the NeutralKillerGameOver win condition.
CustomGameOver.Trigger<NeutralKillerGameOver>(winners);

The winners parameter is any IEnumerable<NetworkedPlayerInfo>.

CustomGameOver Members

Member Description
VerifyCondition(PlayerControl, NetworkedPlayerInfo[] winners) Called to confirm the win condition is valid. Return true to allow the game over. Defaults to true.
BeforeEndGameSetup(EndGameManager) Called before the vanilla end-game screen setup. Return false to skip the vanilla setup entirely. Defaults to true (runs vanilla).
AfterEndGameSetup(EndGameManager) Called after the vanilla end-game screen setup. Use this to customize win text and colors.
static Trigger<T>(IEnumerable<NetworkedPlayerInfo> winners) Sends the game over RPC. Call only on the host.
static GameOverReason<T>() Returns the GameOverReason enum value corresponding to the custom game over type T.
static Instance The CustomGameOver instance currently active on the end-game screen, or null if a vanilla reason caused the game to end.

CustomGameOver also has an implicit conversion to GameOverReason, so you can use a game over instance directly wherever a GameOverReason is expected.

GameOverManager

GameOverManager provides access to the registry of custom game overs.

Method Description
GameOverManager.GetGameOverId<T>() Returns the integer ID assigned to the custom game over type T.
GameOverManager.GetGameOverId(Type) Returns the integer ID for the given type.
GameOverManager.TryGetGameOver(int id, out CustomGameOver?) Creates a new instance of the game over registered with the given ID. Returns false if the ID is not found.

IDs start after the last value in the vanilla GameOverReason enum, so they never conflict with vanilla reasons.

GameOverData

GameOverData is an internal record struct used to transmit game over information over the network.

record struct GameOverData(int Reason, List<NetworkedPlayerInfo> Winners)

You do not need to use GameOverData directly; it is created and consumed internally when Trigger<T> is called.

Checking the Active Game Over

During the end-game screen, use CustomGameOver.Instance to access the active custom game over and distinguish it from vanilla endings:

[RegisterEvent]
public static void OnGameEnd(GameEndEvent @event)
{
    if (CustomGameOver.Instance is NeutralKillerGameOver)
    {
        Logger<MyPlugin>.Info("Neutral killer won!");
    }
}

Clone this wiki locally