From 14ce0202087017ea5badf13147a249119d49c1d3 Mon Sep 17 00:00:00 2001 From: Atony <75191600+AtonyGit@users.noreply.github.com> Date: Wed, 12 Aug 2026 21:14:50 -0500 Subject: [PATCH 1/2] Hide modifier spawning on non-dev builds --- MiraAPI/Modifiers/ModifierManager.cs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/MiraAPI/Modifiers/ModifierManager.cs b/MiraAPI/Modifiers/ModifierManager.cs index c2688a0..28faa8b 100644 --- a/MiraAPI/Modifiers/ModifierManager.cs +++ b/MiraAPI/Modifiers/ModifierManager.cs @@ -136,7 +136,10 @@ public static class ModifierManager var validPlayers = plrs.Where(x => IsGameModifierValid(x, modifier, modifier.TypeId)).ToList(); if (validPlayers.Count == 0) { - Warning($"No valid players for modifier {modifier.ModifierName}"); + if (MiraApiPlugin.IsDevBuild) + { + Warning($"No valid players for modifier {modifier.ModifierName}"); + } continue; } @@ -157,15 +160,23 @@ public static class ModifierManager if (candidates.Count == 0) { - Warning( - $"No available players for modifier {modifier.ModifierName} at assignment {i + 1}"); + if (MiraApiPlugin.IsDevBuild) + { + Warning( + $"No available players for modifier {modifier.ModifierName} at assignment {i + 1}"); + } + break; } var plr = candidates.Random(); if (plr == null) { - Warning($"Valid player for modifier {modifier.ModifierName} disappeared"); + if (MiraApiPlugin.IsDevBuild) + { + Warning($"Valid player for modifier {modifier.ModifierName} disappeared"); + } + continue; } From abb6f3d161aa4ecf0caa1ce8cf2f2f08d891fbf1 Mon Sep 17 00:00:00 2001 From: Atony <75191600+AtonyGit@users.noreply.github.com> Date: Wed, 12 Aug 2026 23:22:55 -0500 Subject: [PATCH 2/2] Add better murder event data --- .../Vanilla/Gameplay/AfterMurderEvent.cs | 64 +++++++++++++++++-- .../Vanilla/Gameplay/BeforeMurderEvent.cs | 59 +++++++++++++++++ 2 files changed, 119 insertions(+), 4 deletions(-) diff --git a/MiraAPI/Events/Vanilla/Gameplay/AfterMurderEvent.cs b/MiraAPI/Events/Vanilla/Gameplay/AfterMurderEvent.cs index 8b85622..8db74b9 100644 --- a/MiraAPI/Events/Vanilla/Gameplay/AfterMurderEvent.cs +++ b/MiraAPI/Events/Vanilla/Gameplay/AfterMurderEvent.cs @@ -16,20 +16,76 @@ public class AfterMurderEvent : MiraEvent public PlayerControl Target { get; } /// - /// Gets the 's , if it exists. + /// Gets the that was framed, if any. + /// + public PlayerControl? Framed { get; } + + /// + /// Gets a value indicating whether the murder was done indirectly. + /// This is commonly used to prevent the from being killed. + /// + public bool IsIndirectAttack { get; } + + /// + /// Gets a value indicating whether the murder was able to bypass protective roles or general defense, such as . + /// + public bool IgnoreDefense { get; } + + /// + /// Gets the 's , if it exists. /// public DeadBody? DeadBody { get; } /// /// Initializes a new instance of the class. /// - /// The killer. - /// The killed . - /// The 's , if it exists. + /// The that killed the . + /// The that was killed. + /// The 's , if it exists. + /// Whether the murder was caused indirectly. + /// Whether the murder ignored protection. + public AfterMurderEvent(PlayerControl source, PlayerControl target, DeadBody? deadBody, bool isIndirect, bool ignoreDefense = false) + { + Source = source; + Target = target; + Framed = null; + DeadBody = deadBody; + IsIndirectAttack = isIndirect; + IgnoreDefense = ignoreDefense; + } + + /// + /// Initializes a new instance of the class. + /// + /// The that killed the . + /// The that was killed. + /// The that was framed. + /// The 's , if it exists. + /// Whether the murder was caused indirectly. + /// Whether the murder ignored protection. + public AfterMurderEvent(PlayerControl source, PlayerControl target, PlayerControl framed, DeadBody? deadBody, bool isIndirect = true, bool ignoreDefense = false) + { + Source = source; + Target = target; + Framed = framed; + DeadBody = deadBody; + IsIndirectAttack = isIndirect; + IgnoreDefense = ignoreDefense; + } + + /// + /// Initializes a new instance of the class. + /// + /// The that killed the . + /// The that was killed. + /// The 's , if it exists. public AfterMurderEvent(PlayerControl source, PlayerControl target, DeadBody? deadBody) { Source = source; Target = target; + Framed = null; DeadBody = deadBody; + IsIndirectAttack = false; + IgnoreDefense = false; } } diff --git a/MiraAPI/Events/Vanilla/Gameplay/BeforeMurderEvent.cs b/MiraAPI/Events/Vanilla/Gameplay/BeforeMurderEvent.cs index cc07e21..8a770dc 100644 --- a/MiraAPI/Events/Vanilla/Gameplay/BeforeMurderEvent.cs +++ b/MiraAPI/Events/Vanilla/Gameplay/BeforeMurderEvent.cs @@ -17,11 +17,64 @@ public sealed class BeforeMurderEvent : MiraCancelableEvent /// public PlayerControl Target { get; } + /// + /// Gets the that is being framed, if any. + /// + public PlayerControl? Framed { get; } + + /// + /// Gets a value indicating whether the murder is done indirectly. + /// This is commonly used to prevent the from being killed. + /// + public bool IsIndirectAttack { get; } + + /// + /// Gets a value indicating whether the murder should bypass protective roles or general defense, such as . + /// + public bool IgnoreDefense { get; } + /// /// Gets whether the murder was meant to be done in a meeting, via an enum. /// public MeetingCheck InMeeting { get; } + /// + /// Initializes a new instance of the class. + /// + /// The that is killing the . + /// The that is being killed. + /// Whether the murder is caused indirectly. + /// Whether the murder should ignore protection. + /// Whether the murder is intended to be triggered in a meeting. + public BeforeMurderEvent(PlayerControl source, PlayerControl target, bool isIndirect, bool ignoreDefense = false, MeetingCheck inMeeting = MeetingCheck.Ignore) + { + Source = source; + Target = target; + Framed = null; + IsIndirectAttack = isIndirect; + IgnoreDefense = ignoreDefense; + InMeeting = inMeeting; + } + + /// + /// Initializes a new instance of the class. + /// + /// The that is killing the . + /// The that is being killed. + /// The that is being framed. + /// Whether the murder is caused indirectly. + /// Whether the murder should ignore protection. + /// Whether the murder is intended to be triggered in a meeting. + public BeforeMurderEvent(PlayerControl source, PlayerControl target, PlayerControl framed, bool isIndirect = true, bool ignoreDefense = false, MeetingCheck inMeeting = MeetingCheck.Ignore) + { + Source = source; + Target = target; + Framed = framed; + IsIndirectAttack = isIndirect; + IgnoreDefense = ignoreDefense; + InMeeting = inMeeting; + } + /// /// Initializes a new instance of the class. /// @@ -32,6 +85,9 @@ public sealed class BeforeMurderEvent : MiraCancelableEvent { Source = source; Target = target; + Framed = null; + IsIndirectAttack = false; + IgnoreDefense = false; InMeeting = inMeeting; } @@ -44,6 +100,9 @@ public sealed class BeforeMurderEvent : MiraCancelableEvent { Source = source; Target = target; + Framed = null; + IsIndirectAttack = false; + IgnoreDefense = false; InMeeting = MeetingCheck.Ignore; } }