diff --git a/EXILED/Exiled.Events/EventArgs/Server/RoundStartingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Server/RoundStartingEventArgs.cs
new file mode 100644
index 000000000..b97f309ed
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Server/RoundStartingEventArgs.cs
@@ -0,0 +1,62 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Server
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ using Exiled.Events.EventArgs.Interfaces;
+
+ ///
+ /// Contains all information before the start of a round.
+ ///
+ public class RoundStartingEventArgs : IDeniableEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public RoundStartingEventArgs(short timeLeft, short originalTimeLeft, int topPlayer, int playerCount)
+ {
+ TimeLeft = timeLeft;
+ OriginalTimeLeft = originalTimeLeft;
+ TopPlayer = topPlayer;
+ PlayerCount = playerCount;
+ IsAllowed = TimeLeft == -1;
+ }
+
+ ///
+ /// Gets or sets the time before the start of the Round.
+ ///
+ public int TimeLeft { get; set; }
+
+ ///
+ /// Gets or sets the time before the start of the Round.
+ ///
+ public int OriginalTimeLeft { get; set; }
+
+ ///
+ /// Gets or sets the maximum number of Player on the server since restart.
+ ///
+ public int TopPlayer { get; set; }
+
+ ///
+ /// Gets the number of Player.
+ ///
+ public int PlayerCount { get; }
+
+ ///
+ public bool IsAllowed { get; set; }
+ }
+}
diff --git a/EXILED/Exiled.Events/Handlers/Server.cs b/EXILED/Exiled.Events/Handlers/Server.cs
index 80453625b..caef937bf 100644
--- a/EXILED/Exiled.Events/Handlers/Server.cs
+++ b/EXILED/Exiled.Events/Handlers/Server.cs
@@ -32,6 +32,11 @@ public static class Server
///
public static Event RoundStarted { get; set; } = new();
+ ///
+ /// Invoked after the start of a new round.
+ ///
+ public static Event RoundStarting { get; set; } = new();
+
///
/// Invoked after all players have spawned at the start of a new round.
///
@@ -137,6 +142,12 @@ public static class Server
///
public static void OnWaitingForPlayers() => WaitingForPlayers.InvokeSafely();
+ ///
+ /// Called before the start of a new round.
+ ///
+ /// The instance.
+ public static void OnRoundStarting(RoundStartingEventArgs ev) => RoundStarting.InvokeSafely(ev);
+
///
/// Called after the start of a new round.
///
diff --git a/EXILED/Exiled.Events/Patches/Events/Server/RoundStarting.cs b/EXILED/Exiled.Events/Patches/Events/Server/RoundStarting.cs
new file mode 100644
index 000000000..ec5e68b95
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Events/Server/RoundStarting.cs
@@ -0,0 +1,118 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Events.Server
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Reflection;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features;
+ using Exiled.API.Features.Pools;
+ using Exiled.Events.EventArgs.Server;
+ using HarmonyLib;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patches .
+ /// Adds the event.
+ ///
+ [HarmonyPatch]
+ internal class RoundStarting
+ {
+ #pragma warning disable SA1600 // Elements should be documented
+ public static Type PrivateType { get; internal set; }
+
+ private static MethodInfo TargetMethod()
+ {
+ PrivateType = typeof(CharacterClassManager).GetNestedTypes(all)
+ .FirstOrDefault(currentType => currentType.Name.Contains("Init"));
+ if (PrivateType == null)
+ throw new Exception("State machine type for Init not found.");
+ MethodInfo moveNextMethod = PrivateType.GetMethod("MoveNext", all);
+
+ if (moveNextMethod == null)
+ throw new Exception("MoveNext method not found in the state machine type.");
+ return moveNextMethod;
+ }
+
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ const string TimeLeft = "5__3";
+ const string OriginalTimeLeft = "5__2";
+ const string TopPlayer = "5__4";
+
+ LocalBuilder ev = generator.DeclareLocal(typeof(RoundStartingEventArgs));
+ int offset = -4;
+ int index = newInstructions.FindLastIndex(x => x.Calls(Method(typeof(CharacterClassManager), nameof(CharacterClassManager.ForceRoundStart)))) + offset;
+
+ List