diff --git a/MiraAPI/Events/Vanilla/Gameplay/BeforeRoundStartEvent.cs b/MiraAPI/Events/Vanilla/Gameplay/BeforeRoundStartEvent.cs new file mode 100644 index 0000000..f9d41ee --- /dev/null +++ b/MiraAPI/Events/Vanilla/Gameplay/BeforeRoundStartEvent.cs @@ -0,0 +1,21 @@ +namespace MiraAPI.Events.Vanilla.Gameplay; + +/// +/// Event invoked on IntroCutscene.OnDestroy and ExileController.WrapUp to determine if it should run the round event or not. +/// +public class BeforeRoundStartEvent : MiraCancelableEvent +{ + /// + /// Gets a value indicating whether the event was triggered by the IntroCutscene or ExileController. + /// + public bool TriggeredByIntro { get; } + + /// + /// Initializes a new instance of the class. + /// + /// Whether the event was triggered by the intro or not. + public BeforeRoundStartEvent(bool triggeredByIntro) + { + TriggeredByIntro = triggeredByIntro; + } +} diff --git a/MiraAPI/Events/Vanilla/Gameplay/RoundStartEvent.cs b/MiraAPI/Events/Vanilla/Gameplay/RoundStartEvent.cs index a50fde5..470f85a 100644 --- a/MiraAPI/Events/Vanilla/Gameplay/RoundStartEvent.cs +++ b/MiraAPI/Events/Vanilla/Gameplay/RoundStartEvent.cs @@ -1,7 +1,7 @@ namespace MiraAPI.Events.Vanilla.Gameplay; /// -/// Start Round event, invoked on IntroCutscene.OnDestroy and ExileController.WrapUp. +/// Start Round event, invoked on IntroCutscene.OnDestroy and ExileController.WrapUp if the event isn't cancelled. /// public class RoundStartEvent : MiraEvent { diff --git a/MiraAPI/Patches/Events/SpawnInMinigamePatch.cs b/MiraAPI/Patches/Events/SpawnInMinigamePatch.cs index b726999..65768d4 100644 --- a/MiraAPI/Patches/Events/SpawnInMinigamePatch.cs +++ b/MiraAPI/Patches/Events/SpawnInMinigamePatch.cs @@ -9,7 +9,12 @@ internal static class SpawnInMinigamePatch { public static void Postfix() { - var @event = new RoundStartEvent(false); + var @event = new BeforeRoundStartEvent(false); MiraEventManager.InvokeEvent(@event); + + if (@event.IsCancelled) return; + + var @event2 = new RoundStartEvent(false); + MiraEventManager.InvokeEvent(@event2); } } diff --git a/MiraAPI/Patches/Events/SubmergedSpawnGamePatch.cs b/MiraAPI/Patches/Events/SubmergedSpawnGamePatch.cs index d2664b9..07c358a 100644 --- a/MiraAPI/Patches/Events/SubmergedSpawnGamePatch.cs +++ b/MiraAPI/Patches/Events/SubmergedSpawnGamePatch.cs @@ -25,7 +25,12 @@ internal static class SubmergedSpawnGamePatch public static void Postfix() { - var @event = new RoundStartEvent(false); + var @event = new BeforeRoundStartEvent(false); MiraEventManager.InvokeEvent(@event); + + if (@event.IsCancelled) return; + + var @event2 = new RoundStartEvent(false); + MiraEventManager.InvokeEvent(@event2); } } diff --git a/MiraAPI/Patches/IntroCutscenePatches.cs b/MiraAPI/Patches/IntroCutscenePatches.cs index d068f26..af7ce8c 100644 --- a/MiraAPI/Patches/IntroCutscenePatches.cs +++ b/MiraAPI/Patches/IntroCutscenePatches.cs @@ -61,6 +61,11 @@ public static class IntroCutscenePatches public static void GameBeginPatch(IntroCutscene __instance) { MiraEventManager.InvokeEvent(new IntroEndEvent(__instance)); + + var @event = new BeforeRoundStartEvent(true); + MiraEventManager.InvokeEvent(@event); + + if (@event.IsCancelled) return; MiraEventManager.InvokeEvent(new RoundStartEvent(true)); } } diff --git a/MiraAPI/Patches/Roles/EjectionPatches.cs b/MiraAPI/Patches/Roles/EjectionPatches.cs index 85641eb..009da27 100644 --- a/MiraAPI/Patches/Roles/EjectionPatches.cs +++ b/MiraAPI/Patches/Roles/EjectionPatches.cs @@ -38,8 +38,13 @@ internal static class EjectionPatches { public static void Postfix() { - var @event = new RoundStartEvent(false); + var @event = new BeforeRoundStartEvent(false); MiraEventManager.InvokeEvent(@event); + + if (@event.IsCancelled) return; + + var @event2 = new RoundStartEvent(false); + MiraEventManager.InvokeEvent(@event2); } } } diff --git a/MiraAPI/Utilities/Extensions.cs b/MiraAPI/Utilities/Extensions.cs index 5fbc671..95a6692 100644 --- a/MiraAPI/Utilities/Extensions.cs +++ b/MiraAPI/Utilities/Extensions.cs @@ -513,7 +513,7 @@ public static class Extensions /// Whether impostors should be included in the search. /// The radius to search within. /// Whether colliders should be ignored when searching. - /// Determines if Ghosts are included + /// Determines if Ghosts are included. /// Optional predicate to test if the object is valid. /// The closest player if there is one, false otherwise. public static PlayerControl? GetClosestPlayer(