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); + } } }