From 6408f44818cc300010b4c37eef4ee1a67199a47a Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Mon, 23 Feb 2026 07:36:48 +0100 Subject: [PATCH 01/17] Exiled.Utility --- EXILED/EXILED.sln | 12 +- .../Commands/TpsCommand.cs | 2 +- EXILED/Exiled.Utility/Config.cs | 114 ++++++++++++++++++ EXILED/Exiled.Utility/Exiled.Utility.csproj | 57 +++++++++ EXILED/Exiled.Utility/Utility.cs | 93 ++++++++++++++ EXILED/build.ps1 | 1 + 6 files changed, 276 insertions(+), 3 deletions(-) rename EXILED/{Exiled.Events => Exiled.Utility}/Commands/TpsCommand.cs (97%) create mode 100644 EXILED/Exiled.Utility/Config.cs create mode 100644 EXILED/Exiled.Utility/Exiled.Utility.csproj create mode 100644 EXILED/Exiled.Utility/Utility.cs diff --git a/EXILED/EXILED.sln b/EXILED/EXILED.sln index 60b7f5f72c..6c48410428 100644 --- a/EXILED/EXILED.sln +++ b/EXILED/EXILED.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.4.33205.214 +# Visual Studio Version 18 +VisualStudioVersion = 18.3.11512.155 d18.3 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Exiled.Events", "Exiled.Events\Exiled.Events.csproj", "{1E6C4350-5067-4CE7-91DB-6420D027A4FC}" EndProject @@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Exiled.CustomRoles", "Exile EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "docs", "docs\docs.csproj", "{BE130A80-6819-44C6-AA1B-BF068DEA67FF}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Exiled.Utility", "Exiled.Utility\Exiled.Utility.csproj", "{70A4E012-0DBB-18AA-A972-770281EEF726}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -82,6 +84,12 @@ Global {BE130A80-6819-44C6-AA1B-BF068DEA67FF}.Installer|Any CPU.Build.0 = Installer|Any CPU {BE130A80-6819-44C6-AA1B-BF068DEA67FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {BE130A80-6819-44C6-AA1B-BF068DEA67FF}.Release|Any CPU.Build.0 = Release|Any CPU + {70A4E012-0DBB-18AA-A972-770281EEF726}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {70A4E012-0DBB-18AA-A972-770281EEF726}.Debug|Any CPU.Build.0 = Debug|Any CPU + {70A4E012-0DBB-18AA-A972-770281EEF726}.Installer|Any CPU.ActiveCfg = Installer|Any CPU + {70A4E012-0DBB-18AA-A972-770281EEF726}.Installer|Any CPU.Build.0 = Installer|Any CPU + {70A4E012-0DBB-18AA-A972-770281EEF726}.Release|Any CPU.ActiveCfg = Release|Any CPU + {70A4E012-0DBB-18AA-A972-770281EEF726}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/EXILED/Exiled.Events/Commands/TpsCommand.cs b/EXILED/Exiled.Utility/Commands/TpsCommand.cs similarity index 97% rename from EXILED/Exiled.Events/Commands/TpsCommand.cs rename to EXILED/Exiled.Utility/Commands/TpsCommand.cs index 14c0def05e..dcbe781824 100644 --- a/EXILED/Exiled.Events/Commands/TpsCommand.cs +++ b/EXILED/Exiled.Utility/Commands/TpsCommand.cs @@ -5,7 +5,7 @@ // // ----------------------------------------------------------------------- -namespace Exiled.Events.Commands +namespace Exiled.Utility.Commands { using System; diff --git a/EXILED/Exiled.Utility/Config.cs b/EXILED/Exiled.Utility/Config.cs new file mode 100644 index 0000000000..886aef6da5 --- /dev/null +++ b/EXILED/Exiled.Utility/Config.cs @@ -0,0 +1,114 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Utility +{ + using System.ComponentModel; + + using API.Interfaces; + + /// + public sealed class Config : IConfig + { + /// + public bool IsEnabled { get; set; } = true; + + /// + public bool Debug { get; set; } + + /// + /// Gets or sets a value indicating whether events are only patched if they have delegates subscribed to them. + /// + [Description("Indicates whether events are patched only if they have delegates subscribed to them")] + public bool UseDynamicPatching { get; set; } = true; + + /// + /// Gets or sets a value indicating whether SCP-173 can be blocked by the tutorial. + /// + [Description("Indicates whether SCP-173 can be blocked by the tutorial")] + public bool CanTutorialBlockScp173 { get; set; } = true; + + /// + /// Gets or sets a value indicating whether SCP-096 can be triggered by the tutorial. + /// + [Description("Indicates whether SCP-096 can be triggered by the tutorial")] + public bool CanTutorialTriggerScp096 { get; set; } = true; + + /// + /// Gets or sets a value indicating whether SCP-049 can activate the sense ability on tutorials. + /// + [Description("Indicates whether SCP-049 can sense tutorial players")] + public bool CanScp049SenseTutorial { get; set; } = true; + + /// + /// Gets or sets a value indicating whether tutorial is affected by SCP-079 scan. + /// + [Description("Indicates whether tutorial is affected by SCP-079 scan.")] + public bool TutorialNotAffectedByScp079Scan { get; set; } = false; + + /// + /// Gets or sets a value indicating whether flashbangs flash original thrower. + /// + [Description("Indicates whether flashbangs flash original thrower.")] + public bool CanFlashbangsAffectThrower { get; set; } = false; + + /// + /// Gets or sets a value indicating whether the name tracking (invisible EXILED version string added to the end of the server name) is enabled or not. + /// + [Description("Indicates whether the name tracking (invisible EXILED version string added to the end of the server name) is enabled or not")] + public bool IsNameTrackingEnabled { get; set; } = true; + + /// + /// Gets or sets a value indicating whether the inventory should be dropped before being set as spectator, through commands or plugins. + /// + [Description("Indicates whether the inventory should be dropped before being set as spectator, through commands or plugins")] + public bool ShouldDropInventory { get; set; } = true; + + /// + /// Gets or sets a value indicating whether the blood can be spawned. + /// + [Description("Indicates whether the blood can be spawned")] + public bool CanSpawnBlood { get; set; } = true; + + /// + /// Gets or sets a value indicating whether keycard throw can affect basic doors. + /// + /// TODO: Make a poll about removing this config. (unimplemented since 9.6.0-beta7) + [Description("Indicates whether thrown keycards can affect doors that don't require any permissions")] + public bool CanKeycardThrowAffectDoors { get; set; } = false; + + /// + /// Gets or sets a value indicating whether the SCP079 will recontained if there are no SCPs left. + /// + [Description("Indicates whether the SCP079 will recontained if there are no SCPs left.")] + public bool RecontainScp079IfNoScpsLeft { get; set; } = true; + + /// + /// Gets or sets a value indicating whether configs has to be reloaded every time a round restarts. + /// + [Description("Indicates whether configs have to be reloaded every round restart")] + public bool ShouldReloadConfigsAtRoundRestart { get; set; } = false; + + /// + /// Gets or sets a value indicating whether translations has to be reloaded every time a round restarts. + /// + [Description("Indicates whether translations has to be reloaded every round restart")] + public bool ShouldReloadTranslationsAtRoundRestart { get; set; } = false; + + /// + /// Gets a value indicating whether bans should be logged. + /// + [Description("Indicates whether bans should be logged")] + public bool ShouldLogBans { get; private set; } = true; + + /// + /// Gets or sets a value indicating whether to log RA commands. + /// + [Description("Whether to log RA commands.")] + public bool LogRaCommands { get; set; } = true; + } +} diff --git a/EXILED/Exiled.Utility/Exiled.Utility.csproj b/EXILED/Exiled.Utility/Exiled.Utility.csproj new file mode 100644 index 0000000000..cca7e1e48a --- /dev/null +++ b/EXILED/Exiled.Utility/Exiled.Utility.csproj @@ -0,0 +1,57 @@ + + + + + Library + Exiled.Utility + true + Debug;Release;Installer + AnyCPU + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if not "$(EXILED_DEV_REFERENCES)"=="" copy /y "$(OutputPath)$(AssemblyName).dll" "$(EXILED_DEV_REFERENCES)\Plugins\" + + + if [[ ! -z "$EXILED_DEV_REFERENCES" ]]; then cp "$(OutputPath)$(AssemblyName).dll" "$EXILED_DEV_REFERENCES/Plugins/"; fi + + + diff --git a/EXILED/Exiled.Utility/Utility.cs b/EXILED/Exiled.Utility/Utility.cs new file mode 100644 index 0000000000..c0a6a24d15 --- /dev/null +++ b/EXILED/Exiled.Utility/Utility.cs @@ -0,0 +1,93 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Utility +{ + using System; + using System.Diagnostics; + + using API.Enums; + using API.Features; + using CentralAuth; + using Exiled.API.Features.Core.UserSettings; + using Exiled.Events.Features; + using HarmonyLib; + using InventorySystem.Items.Pickups; + using InventorySystem.Items.Usables; + using PlayerRoles.Ragdolls; + using PlayerRoles.RoleAssign; + + using Respawning; + using UnityEngine.SceneManagement; + using UserSettings.ServerSpecific; + + /// + /// Patch and unpatch events into the game. + /// + public sealed class Utility : Plugin + { + /// + /// Gets the plugin instance. + /// + public static Utility Instance { get; private set; } + + /// + /// Gets the Harmony instance. + /// + public static Harmony Harmony { get; private set; } + + /// + public override PluginPriority Priority { get; } = PluginPriority.Higher; + + /// + public override void OnEnabled() + { + Instance = this; + base.OnEnabled(); + + Stopwatch watch = Stopwatch.StartNew(); + + Patch(); + + watch.Stop(); + + Log.Info($"{(Config.UseDynamicPatching ? "Non-event" : "All")} patches completed in {watch.Elapsed}"); + + ServerConsole.ReloadServerName(); + } + + /// + public override void OnDisabled() + { + base.OnDisabled(); + + Unpatch(); + } + + /// + /// Patches all events. + /// + public void Patch() + { + Harmony = new Harmony($"com.{nameof(Utility)}.ExiledTeam-{DateTime.Now.Ticks}"); + GlobalPatchProcessor.PatchAll(Harmony, out int failedPatch); + if (failedPatch != 0) + Log.Error($"Patching failed! There are {failedPatch} broken patches."); + } + + /// + /// Unpatches all events. + /// + public void Unpatch() + { + Log.Debug("Unpatching events..."); + Harmony.UnpatchAll(Harmony.Id); + Harmony = null; + Log.Debug("All events have been unpatched complete. Goodbye!"); + } + } +} diff --git a/EXILED/build.ps1 b/EXILED/build.ps1 index 2b4f5a54c8..07b30ee294 100644 --- a/EXILED/build.ps1 +++ b/EXILED/build.ps1 @@ -9,6 +9,7 @@ $Projects = @( 'Exiled.API', 'Exiled.Permissions', 'Exiled.Events', + 'Exiled.Utility', 'Exiled.CreditTags', 'Exiled.Example', 'Exiled.CustomItems', From aefd9780b9b2b136f6060e281ac54bc91d31c852 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Mon, 23 Feb 2026 08:03:19 +0100 Subject: [PATCH 02/17] Move Scp079Recontain file into Utility --- EXILED/Exiled.Utility/Exiled.Utility.csproj | 5 ----- .../Generic => Exiled.Utility/Patches}/Scp079Recontain.cs | 6 +++--- 2 files changed, 3 insertions(+), 8 deletions(-) rename EXILED/{Exiled.Events/Patches/Generic => Exiled.Utility/Patches}/Scp079Recontain.cs (91%) diff --git a/EXILED/Exiled.Utility/Exiled.Utility.csproj b/EXILED/Exiled.Utility/Exiled.Utility.csproj index cca7e1e48a..323fecd1f6 100644 --- a/EXILED/Exiled.Utility/Exiled.Utility.csproj +++ b/EXILED/Exiled.Utility/Exiled.Utility.csproj @@ -42,11 +42,6 @@ - - - - - if not "$(EXILED_DEV_REFERENCES)"=="" copy /y "$(OutputPath)$(AssemblyName).dll" "$(EXILED_DEV_REFERENCES)\Plugins\" diff --git a/EXILED/Exiled.Events/Patches/Generic/Scp079Recontain.cs b/EXILED/Exiled.Utility/Patches/Scp079Recontain.cs similarity index 91% rename from EXILED/Exiled.Events/Patches/Generic/Scp079Recontain.cs rename to EXILED/Exiled.Utility/Patches/Scp079Recontain.cs index f92a59482f..3ce9e801dc 100644 --- a/EXILED/Exiled.Events/Patches/Generic/Scp079Recontain.cs +++ b/EXILED/Exiled.Utility/Patches/Scp079Recontain.cs @@ -5,7 +5,7 @@ // // ----------------------------------------------------------------------- -namespace Exiled.Events.Patches.Generic +namespace Exiled.Utility.Patches { using System.Collections.Generic; using System.Reflection.Emit; @@ -37,8 +37,8 @@ private static IEnumerable Transpiler(IEnumerable Date: Mon, 23 Feb 2026 08:03:32 +0100 Subject: [PATCH 03/17] more config stuff --- EXILED/Exiled.Events/Config.cs | 1 - .../Patches/Generic/Scp173BeingLooked.cs | 2 +- EXILED/Exiled.Utility/Config.cs | 68 +++++-------------- 3 files changed, 19 insertions(+), 52 deletions(-) diff --git a/EXILED/Exiled.Events/Config.cs b/EXILED/Exiled.Events/Config.cs index fd244f699b..56a8206e74 100644 --- a/EXILED/Exiled.Events/Config.cs +++ b/EXILED/Exiled.Events/Config.cs @@ -77,7 +77,6 @@ public sealed class Config : IConfig /// /// Gets or sets a value indicating whether keycard throw can affect basic doors. /// - /// TODO: Make a poll about removing this config. (unimplemented since 9.6.0-beta7) [Description("Indicates whether thrown keycards can affect doors that don't require any permissions")] public bool CanKeycardThrowAffectDoors { get; set; } = false; diff --git a/EXILED/Exiled.Events/Patches/Generic/Scp173BeingLooked.cs b/EXILED/Exiled.Events/Patches/Generic/Scp173BeingLooked.cs index aadad0c087..763b23f88c 100644 --- a/EXILED/Exiled.Events/Patches/Generic/Scp173BeingLooked.cs +++ b/EXILED/Exiled.Events/Patches/Generic/Scp173BeingLooked.cs @@ -69,7 +69,7 @@ private static IEnumerable Transpiler(IEnumerable public sealed class Config : IConfig @@ -20,18 +23,19 @@ public sealed class Config : IConfig /// public bool Debug { get; set; } - /// - /// Gets or sets a value indicating whether events are only patched if they have delegates subscribed to them. - /// - [Description("Indicates whether events are patched only if they have delegates subscribed to them")] - public bool UseDynamicPatching { get; set; } = true; - /// /// Gets or sets a value indicating whether SCP-173 can be blocked by the tutorial. /// [Description("Indicates whether SCP-173 can be blocked by the tutorial")] - public bool CanTutorialBlockScp173 { get; set; } = true; - + public Dictionary CanTutorialBlockScp173 { get; set; } = + Events.Events.Instance.Config.CanTutorialBlockScp173 ? + new() + { + { RoleTypeId.Tutorial.ToString(), 0 }, + } + : new() { }; + + /* /// /// Gets or sets a value indicating whether SCP-096 can be triggered by the tutorial. /// @@ -49,66 +53,30 @@ public sealed class Config : IConfig /// [Description("Indicates whether tutorial is affected by SCP-079 scan.")] public bool TutorialNotAffectedByScp079Scan { get; set; } = false; + */ /// /// Gets or sets a value indicating whether flashbangs flash original thrower. /// [Description("Indicates whether flashbangs flash original thrower.")] - public bool CanFlashbangsAffectThrower { get; set; } = false; - - /// - /// Gets or sets a value indicating whether the name tracking (invisible EXILED version string added to the end of the server name) is enabled or not. - /// - [Description("Indicates whether the name tracking (invisible EXILED version string added to the end of the server name) is enabled or not")] - public bool IsNameTrackingEnabled { get; set; } = true; + public bool CanFlashbangsAffectThrower { get; set; } = Events.Events.Instance.Config.CanFlashbangsAffectThrower; /// /// Gets or sets a value indicating whether the inventory should be dropped before being set as spectator, through commands or plugins. /// [Description("Indicates whether the inventory should be dropped before being set as spectator, through commands or plugins")] - public bool ShouldDropInventory { get; set; } = true; + public bool ShouldDropInventory { get; set; } = Events.Events.Instance.Config.ShouldDropInventory; /// /// Gets or sets a value indicating whether the blood can be spawned. /// - [Description("Indicates whether the blood can be spawned")] - public bool CanSpawnBlood { get; set; } = true; - - /// - /// Gets or sets a value indicating whether keycard throw can affect basic doors. - /// - /// TODO: Make a poll about removing this config. (unimplemented since 9.6.0-beta7) - [Description("Indicates whether thrown keycards can affect doors that don't require any permissions")] - public bool CanKeycardThrowAffectDoors { get; set; } = false; + [Description("Indicates whether the Decal (Blood, Bullet, Buckshot, GlassCrack) can be spawned")] + public List PreventDecalSpawn { get; set; } = Events.Events.Instance.Config.CanSpawnBlood ? new() { DecalPoolType.Blood } : new() { }; /// /// Gets or sets a value indicating whether the SCP079 will recontained if there are no SCPs left. /// [Description("Indicates whether the SCP079 will recontained if there are no SCPs left.")] - public bool RecontainScp079IfNoScpsLeft { get; set; } = true; - - /// - /// Gets or sets a value indicating whether configs has to be reloaded every time a round restarts. - /// - [Description("Indicates whether configs have to be reloaded every round restart")] - public bool ShouldReloadConfigsAtRoundRestart { get; set; } = false; - - /// - /// Gets or sets a value indicating whether translations has to be reloaded every time a round restarts. - /// - [Description("Indicates whether translations has to be reloaded every round restart")] - public bool ShouldReloadTranslationsAtRoundRestart { get; set; } = false; - - /// - /// Gets a value indicating whether bans should be logged. - /// - [Description("Indicates whether bans should be logged")] - public bool ShouldLogBans { get; private set; } = true; - - /// - /// Gets or sets a value indicating whether to log RA commands. - /// - [Description("Whether to log RA commands.")] - public bool LogRaCommands { get; set; } = true; + public bool RecontainScp079IfNoScpsLeft { get; set; } = Events.Events.Instance.Config.RecontainScp079IfNoScpsLeft; } } From 430566ad7fda5cdff8d0b2a07c8ce56eae7ce2eb Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Mon, 23 Feb 2026 08:12:17 +0100 Subject: [PATCH 04/17] remove Dynamic --- EXILED/Exiled.Utility/Utility.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.Utility/Utility.cs b/EXILED/Exiled.Utility/Utility.cs index c0a6a24d15..d99082c0e9 100644 --- a/EXILED/Exiled.Utility/Utility.cs +++ b/EXILED/Exiled.Utility/Utility.cs @@ -55,7 +55,7 @@ public override void OnEnabled() watch.Stop(); - Log.Info($"{(Config.UseDynamicPatching ? "Non-event" : "All")} patches completed in {watch.Elapsed}"); + Log.Info($"patches completed in {watch.Elapsed}"); ServerConsole.ReloadServerName(); } From 07d0c076a28bfb0d390469198a385f682ccde85c Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Mon, 23 Feb 2026 08:45:03 +0100 Subject: [PATCH 05/17] NewEnumForAllStuffThatWasAboutTutorial --- EXILED/Exiled.Utility/Config.cs | 5 ++- .../NewEnumForAllStuffThatWasAboutTutorial.cs | 43 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs diff --git a/EXILED/Exiled.Utility/Config.cs b/EXILED/Exiled.Utility/Config.cs index 8efb5c2b74..4298599806 100644 --- a/EXILED/Exiled.Utility/Config.cs +++ b/EXILED/Exiled.Utility/Config.cs @@ -12,6 +12,7 @@ namespace Exiled.Utility using API.Interfaces; using Decals; + using Exiled.Utility.Enums; using PlayerRoles; /// @@ -27,11 +28,11 @@ public sealed class Config : IConfig /// Gets or sets a value indicating whether SCP-173 can be blocked by the tutorial. /// [Description("Indicates whether SCP-173 can be blocked by the tutorial")] - public Dictionary CanTutorialBlockScp173 { get; set; } = + public Dictionary CanTutorialBlockScp173 { get; set; } = Events.Events.Instance.Config.CanTutorialBlockScp173 ? new() { - { RoleTypeId.Tutorial.ToString(), 0 }, + { RoleTypeId.Tutorial.ToString(), NewEnumForAllStuffThatWasAboutTutorial.CanTutorialBlockScp173 }, } : new() { }; diff --git a/EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs b/EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs new file mode 100644 index 0000000000..f0b8d81324 --- /dev/null +++ b/EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs @@ -0,0 +1,43 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Utility.Enums +{ + using System; + + /// + /// All available screen aspect ratio types. + /// + [Flags] + public enum NewEnumForAllStuffThatWasAboutTutorial + { + /// + /// Unknown aspect ratio. + /// + None = 0, + + /// + /// Prevent from blocking Scp173. + /// + CanBlockScp173 = 1, + + /// + /// Prevent from being target of Scp096. + /// + CanTriggerScp096 = 2, + + /// + /// Prevent from being target of Scp049. + /// + CanScp049Sense = 4, + + /// + /// Prevent Player to be Alarmed by Scp079. + /// + NotAffectedByScp079Scan = 8, + } +} From eb69e7b4491f20a145e152b8fe379c4def4b1080 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Mon, 23 Feb 2026 08:57:19 +0100 Subject: [PATCH 06/17] idk how to make it --- EXILED/Exiled.Utility/Config.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EXILED/Exiled.Utility/Config.cs b/EXILED/Exiled.Utility/Config.cs index 4298599806..e6da1c5c5f 100644 --- a/EXILED/Exiled.Utility/Config.cs +++ b/EXILED/Exiled.Utility/Config.cs @@ -27,12 +27,12 @@ public sealed class Config : IConfig /// /// Gets or sets a value indicating whether SCP-173 can be blocked by the tutorial. /// - [Description("Indicates whether SCP-173 can be blocked by the tutorial")] - public Dictionary CanTutorialBlockScp173 { get; set; } = + [Description("Indicates whether RoleTypeId or CustomRole(Name or Id) prevented behaviours")] + public Dictionary NewStuffThatWasAboutTutorial { get; set; } = Events.Events.Instance.Config.CanTutorialBlockScp173 ? new() { - { RoleTypeId.Tutorial.ToString(), NewEnumForAllStuffThatWasAboutTutorial.CanTutorialBlockScp173 }, + { RoleTypeId.Tutorial.ToString(), NewEnumForAllStuffThatWasAboutTutorial.CanBlockScp173 }, } : new() { }; From 3c3e3f663fa8b3d0432c7831021dbdb2373563c1 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Mon, 23 Feb 2026 10:24:21 +0100 Subject: [PATCH 07/17] removing all config stuff inside Exiled.Events that arent related to event --- EXILED/Exiled.Events/Handlers/Internal/Round.cs | 2 +- .../Patches/Events/Map/ExplodingFlashGrenade.cs | 7 ++----- .../Patches/Generic/CanScp049SenseTutorial.cs | 17 +---------------- EXILED/Exiled.Utility/Config.cs | 2 +- 4 files changed, 5 insertions(+), 23 deletions(-) diff --git a/EXILED/Exiled.Events/Handlers/Internal/Round.cs b/EXILED/Exiled.Events/Handlers/Internal/Round.cs index cebcffa749..d6e7a9565b 100644 --- a/EXILED/Exiled.Events/Handlers/Internal/Round.cs +++ b/EXILED/Exiled.Events/Handlers/Internal/Round.cs @@ -104,7 +104,7 @@ public static void OnActivatingSense(ActivatingSenseEventArgs ev) { if (ev.Target is null) return; - if ((Events.Instance.Config.CanScp049SenseTutorial || ev.Target.Role.Type is not RoleTypeId.Tutorial) && !Scp049Role.TurnedPlayers.Contains(ev.Target)) + if (!Scp049Role.TurnedPlayers.Contains(ev.Target)) return; ev.Target = ev.Scp049.SenseAbility.CanFindTarget(out ReferenceHub hub) ? Player.Get(hub) : null; } diff --git a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs index 88549bc13a..d78daefdff 100644 --- a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs +++ b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs @@ -26,7 +26,7 @@ namespace Exiled.Events.Patches.Events.Map /// /// Patches . - /// Adds the event and . + /// Adds the event"/>. /// [HarmonyPatch(typeof(FlashbangGrenade), nameof(FlashbangGrenade.ServerFuseEnd))] internal static class ExplodingFlashGrenade @@ -69,10 +69,7 @@ private static void ProcessEvent(FlashbangGrenade instance, float distance) if ((instance.transform.position - player.Position).sqrMagnitude > distance) continue; - if (!ExiledEvents.Instance.Config.CanFlashbangsAffectThrower && instance.PreviousOwner.CompareLife(player.ReferenceHub)) - continue; - - if (!IndividualFriendlyFire.CheckFriendlyFirePlayer(instance.PreviousOwner, player.ReferenceHub) && !instance.PreviousOwner.CompareLife(player.ReferenceHub)) + if (!IndividualFriendlyFire.CheckFriendlyFirePlayer(instance.PreviousOwner, player.ReferenceHub)) continue; if (Physics.Linecast(instance.transform.position, player.CameraTransform.position, instance.BlindingMask)) diff --git a/EXILED/Exiled.Events/Patches/Generic/CanScp049SenseTutorial.cs b/EXILED/Exiled.Events/Patches/Generic/CanScp049SenseTutorial.cs index 01d7daaee5..d069e8d1c2 100644 --- a/EXILED/Exiled.Events/Patches/Generic/CanScp049SenseTutorial.cs +++ b/EXILED/Exiled.Events/Patches/Generic/CanScp049SenseTutorial.cs @@ -36,7 +36,6 @@ private static IEnumerable Transpiler(IEnumerable instruction.opcode == OpCodes.Brfalse); Label continueLabel = (Label)newInstructions[index].operand; - Label skip = generator.DefineLabel(); index += 1; @@ -46,22 +45,8 @@ private static IEnumerable Transpiler(IEnumerable), nameof(Plugin.Config))), - new(OpCodes.Callvirt, PropertyGetter(typeof(Config), nameof(Config.CanScp049SenseTutorial))), - new(OpCodes.Brfalse_S, continueLabel), - // if (Scp049Role.TurnedPlayers.Contains(Player.Get(referenceHub))) - new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(API.Features.Roles.Scp049Role), nameof(API.Features.Roles.Scp049Role.TurnedPlayers))).WithLabels(skip), + new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(API.Features.Roles.Scp049Role), nameof(API.Features.Roles.Scp049Role.TurnedPlayers))), new(OpCodes.Ldloc_S, 6), new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })), new(OpCodes.Callvirt, Method(typeof(HashSet), nameof(HashSet.Contains))), diff --git a/EXILED/Exiled.Utility/Config.cs b/EXILED/Exiled.Utility/Config.cs index e6da1c5c5f..fcdd93c522 100644 --- a/EXILED/Exiled.Utility/Config.cs +++ b/EXILED/Exiled.Utility/Config.cs @@ -69,7 +69,7 @@ public sealed class Config : IConfig public bool ShouldDropInventory { get; set; } = Events.Events.Instance.Config.ShouldDropInventory; /// - /// Gets or sets a value indicating whether the blood can be spawned. + /// Gets or sets a value indicating whether Decal spawned. /// [Description("Indicates whether the Decal (Blood, Bullet, Buckshot, GlassCrack) can be spawned")] public List PreventDecalSpawn { get; set; } = Events.Events.Instance.Config.CanSpawnBlood ? new() { DecalPoolType.Blood } : new() { }; From 8195400b6cac8eedf40ef3e9dbf058246d78af8f Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:24:22 +0100 Subject: [PATCH 08/17] remove config check --- .../Patches/Generic/ParseVisionInformation.cs | 27 +++---------------- 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/EXILED/Exiled.Events/Patches/Generic/ParseVisionInformation.cs b/EXILED/Exiled.Events/Patches/Generic/ParseVisionInformation.cs index 42e6c1013d..86b2bd91de 100644 --- a/EXILED/Exiled.Events/Patches/Generic/ParseVisionInformation.cs +++ b/EXILED/Exiled.Events/Patches/Generic/ParseVisionInformation.cs @@ -38,37 +38,16 @@ private static IEnumerable Transpiler(IEnumerable), nameof(Plugin.Config))), - new(OpCodes.Callvirt, PropertyGetter(typeof(Config), nameof(Config.CanTutorialTriggerScp096))), - new(OpCodes.Brfalse_S, returnLabel), - - // || Scp096Role.TurnedPlayers.Contains(Player.Get(referenceHub)) - new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(Scp096Role), nameof(Scp096Role.TurnedPlayers))).WithLabels(secondCheckPointer), + // if (!Scp096Role.TurnedPlayers.Contains(Player.Get(referenceHub))) + new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(Scp096Role), nameof(Scp096Role.TurnedPlayers))), new(OpCodes.Ldarg_1), new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })), new(OpCodes.Callvirt, Method(typeof(HashSet), nameof(HashSet.Contains))), From abc061c5c419a8ccd7249ae238814cfa685fb9aa Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Sat, 7 Mar 2026 01:49:36 +0100 Subject: [PATCH 09/17] Adding: EventHandler to Utility --- .../Commands/SpawnPrefabType.cs | 67 +++++++++++++++++++ EXILED/Exiled.Utility/Config.cs | 5 +- .../NewEnumForAllStuffThatWasAboutTutorial.cs | 9 ++- EXILED/Exiled.Utility/EventHandler.cs | 52 ++++++++++++++ EXILED/Exiled.Utility/Exiled.Utility.csproj | 4 ++ EXILED/Exiled.Utility/Utility.cs | 36 ++++------ 6 files changed, 147 insertions(+), 26 deletions(-) create mode 100644 EXILED/Exiled.Utility/Commands/SpawnPrefabType.cs create mode 100644 EXILED/Exiled.Utility/EventHandler.cs diff --git a/EXILED/Exiled.Utility/Commands/SpawnPrefabType.cs b/EXILED/Exiled.Utility/Commands/SpawnPrefabType.cs new file mode 100644 index 0000000000..f56a7fe9ef --- /dev/null +++ b/EXILED/Exiled.Utility/Commands/SpawnPrefabType.cs @@ -0,0 +1,67 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Utility.Commands +{ + using System; + + using CommandSystem; + using Exiled.API.Enums; + using Exiled.API.Features; + + /// + /// Command for spawning . + /// + [CommandHandler(typeof(RemoteAdminCommandHandler))] + public class SpawnPrefabType : ICommand, IUsageProvider + { + /// + public string Command { get; } = "PrefabType"; + + /// + public string[] Aliases { get; } = Array.Empty(); + + /// + public string Description { get; } = "Spawning PrefabType"; + + /// + public string[] Usage { get; } = new string[] { $"{string.Join(", ", EnumUtils.Names)}", }; + + /// + public bool Execute(ArraySegment arguments, ICommandSender sender, out string response) + { + if (!sender.CheckPermission(PlayerPermissions.FacilityManagement, out response)) + { + return false; + } + + Player.TryGet(sender, out Player player); + if (player is null) + { + response = "You must be a player to use this command."; + return false; + } + + if (arguments.Count < 1) + { + response = $"Please, use: {Command} {Usage}"; + return false; + } + + if (Enum.TryParse(arguments.At(0), out PrefabType prefabType)) + { + response = $"\"{arguments.At(0)}\" is not a valid prefab type."; + return false; + } + + PrefabHelper.Spawn(prefabType, player.Position, player.Rotation); + + response = "Spawning prefab type..."; + return true; + } + } +} \ No newline at end of file diff --git a/EXILED/Exiled.Utility/Config.cs b/EXILED/Exiled.Utility/Config.cs index fcdd93c522..901a6227fd 100644 --- a/EXILED/Exiled.Utility/Config.cs +++ b/EXILED/Exiled.Utility/Config.cs @@ -34,7 +34,10 @@ public sealed class Config : IConfig { { RoleTypeId.Tutorial.ToString(), NewEnumForAllStuffThatWasAboutTutorial.CanBlockScp173 }, } - : new() { }; + : new() + { + { RoleTypeId.Tutorial.ToString(), NewEnumForAllStuffThatWasAboutTutorial.None }, + }; /* /// diff --git a/EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs b/EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs index f0b8d81324..d59ced9d22 100644 --- a/EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs +++ b/EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs @@ -16,7 +16,12 @@ namespace Exiled.Utility.Enums public enum NewEnumForAllStuffThatWasAboutTutorial { /// - /// Unknown aspect ratio. + /// All. + /// + All = -1, + + /// + /// None. /// None = 0, @@ -31,7 +36,7 @@ public enum NewEnumForAllStuffThatWasAboutTutorial CanTriggerScp096 = 2, /// - /// Prevent from being target of Scp049. + /// Prevent from being target of Scp049 and stagger Scp0492. /// CanScp049Sense = 4, diff --git a/EXILED/Exiled.Utility/EventHandler.cs b/EXILED/Exiled.Utility/EventHandler.cs new file mode 100644 index 0000000000..b031cd390e --- /dev/null +++ b/EXILED/Exiled.Utility/EventHandler.cs @@ -0,0 +1,52 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Utility +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Decals; + using Exiled.API.Features; + using Exiled.Events.EventArgs.Map; + using InventorySystem.Items.Firearms.Modules; + using PlayerRoles; + +#pragma warning disable CS1591 // Commentaire XML manquant pour le type ou le membre visible publiquement +#pragma warning disable SA1600 // Elements should be documented + public class EventHandler + { + public Config Config { get; internal set; } + + public void OnWaitingForPlayers() + { + if (!Config.RecontainScp079IfNoScpsLeft) + PlayerRoleManager.OnServerRoleSet -= Recontainer.Base.OnServerRoleChanged; + } + + public void OnPlacingBulletHole(PlacingBulletHoleEventArgs ev) + { + ImpactEffectsModule impactEffectsModule = ev.Firearm.HitscanHitregModule._impactEffectsModule; + int? num = null; + for (int i = 0; i < impactEffectsModule.AttachmentOverrides.Length; i++) + { + if (impactEffectsModule.AttachmentOverrides[i].GetEnabled(ev.Firearm.Base)) + { + num = new int?(i); + break; + } + } + + DecalPoolType decalPoolType = ev.Firearm.HitscanHitregModule._impactEffectsModule.GetSettings(num).BulletholeDecal; + + if (Config.PreventDecalSpawn.Contains(decalPoolType)) + ev.IsAllowed = false; + } + } +} diff --git a/EXILED/Exiled.Utility/Exiled.Utility.csproj b/EXILED/Exiled.Utility/Exiled.Utility.csproj index 323fecd1f6..be661cdea8 100644 --- a/EXILED/Exiled.Utility/Exiled.Utility.csproj +++ b/EXILED/Exiled.Utility/Exiled.Utility.csproj @@ -11,6 +11,10 @@ + + + + diff --git a/EXILED/Exiled.Utility/Utility.cs b/EXILED/Exiled.Utility/Utility.cs index d99082c0e9..4b3ad3769c 100644 --- a/EXILED/Exiled.Utility/Utility.cs +++ b/EXILED/Exiled.Utility/Utility.cs @@ -11,19 +11,8 @@ namespace Exiled.Utility using System.Diagnostics; using API.Enums; - using API.Features; - using CentralAuth; - using Exiled.API.Features.Core.UserSettings; - using Exiled.Events.Features; + using Exiled.API.Features; using HarmonyLib; - using InventorySystem.Items.Pickups; - using InventorySystem.Items.Usables; - using PlayerRoles.Ragdolls; - using PlayerRoles.RoleAssign; - - using Respawning; - using UnityEngine.SceneManagement; - using UserSettings.ServerSpecific; /// /// Patch and unpatch events into the game. @@ -35,6 +24,11 @@ public sealed class Utility : Plugin /// public static Utility Instance { get; private set; } + /// + /// Gets the eventHandler. + /// + public static EventHandler EventHandler { get; private set; } + /// /// Gets the Harmony instance. /// @@ -47,17 +41,15 @@ public sealed class Utility : Plugin public override void OnEnabled() { Instance = this; - base.OnEnabled(); - - Stopwatch watch = Stopwatch.StartNew(); + EventHandler = new EventHandler + { + Config = Config, + }; + Events.Handlers.Server.WaitingForPlayers += EventHandler.OnWaitingForPlayers; + Events.Handlers.Map.PlacingBulletHole += EventHandler.OnPlacingBulletHole; Patch(); - - watch.Stop(); - - Log.Info($"patches completed in {watch.Elapsed}"); - - ServerConsole.ReloadServerName(); + base.OnEnabled(); } /// @@ -84,10 +76,8 @@ public void Patch() /// public void Unpatch() { - Log.Debug("Unpatching events..."); Harmony.UnpatchAll(Harmony.Id); Harmony = null; - Log.Debug("All events have been unpatched complete. Goodbye!"); } } } From 3527880c1ef6760ead7829fd089ba04d8ea7f9d7 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Sat, 7 Mar 2026 02:12:58 +0100 Subject: [PATCH 10/17] This is ASS code to show what should be improve in Exiled --- .../Exiled.API/Features/Roles/Scp0492Role.cs | 7 +++ .../Scp0492/TriggeringBloodlustEvent.cs | 15 +++++++ .../NewEnumForAllStuffThatWasAboutTutorial.cs | 7 ++- EXILED/Exiled.Utility/EventHandler.cs | 45 +++++++++++++++++++ EXILED/Exiled.Utility/Exiled.Utility.csproj | 1 + 5 files changed, 74 insertions(+), 1 deletion(-) diff --git a/EXILED/Exiled.API/Features/Roles/Scp0492Role.cs b/EXILED/Exiled.API/Features/Roles/Scp0492Role.cs index 7250aa4662..59aacd81ca 100644 --- a/EXILED/Exiled.API/Features/Roles/Scp0492Role.cs +++ b/EXILED/Exiled.API/Features/Roles/Scp0492Role.cs @@ -7,6 +7,8 @@ namespace Exiled.API.Features.Roles { + using System.Collections.Generic; + using PlayerRoles; using PlayerRoles.PlayableScps.HumeShield; using PlayerRoles.PlayableScps.Scp049; @@ -45,6 +47,11 @@ internal Scp0492Role(ZombieRole baseRole) ConsumeAbility = zombieConsumeAbility492; } + /// + /// Gets a list of players who are turned away from SCP-049 Sense Ability. + /// + public static HashSet TurnedPlayers { get; } = new(20); + /// public override RoleTypeId Type { get; } = RoleTypeId.Scp0492; diff --git a/EXILED/Exiled.Events/Patches/Events/Scp0492/TriggeringBloodlustEvent.cs b/EXILED/Exiled.Events/Patches/Events/Scp0492/TriggeringBloodlustEvent.cs index 32cd7264d0..722e94f1e6 100644 --- a/EXILED/Exiled.Events/Patches/Events/Scp0492/TriggeringBloodlustEvent.cs +++ b/EXILED/Exiled.Events/Patches/Events/Scp0492/TriggeringBloodlustEvent.cs @@ -12,6 +12,7 @@ namespace Exiled.Events.Patches.Events.Scp0492 using Exiled.API.Features; using Exiled.API.Features.Pools; + using Exiled.API.Features.Roles; using Exiled.Events.Attributes; using Exiled.Events.EventArgs.Scp0492; @@ -38,17 +39,31 @@ private static IEnumerable Transpiler(IEnumerable), nameof(HashSet.Contains))), + new(OpCodes.Brfalse_S, continueLabel), }); for (int z = 0; z < newInstructions.Count; z++) diff --git a/EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs b/EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs index d59ced9d22..d16b35ac30 100644 --- a/EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs +++ b/EXILED/Exiled.Utility/Enums/NewEnumForAllStuffThatWasAboutTutorial.cs @@ -40,9 +40,14 @@ public enum NewEnumForAllStuffThatWasAboutTutorial /// CanScp049Sense = 4, + /// + /// Prevent from being target of Scp049 and stagger Scp0492. + /// + CanScp0492Sense = 4, + /// /// Prevent Player to be Alarmed by Scp079. /// - NotAffectedByScp079Scan = 8, + NotAffectedByScp079Scan = 16, } } diff --git a/EXILED/Exiled.Utility/EventHandler.cs b/EXILED/Exiled.Utility/EventHandler.cs index b031cd390e..29681870fc 100644 --- a/EXILED/Exiled.Utility/EventHandler.cs +++ b/EXILED/Exiled.Utility/EventHandler.cs @@ -12,9 +12,14 @@ namespace Exiled.Utility using System.Linq; using System.Text; using System.Threading.Tasks; + using Decals; using Exiled.API.Features; + using Exiled.API.Features.Roles; + using Exiled.CustomRoles.API.Features; using Exiled.Events.EventArgs.Map; + using Exiled.Events.EventArgs.Player; + using Exiled.Utility.Enums; using InventorySystem.Items.Firearms.Modules; using PlayerRoles; @@ -30,6 +35,46 @@ public void OnWaitingForPlayers() PlayerRoleManager.OnServerRoleSet -= Recontainer.Base.OnServerRoleChanged; } + public void OnSpawned(SpawnedEventArgs ev) + { + Scp173Role.TurnedPlayers.Remove(ev.Player); + Scp096Role.TurnedPlayers.Remove(ev.Player); + Scp049Role.TurnedPlayers.Remove(ev.Player); + Scp0492Role.TurnedPlayers.Remove(ev.Player); + string role = ev.Player.Role.Type.ToString(); + foreach (CustomRole customRole in CustomRole.Registered) + { + if (customRole.Check(ev.Player)) + { + role = customRole.Name; + break; + } + } + + if (Config.NewStuffThatWasAboutTutorial.TryGetValue(role, out NewEnumForAllStuffThatWasAboutTutorial bruh)) + { + if (bruh.HasFlag(NewEnumForAllStuffThatWasAboutTutorial.CanBlockScp173)) + { + Scp173Role.TurnedPlayers.Add(ev.Player); + } + + if (bruh.HasFlag(NewEnumForAllStuffThatWasAboutTutorial.CanTriggerScp096)) + { + Scp096Role.TurnedPlayers.Add(ev.Player); + } + + if (bruh.HasFlag(NewEnumForAllStuffThatWasAboutTutorial.CanScp049Sense)) + { + Scp049Role.TurnedPlayers.Add(ev.Player); + } + + if (bruh.HasFlag(NewEnumForAllStuffThatWasAboutTutorial.CanScp0492Sense)) + { + Scp0492Role.TurnedPlayers.Add(ev.Player); + } + } + } + public void OnPlacingBulletHole(PlacingBulletHoleEventArgs ev) { ImpactEffectsModule impactEffectsModule = ev.Firearm.HitscanHitregModule._impactEffectsModule; diff --git a/EXILED/Exiled.Utility/Exiled.Utility.csproj b/EXILED/Exiled.Utility/Exiled.Utility.csproj index be661cdea8..fb8692eb27 100644 --- a/EXILED/Exiled.Utility/Exiled.Utility.csproj +++ b/EXILED/Exiled.Utility/Exiled.Utility.csproj @@ -17,6 +17,7 @@ + From c2e4560d91d82486dafe831b40f47561768859b5 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Sat, 7 Mar 2026 02:15:43 +0100 Subject: [PATCH 11/17] we don't have BloodDecalEvent --- EXILED/Exiled.Utility/Utility.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/EXILED/Exiled.Utility/Utility.cs b/EXILED/Exiled.Utility/Utility.cs index 4b3ad3769c..b042843f27 100644 --- a/EXILED/Exiled.Utility/Utility.cs +++ b/EXILED/Exiled.Utility/Utility.cs @@ -48,6 +48,8 @@ public override void OnEnabled() Events.Handlers.Server.WaitingForPlayers += EventHandler.OnWaitingForPlayers; Events.Handlers.Map.PlacingBulletHole += EventHandler.OnPlacingBulletHole; + + // BloodDecal is Missing Patch(); base.OnEnabled(); } From 2c87b972716ca060a3233c0ea6a7a980f1ad72d7 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Sat, 7 Mar 2026 02:16:44 +0100 Subject: [PATCH 12/17] remove commented code --- EXILED/Exiled.Utility/Config.cs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/EXILED/Exiled.Utility/Config.cs b/EXILED/Exiled.Utility/Config.cs index 901a6227fd..bfabdddd59 100644 --- a/EXILED/Exiled.Utility/Config.cs +++ b/EXILED/Exiled.Utility/Config.cs @@ -39,26 +39,6 @@ public sealed class Config : IConfig { RoleTypeId.Tutorial.ToString(), NewEnumForAllStuffThatWasAboutTutorial.None }, }; - /* - /// - /// Gets or sets a value indicating whether SCP-096 can be triggered by the tutorial. - /// - [Description("Indicates whether SCP-096 can be triggered by the tutorial")] - public bool CanTutorialTriggerScp096 { get; set; } = true; - - /// - /// Gets or sets a value indicating whether SCP-049 can activate the sense ability on tutorials. - /// - [Description("Indicates whether SCP-049 can sense tutorial players")] - public bool CanScp049SenseTutorial { get; set; } = true; - - /// - /// Gets or sets a value indicating whether tutorial is affected by SCP-079 scan. - /// - [Description("Indicates whether tutorial is affected by SCP-079 scan.")] - public bool TutorialNotAffectedByScp079Scan { get; set; } = false; - */ - /// /// Gets or sets a value indicating whether flashbangs flash original thrower. /// From 5f271e186a74d763f2c59721c9cf3e652461d353 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Sat, 7 Mar 2026 02:23:03 +0100 Subject: [PATCH 13/17] feat: `Player.LifeIdentifier` --- EXILED/Exiled.API/Features/Player.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/EXILED/Exiled.API/Features/Player.cs b/EXILED/Exiled.API/Features/Player.cs index 522a0a2113..9d500ca681 100644 --- a/EXILED/Exiled.API/Features/Player.cs +++ b/EXILED/Exiled.API/Features/Player.cs @@ -1199,6 +1199,11 @@ public bool IsSpectatable /// public Footprint Footprint => new(ReferenceHub); + /// + /// Gets the player's UniqueLifeIdentifier. + /// + public int LifeIdentifier => ReferenceHub.roleManager.CurrentRole.UniqueLifeIdentifier; + /// /// Gets or sets a value indicating whether the player is spawn protected. /// From 6b0b3a3ae935c0e3db53bd7980df40a264df5235 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Sat, 7 Mar 2026 02:23:14 +0100 Subject: [PATCH 14/17] this is required --- .../Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs index d78daefdff..8ed622394d 100644 --- a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs +++ b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs @@ -69,7 +69,7 @@ private static void ProcessEvent(FlashbangGrenade instance, float distance) if ((instance.transform.position - player.Position).sqrMagnitude > distance) continue; - if (!IndividualFriendlyFire.CheckFriendlyFirePlayer(instance.PreviousOwner, player.ReferenceHub)) + if (!IndividualFriendlyFire.CheckFriendlyFirePlayer(instance.PreviousOwner, player.ReferenceHub) && instance.PreviousOwner.LifeIdentifier == player.Footprint.LifeIdentifier) continue; if (Physics.Linecast(instance.transform.position, player.CameraTransform.position, instance.BlindingMask)) From f6786420c493378d35cbea3a63dc2c5e6a7282cf Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Sat, 7 Mar 2026 02:27:16 +0100 Subject: [PATCH 15/17] comment --- EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs index 8ed622394d..f376123a9e 100644 --- a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs +++ b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs @@ -69,6 +69,7 @@ private static void ProcessEvent(FlashbangGrenade instance, float distance) if ((instance.transform.position - player.Position).sqrMagnitude > distance) continue; + // LifeIdentifier check is needed to fix NW Bug https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/2811 if (!IndividualFriendlyFire.CheckFriendlyFirePlayer(instance.PreviousOwner, player.ReferenceHub) && instance.PreviousOwner.LifeIdentifier == player.Footprint.LifeIdentifier) continue; From ccdeac7c2e4fb371f3818a12d0a517fb208469e8 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Sat, 7 Mar 2026 02:53:25 +0100 Subject: [PATCH 16/17] =?UTF-8?q?doing=20stuff=20it's=203am=20i=20am=20laz?= =?UTF-8?q?y=20to=20write=20correct=20commit=20=F0=9F=AA=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EXILED/Exiled.Events/Config.cs | 48 ------------------- EXILED/Exiled.Events/Events.cs | 2 - .../Exiled.Events/Handlers/Internal/Round.cs | 7 --- .../Patches/Generic/CanScp049SenseTutorial.cs | 4 +- .../Patches/Generic/Scp079Scan.cs | 14 ------ EXILED/Exiled.Utility/Config.cs | 16 ++----- EXILED/Exiled.Utility/EventHandler.cs | 15 ++++++ EXILED/Exiled.Utility/Utility.cs | 7 ++- 8 files changed, 26 insertions(+), 87 deletions(-) diff --git a/EXILED/Exiled.Events/Config.cs b/EXILED/Exiled.Events/Config.cs index 56a8206e74..4fea2e64ab 100644 --- a/EXILED/Exiled.Events/Config.cs +++ b/EXILED/Exiled.Events/Config.cs @@ -26,66 +26,18 @@ public sealed class Config : IConfig [Description("Indicates whether events are patched only if they have delegates subscribed to them")] public bool UseDynamicPatching { get; set; } = true; - /// - /// Gets or sets a value indicating whether SCP-173 can be blocked by the tutorial. - /// - [Description("Indicates whether SCP-173 can be blocked by the tutorial")] - public bool CanTutorialBlockScp173 { get; set; } = true; - - /// - /// Gets or sets a value indicating whether SCP-096 can be triggered by the tutorial. - /// - [Description("Indicates whether SCP-096 can be triggered by the tutorial")] - public bool CanTutorialTriggerScp096 { get; set; } = true; - - /// - /// Gets or sets a value indicating whether SCP-049 can activate the sense ability on tutorials. - /// - [Description("Indicates whether SCP-049 can sense tutorial players")] - public bool CanScp049SenseTutorial { get; set; } = true; - - /// - /// Gets or sets a value indicating whether tutorial is affected by SCP-079 scan. - /// - [Description("Indicates whether tutorial is affected by SCP-079 scan.")] - public bool TutorialNotAffectedByScp079Scan { get; set; } = false; - - /// - /// Gets or sets a value indicating whether flashbangs flash original thrower. - /// - [Description("Indicates whether flashbangs flash original thrower.")] - public bool CanFlashbangsAffectThrower { get; set; } = false; - /// /// Gets or sets a value indicating whether the name tracking (invisible EXILED version string added to the end of the server name) is enabled or not. /// [Description("Indicates whether the name tracking (invisible EXILED version string added to the end of the server name) is enabled or not")] public bool IsNameTrackingEnabled { get; set; } = true; - /// - /// Gets or sets a value indicating whether the inventory should be dropped before being set as spectator, through commands or plugins. - /// - [Description("Indicates whether the inventory should be dropped before being set as spectator, through commands or plugins")] - public bool ShouldDropInventory { get; set; } = true; - - /// - /// Gets or sets a value indicating whether the blood can be spawned. - /// - [Description("Indicates whether the blood can be spawned")] - public bool CanSpawnBlood { get; set; } = true; - /// /// Gets or sets a value indicating whether keycard throw can affect basic doors. /// [Description("Indicates whether thrown keycards can affect doors that don't require any permissions")] public bool CanKeycardThrowAffectDoors { get; set; } = false; - /// - /// Gets or sets a value indicating whether the SCP079 will recontained if there are no SCPs left. - /// - [Description("Indicates whether the SCP079 will recontained if there are no SCPs left.")] - public bool RecontainScp079IfNoScpsLeft { get; set; } = true; - /// /// Gets or sets a value indicating whether configs has to be reloaded every time a round restarts. /// diff --git a/EXILED/Exiled.Events/Events.cs b/EXILED/Exiled.Events/Events.cs index f01919aff5..fb3cbdaa20 100644 --- a/EXILED/Exiled.Events/Events.cs +++ b/EXILED/Exiled.Events/Events.cs @@ -65,7 +65,6 @@ public override void OnEnabled() Handlers.Server.WaitingForPlayers += Handlers.Internal.Round.OnWaitingForPlayers; Handlers.Server.RestartingRound += Handlers.Internal.Round.OnRestartingRound; Handlers.Server.RoundStarted += Handlers.Internal.Round.OnRoundStarted; - Handlers.Player.ChangingRole += Handlers.Internal.Round.OnChangingRole; Handlers.Player.SpawningRagdoll += Handlers.Internal.Round.OnSpawningRagdoll; Handlers.Scp049.ActivatingSense += Handlers.Internal.Round.OnActivatingSense; Handlers.Player.Verified += Handlers.Internal.Round.OnVerified; @@ -113,7 +112,6 @@ public override void OnDisabled() Handlers.Server.WaitingForPlayers -= Handlers.Internal.Round.OnWaitingForPlayers; Handlers.Server.RestartingRound -= Handlers.Internal.Round.OnRestartingRound; Handlers.Server.RoundStarted -= Handlers.Internal.Round.OnRoundStarted; - Handlers.Player.ChangingRole -= Handlers.Internal.Round.OnChangingRole; Handlers.Player.SpawningRagdoll -= Handlers.Internal.Round.OnSpawningRagdoll; Handlers.Scp049.ActivatingSense -= Handlers.Internal.Round.OnActivatingSense; Handlers.Player.Verified -= Handlers.Internal.Round.OnVerified; diff --git a/EXILED/Exiled.Events/Handlers/Internal/Round.cs b/EXILED/Exiled.Events/Handlers/Internal/Round.cs index d6e7a9565b..015a9fe7d8 100644 --- a/EXILED/Exiled.Events/Handlers/Internal/Round.cs +++ b/EXILED/Exiled.Events/Handlers/Internal/Round.cs @@ -82,13 +82,6 @@ public static void OnRestartingRound() /// public static void OnRoundStarted() => MultiAdminFeatures.CallEvent(MultiAdminFeatures.EventType.ROUND_START); - /// - public static void OnChangingRole(ChangingRoleEventArgs ev) - { - if (!ev.Player.IsHost && ev.NewRole == RoleTypeId.Spectator && ev.Reason is not SpawnReason.Destroyed && Events.Instance.Config.ShouldDropInventory) - ev.Player.Inventory.ServerDropEverything(); - } - /// public static void OnSpawningRagdoll(SpawningRagdollEventArgs ev) { diff --git a/EXILED/Exiled.Events/Patches/Generic/CanScp049SenseTutorial.cs b/EXILED/Exiled.Events/Patches/Generic/CanScp049SenseTutorial.cs index d069e8d1c2..222d4ecd73 100644 --- a/EXILED/Exiled.Events/Patches/Generic/CanScp049SenseTutorial.cs +++ b/EXILED/Exiled.Events/Patches/Generic/CanScp049SenseTutorial.cs @@ -20,11 +20,9 @@ namespace Exiled.Events.Patches.Generic using static HarmonyLib.AccessTools; - using ExiledEvents = Exiled.Events.Events; - /// /// Patches . - /// . + /// . /// [HarmonyPatch(typeof(Scp049SenseAbility), nameof(Scp049SenseAbility.CanFindTarget))] internal static class CanScp049SenseTutorial diff --git a/EXILED/Exiled.Events/Patches/Generic/Scp079Scan.cs b/EXILED/Exiled.Events/Patches/Generic/Scp079Scan.cs index 6b4b93e406..b3bd692607 100644 --- a/EXILED/Exiled.Events/Patches/Generic/Scp079Scan.cs +++ b/EXILED/Exiled.Events/Patches/Generic/Scp079Scan.cs @@ -41,20 +41,6 @@ private static IEnumerable Transpiler(IEnumerable), nameof(Plugin.Config))), - new(OpCodes.Callvirt, PropertyGetter(typeof(Config), nameof(Config.TutorialNotAffectedByScp079Scan))), - new(OpCodes.Brfalse_S, returnLabel), - // if (Scp079Role.TurnedPlayers.Contains(Player.Get(referenceHub))) new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(API.Features.Roles.Scp079Role), nameof(API.Features.Roles.Scp079Role.TurnedPlayers))).WithLabels(skip), new(OpCodes.Ldarg_1), diff --git a/EXILED/Exiled.Utility/Config.cs b/EXILED/Exiled.Utility/Config.cs index bfabdddd59..2d3bccebab 100644 --- a/EXILED/Exiled.Utility/Config.cs +++ b/EXILED/Exiled.Utility/Config.cs @@ -28,13 +28,7 @@ public sealed class Config : IConfig /// Gets or sets a value indicating whether SCP-173 can be blocked by the tutorial. /// [Description("Indicates whether RoleTypeId or CustomRole(Name or Id) prevented behaviours")] - public Dictionary NewStuffThatWasAboutTutorial { get; set; } = - Events.Events.Instance.Config.CanTutorialBlockScp173 ? - new() - { - { RoleTypeId.Tutorial.ToString(), NewEnumForAllStuffThatWasAboutTutorial.CanBlockScp173 }, - } - : new() + public Dictionary NewStuffThatWasAboutTutorial { get; set; } = new() { { RoleTypeId.Tutorial.ToString(), NewEnumForAllStuffThatWasAboutTutorial.None }, }; @@ -43,24 +37,24 @@ public sealed class Config : IConfig /// Gets or sets a value indicating whether flashbangs flash original thrower. /// [Description("Indicates whether flashbangs flash original thrower.")] - public bool CanFlashbangsAffectThrower { get; set; } = Events.Events.Instance.Config.CanFlashbangsAffectThrower; + public bool CanFlashbangsAffectThrower { get; set; } = false; /// /// Gets or sets a value indicating whether the inventory should be dropped before being set as spectator, through commands or plugins. /// [Description("Indicates whether the inventory should be dropped before being set as spectator, through commands or plugins")] - public bool ShouldDropInventory { get; set; } = Events.Events.Instance.Config.ShouldDropInventory; + public bool ShouldDropInventory { get; set; } = false; /// /// Gets or sets a value indicating whether Decal spawned. /// [Description("Indicates whether the Decal (Blood, Bullet, Buckshot, GlassCrack) can be spawned")] - public List PreventDecalSpawn { get; set; } = Events.Events.Instance.Config.CanSpawnBlood ? new() { DecalPoolType.Blood } : new() { }; + public List PreventDecalSpawn { get; set; } = new() { }; /// /// Gets or sets a value indicating whether the SCP079 will recontained if there are no SCPs left. /// [Description("Indicates whether the SCP079 will recontained if there are no SCPs left.")] - public bool RecontainScp079IfNoScpsLeft { get; set; } = Events.Events.Instance.Config.RecontainScp079IfNoScpsLeft; + public bool RecontainScp079IfNoScpsLeft { get; set; } = true; } } diff --git a/EXILED/Exiled.Utility/EventHandler.cs b/EXILED/Exiled.Utility/EventHandler.cs index 29681870fc..7f1e958720 100644 --- a/EXILED/Exiled.Utility/EventHandler.cs +++ b/EXILED/Exiled.Utility/EventHandler.cs @@ -14,12 +14,14 @@ namespace Exiled.Utility using System.Threading.Tasks; using Decals; + using Exiled.API.Enums; using Exiled.API.Features; using Exiled.API.Features.Roles; using Exiled.CustomRoles.API.Features; using Exiled.Events.EventArgs.Map; using Exiled.Events.EventArgs.Player; using Exiled.Utility.Enums; + using InventorySystem; using InventorySystem.Items.Firearms.Modules; using PlayerRoles; @@ -35,12 +37,20 @@ public void OnWaitingForPlayers() PlayerRoleManager.OnServerRoleSet -= Recontainer.Base.OnServerRoleChanged; } + /// + public void OnChangingRole(ChangingRoleEventArgs ev) + { + if (!ev.Player.IsHost && ev.NewRole == RoleTypeId.Spectator && ev.Reason is not SpawnReason.Destroyed && Config.ShouldDropInventory) + ev.Player.Inventory.ServerDropEverything(); + } + public void OnSpawned(SpawnedEventArgs ev) { Scp173Role.TurnedPlayers.Remove(ev.Player); Scp096Role.TurnedPlayers.Remove(ev.Player); Scp049Role.TurnedPlayers.Remove(ev.Player); Scp0492Role.TurnedPlayers.Remove(ev.Player); + Scp079Role.TurnedPlayers.Remove(ev.Player); string role = ev.Player.Role.Type.ToString(); foreach (CustomRole customRole in CustomRole.Registered) { @@ -72,6 +82,11 @@ public void OnSpawned(SpawnedEventArgs ev) { Scp0492Role.TurnedPlayers.Add(ev.Player); } + + if (bruh.HasFlag(NewEnumForAllStuffThatWasAboutTutorial.NotAffectedByScp079Scan)) + { + Scp079Role.TurnedPlayers.Add(ev.Player); + } } } diff --git a/EXILED/Exiled.Utility/Utility.cs b/EXILED/Exiled.Utility/Utility.cs index b042843f27..42bdcbcd60 100644 --- a/EXILED/Exiled.Utility/Utility.cs +++ b/EXILED/Exiled.Utility/Utility.cs @@ -9,6 +9,7 @@ namespace Exiled.Utility { using System; using System.Diagnostics; + using System.Runtime.InteropServices; using API.Enums; using Exiled.API.Features; @@ -45,7 +46,7 @@ public override void OnEnabled() { Config = Config, }; - + Events.Handlers.Player.ChangingRole += EventHandler.OnChangingRole; Events.Handlers.Server.WaitingForPlayers += EventHandler.OnWaitingForPlayers; Events.Handlers.Map.PlacingBulletHole += EventHandler.OnPlacingBulletHole; @@ -58,7 +59,9 @@ public override void OnEnabled() public override void OnDisabled() { base.OnDisabled(); - + Events.Handlers.Player.ChangingRole += EventHandler.OnChangingRole; + Events.Handlers.Server.WaitingForPlayers += EventHandler.OnWaitingForPlayers; + Events.Handlers.Map.PlacingBulletHole += EventHandler.OnPlacingBulletHole; Unpatch(); } From 59147ff36a6be2fc52047a806a65d2dee3150916 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Sat, 7 Mar 2026 03:24:15 +0100 Subject: [PATCH 17/17] SpawnPrefabType --- EXILED/Exiled.API/Enums/PrefabType.cs | 1 + EXILED/Exiled.API/Features/PrefabHelper.cs | 18 +++++++++++++++++- .../Exiled.Utility/Commands/SpawnPrefabType.cs | 5 +++-- EXILED/Exiled.Utility/Utility.cs | 2 -- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/EXILED/Exiled.API/Enums/PrefabType.cs b/EXILED/Exiled.API/Enums/PrefabType.cs index 43936f1d80..c3ce00898d 100644 --- a/EXILED/Exiled.API/Enums/PrefabType.cs +++ b/EXILED/Exiled.API/Enums/PrefabType.cs @@ -12,6 +12,7 @@ namespace Exiled.API.Enums /// /// Type of prefab. /// + /// public enum PrefabType { #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member diff --git a/EXILED/Exiled.API/Features/PrefabHelper.cs b/EXILED/Exiled.API/Features/PrefabHelper.cs index 179991e635..22579651ac 100644 --- a/EXILED/Exiled.API/Features/PrefabHelper.cs +++ b/EXILED/Exiled.API/Features/PrefabHelper.cs @@ -14,8 +14,8 @@ namespace Exiled.API.Features using Exiled.API.Enums; using Exiled.API.Features.Attributes; - using MapGeneration.Distributors; + using MapGeneration.RoomConnectors; using Mirror; using UnityEngine; @@ -57,6 +57,11 @@ public static PrefabAttribute GetPrefabAttribute(this PrefabType prefabType) /// Returns the . public static GameObject GetPrefab(PrefabType prefabType) { + if (prefabType is PrefabType.HCZOneSided or PrefabType.HCZTwoSided) + { + prefabType = PrefabType.HCZBreakableDoor; + } + if (Prefabs.TryGetValue(prefabType, out (GameObject, Component) prefab)) return prefab.Item1; @@ -112,6 +117,17 @@ public static GameObject Spawn(PrefabType prefabType, Vector3 position = default positionSync.Network_rotationY = (sbyte)Mathf.RoundToInt(rotation.Value.eulerAngles.y / 5.625F); } + if (prefabType is PrefabType.HCZOneSided or PrefabType.HCZTwoSided or PrefabType.HCZBreakableDoor) + { + newGameObject.GetComponent().Network_syncBitmask = prefabType switch + { + PrefabType.HCZTwoSided => 0b00000000, + PrefabType.HCZOneSided => 0b00000001, + PrefabType.HCZBreakableDoor => 0b00000011, + _ => 0 + }; + } + NetworkServer.Spawn(newGameObject); return newGameObject; diff --git a/EXILED/Exiled.Utility/Commands/SpawnPrefabType.cs b/EXILED/Exiled.Utility/Commands/SpawnPrefabType.cs index f56a7fe9ef..7c84c9a388 100644 --- a/EXILED/Exiled.Utility/Commands/SpawnPrefabType.cs +++ b/EXILED/Exiled.Utility/Commands/SpawnPrefabType.cs @@ -8,6 +8,7 @@ namespace Exiled.Utility.Commands { using System; + using System.Linq; using CommandSystem; using Exiled.API.Enums; @@ -48,11 +49,11 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s if (arguments.Count < 1) { - response = $"Please, use: {Command} {Usage}"; + response = $"Please, use: {Command} {string.Join(", ", EnumUtils.Names)}"; return false; } - if (Enum.TryParse(arguments.At(0), out PrefabType prefabType)) + if (!Enum.TryParse(arguments.At(0), out PrefabType prefabType)) { response = $"\"{arguments.At(0)}\" is not a valid prefab type."; return false; diff --git a/EXILED/Exiled.Utility/Utility.cs b/EXILED/Exiled.Utility/Utility.cs index 42bdcbcd60..3b26d74666 100644 --- a/EXILED/Exiled.Utility/Utility.cs +++ b/EXILED/Exiled.Utility/Utility.cs @@ -8,8 +8,6 @@ namespace Exiled.Utility { using System; - using System.Diagnostics; - using System.Runtime.InteropServices; using API.Enums; using Exiled.API.Features;