From 1a53e2b045e9fa051a58d2d638a69d261016433d Mon Sep 17 00:00:00 2001
From: XtraCube <72575280+XtraCube@users.noreply.github.com>
Date: Sat, 29 Mar 2025 21:39:44 -0400
Subject: [PATCH 1/3] add new meeting and intro events
---
.../Events/Vanilla/Gameplay/IntroEndEvent.cs | 12 ++++++++++++
.../Events/Vanilla/Meeting/EndMeetingEvent.cs | 12 ++++++++++++
.../Meeting/Voting/VotingCompleteEvent.cs | 13 +++++++++++++
MiraAPI/Patches/IntroCutscenePatches.cs | 7 +++----
MiraAPI/Patches/Voting/MeetingHudPatches.cs | 18 +++++++++++++++++-
5 files changed, 57 insertions(+), 5 deletions(-)
create mode 100644 MiraAPI/Events/Vanilla/Gameplay/IntroEndEvent.cs
create mode 100644 MiraAPI/Events/Vanilla/Meeting/EndMeetingEvent.cs
create mode 100644 MiraAPI/Events/Vanilla/Meeting/Voting/VotingCompleteEvent.cs
diff --git a/MiraAPI/Events/Vanilla/Gameplay/IntroEndEvent.cs b/MiraAPI/Events/Vanilla/Gameplay/IntroEndEvent.cs
new file mode 100644
index 0000000..b27bcec
--- /dev/null
+++ b/MiraAPI/Events/Vanilla/Gameplay/IntroEndEvent.cs
@@ -0,0 +1,12 @@
+namespace MiraAPI.Events.Vanilla.Gameplay;
+
+///
+/// The event that is invoked when the intro cutscene has finished playing.
+///
+public class IntroEndEvent(IntroCutscene introCutscene) : MiraEvent
+{
+ ///
+ /// Gets the instance of the IntroCutscene.
+ ///
+ public IntroCutscene IntroCutscene { get; } = introCutscene;
+}
diff --git a/MiraAPI/Events/Vanilla/Meeting/EndMeetingEvent.cs b/MiraAPI/Events/Vanilla/Meeting/EndMeetingEvent.cs
new file mode 100644
index 0000000..55cdae9
--- /dev/null
+++ b/MiraAPI/Events/Vanilla/Meeting/EndMeetingEvent.cs
@@ -0,0 +1,12 @@
+namespace MiraAPI.Events.Vanilla.Meeting;
+
+///
+/// The event that is invoked when the meeting has ended.
+///
+public class EndMeetingEvent(MeetingHud meetingHud) : MiraEvent
+{
+ ///
+ /// Gets the MeetingHud instance.
+ ///
+ public MeetingHud MeetingHud { get; } = meetingHud;
+}
diff --git a/MiraAPI/Events/Vanilla/Meeting/Voting/VotingCompleteEvent.cs b/MiraAPI/Events/Vanilla/Meeting/Voting/VotingCompleteEvent.cs
new file mode 100644
index 0000000..5f782bf
--- /dev/null
+++ b/MiraAPI/Events/Vanilla/Meeting/Voting/VotingCompleteEvent.cs
@@ -0,0 +1,13 @@
+namespace MiraAPI.Events.Vanilla.Meeting.Voting;
+
+///
+/// The event that is invoked when the voting phase of a meeting is complete.
+///
+/// The MeetingHud instance.
+public class VotingCompleteEvent(MeetingHud meetingHud) : MiraEvent
+{
+ ///
+ /// Gets the MeetingHud instance.
+ ///
+ public MeetingHud MeetingHud { get; } = meetingHud;
+}
diff --git a/MiraAPI/Patches/IntroCutscenePatches.cs b/MiraAPI/Patches/IntroCutscenePatches.cs
index fb6144a..28c576f 100644
--- a/MiraAPI/Patches/IntroCutscenePatches.cs
+++ b/MiraAPI/Patches/IntroCutscenePatches.cs
@@ -56,11 +56,10 @@ public static class IntroCutscenePatches
}
}
- /*
[HarmonyPostfix]
[HarmonyPatch(nameof(IntroCutscene.OnDestroy))]
- public static void GameBeginPatch()
+ public static void GameBeginPatch(IntroCutscene __instance)
{
- CustomGameModeManager.ActiveMode?.Initialize();
- }*/
+ MiraEventManager.InvokeEvent(new IntroEndEvent(__instance));
+ }
}
diff --git a/MiraAPI/Patches/Voting/MeetingHudPatches.cs b/MiraAPI/Patches/Voting/MeetingHudPatches.cs
index 6070b1e..337a5f7 100644
--- a/MiraAPI/Patches/Voting/MeetingHudPatches.cs
+++ b/MiraAPI/Patches/Voting/MeetingHudPatches.cs
@@ -1,4 +1,5 @@
-using System.Linq;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MiraAPI.Events;
@@ -10,6 +11,7 @@ using MiraAPI.Voting;
namespace MiraAPI.Patches.Voting;
[HarmonyPatch(typeof(MeetingHud))]
+[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Harmony Convention")]
internal static class MeetingHudPatches
{
[HarmonyPostfix]
@@ -31,6 +33,20 @@ internal static class MeetingHudPatches
MiraEventManager.InvokeEvent(@event);
}
+ [HarmonyPostfix]
+ [HarmonyPatch(nameof(MeetingHud.OnDestroy))]
+ public static void MeetingHudOnDestroyPatch(MeetingHud __instance)
+ {
+ MiraEventManager.InvokeEvent(new EndMeetingEvent(__instance));
+ }
+
+ [HarmonyPostfix]
+ [HarmonyPatch(nameof(MeetingHud.VotingComplete))]
+ public static void MeetingHudVotingCompletePatch(MeetingHud __instance)
+ {
+ MiraEventManager.InvokeEvent(new VotingCompleteEvent(__instance));
+ }
+
[HarmonyPrefix]
[HarmonyPatch(nameof(MeetingHud.Select))]
public static bool SelectPatch(MeetingHud __instance, int suspectStateIdx)
From 31132e6e657ab5e1b8a9aa0bf5908d883369b672 Mon Sep 17 00:00:00 2001
From: XtraCube <72575280+XtraCube@users.noreply.github.com>
Date: Sat, 29 Mar 2025 21:51:31 -0400
Subject: [PATCH 2/3] add RoundStartEvent.cs
---
.../Vanilla/Gameplay/RoundStartEvent.cs | 21 +++++++++++++++++++
MiraAPI/Patches/IntroCutscenePatches.cs | 1 +
MiraAPI/Patches/Roles/EjectionPatches.cs | 9 ++++++++
3 files changed, 31 insertions(+)
create mode 100644 MiraAPI/Events/Vanilla/Gameplay/RoundStartEvent.cs
diff --git a/MiraAPI/Events/Vanilla/Gameplay/RoundStartEvent.cs b/MiraAPI/Events/Vanilla/Gameplay/RoundStartEvent.cs
new file mode 100644
index 0000000..a50fde5
--- /dev/null
+++ b/MiraAPI/Events/Vanilla/Gameplay/RoundStartEvent.cs
@@ -0,0 +1,21 @@
+namespace MiraAPI.Events.Vanilla.Gameplay;
+
+///
+/// Start Round event, invoked on IntroCutscene.OnDestroy and ExileController.WrapUp.
+///
+public class RoundStartEvent : MiraEvent
+{
+ ///
+ /// 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 RoundStartEvent(bool triggeredByIntro)
+ {
+ TriggeredByIntro = triggeredByIntro;
+ }
+}
diff --git a/MiraAPI/Patches/IntroCutscenePatches.cs b/MiraAPI/Patches/IntroCutscenePatches.cs
index 28c576f..d068f26 100644
--- a/MiraAPI/Patches/IntroCutscenePatches.cs
+++ b/MiraAPI/Patches/IntroCutscenePatches.cs
@@ -61,5 +61,6 @@ public static class IntroCutscenePatches
public static void GameBeginPatch(IntroCutscene __instance)
{
MiraEventManager.InvokeEvent(new IntroEndEvent(__instance));
+ MiraEventManager.InvokeEvent(new RoundStartEvent(true));
}
}
diff --git a/MiraAPI/Patches/Roles/EjectionPatches.cs b/MiraAPI/Patches/Roles/EjectionPatches.cs
index 48d6abb..be8ef41 100644
--- a/MiraAPI/Patches/Roles/EjectionPatches.cs
+++ b/MiraAPI/Patches/Roles/EjectionPatches.cs
@@ -1,5 +1,6 @@
using HarmonyLib;
using MiraAPI.Events;
+using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Events.Vanilla.Meeting;
using MiraAPI.Roles;
@@ -31,4 +32,12 @@ public static class EjectionPatches
__instance.completeString = role.GetCustomEjectionMessage(__instance.initData.networkedPlayer);
}
+
+ [HarmonyPostfix]
+ [HarmonyPatch(nameof(ExileController.WrapUp))]
+ public static void WrapUpPostfix(ExileController __instance)
+ {
+ var @event = new RoundStartEvent(false);
+ MiraEventManager.InvokeEvent(@event);
+ }
}
From 3cd7acbc70934b3e16f6636433f0c9da5535acfd Mon Sep 17 00:00:00 2001
From: XtraCube <72575280+XtraCube@users.noreply.github.com>
Date: Sat, 29 Mar 2025 22:07:12 -0400
Subject: [PATCH 3/3] fix ejection patch for submerged and airship
---
MiraAPI/Patches/Roles/EjectionPatches.cs | 26 ++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/MiraAPI/Patches/Roles/EjectionPatches.cs b/MiraAPI/Patches/Roles/EjectionPatches.cs
index be8ef41..a7861df 100644
--- a/MiraAPI/Patches/Roles/EjectionPatches.cs
+++ b/MiraAPI/Patches/Roles/EjectionPatches.cs
@@ -1,4 +1,6 @@
-using HarmonyLib;
+using System.Collections.Generic;
+using System.Reflection;
+using HarmonyLib;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Events.Vanilla.Meeting;
@@ -33,11 +35,23 @@ public static class EjectionPatches
__instance.completeString = role.GetCustomEjectionMessage(__instance.initData.networkedPlayer);
}
- [HarmonyPostfix]
- [HarmonyPatch(nameof(ExileController.WrapUp))]
- public static void WrapUpPostfix(ExileController __instance)
+ [HarmonyPatch]
+ internal static class WrapUpPatch
{
- var @event = new RoundStartEvent(false);
- MiraEventManager.InvokeEvent(@event);
+ public static IEnumerable TargetMethods()
+ {
+ yield return AccessTools.Method(typeof(ExileController), nameof(ExileController.WrapUp));
+ yield return AccessTools.Method(typeof(AirshipExileController), nameof(AirshipExileController.WrapUpAndSpawn));
+ if (AccessTools.TypeByName("Submerged.ExileCutscene.SubmergedExileController") is { } type)
+ {
+ yield return AccessTools.Method(type, "WrapUpAndSpawn");
+ }
+ }
+
+ public static void Postfix()
+ {
+ var @event = new RoundStartEvent(false);
+ MiraEventManager.InvokeEvent(@event);
+ }
}
}