From aec6506ca1194ef95a302fcfa85e6ab47a2326b3 Mon Sep 17 00:00:00 2001 From: VALERA771 <72030575+VALERA771@users.noreply.github.com> Date: Thu, 30 Jan 2025 13:33:00 +0300 Subject: [PATCH 01/24] fix: `Room::NearestRooms` fix (#417) fix: new generation --- EXILED/Exiled.API/Features/Room.cs | 12 ++++++++++-- EXILED/Exiled.Events/Patches/Generic/DoorList.cs | 1 - 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/EXILED/Exiled.API/Features/Room.cs b/EXILED/Exiled.API/Features/Room.cs index dc880fe69c..9fde18957c 100644 --- a/EXILED/Exiled.API/Features/Room.cs +++ b/EXILED/Exiled.API/Features/Room.cs @@ -132,7 +132,16 @@ public class Room : MonoBehaviour, IWorldSpace /// /// Gets a of around the . /// - public IReadOnlyList NearestRooms { get; private set; } + public IReadOnlyList NearestRooms + { + get + { + if (NearestRoomsValue.Count == 0 && Identifier.ConnectedRooms.Count > 0) + NearestRoomsValue.AddRange(Identifier.ConnectedRooms.Select(Get)); + + return NearestRoomsValue; + } + } /// /// Gets a of in the . @@ -438,7 +447,6 @@ internal void InternalCreate() Windows = WindowsValue.AsReadOnly(); Doors = DoorsValue.AsReadOnly(); - NearestRooms = NearestRoomsValue.AsReadOnly(); Speakers = SpeakersValue.AsReadOnly(); Cameras = CamerasValue.AsReadOnly(); } diff --git a/EXILED/Exiled.Events/Patches/Generic/DoorList.cs b/EXILED/Exiled.Events/Patches/Generic/DoorList.cs index 8ae6a40910..2057bbd0f5 100644 --- a/EXILED/Exiled.Events/Patches/Generic/DoorList.cs +++ b/EXILED/Exiled.Events/Patches/Generic/DoorList.cs @@ -76,7 +76,6 @@ private static void InitDoor(DoorVariant doorVariant) foreach (Room room in rooms) { room.DoorsValue.Add(door); - room.NearestRoomsValue.AddRange(rooms.Except(new List() { room })); } if (door.Is(out CheckpointDoor checkpoint)) From 2c89b5980586d94211978fcc660ac69fd908c582 Mon Sep 17 00:00:00 2001 From: TtroubleTT <121741230+TtroubleTT@users.noreply.github.com> Date: Thu, 30 Jan 2025 02:40:57 -0800 Subject: [PATCH 02/24] fix: Fixes Custom Weapon Reload (#418) fix custom weapon reloading issues Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com> --- .../API/Features/CustomWeapon.cs | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs index 96122fa641..0eb927dc3e 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs @@ -10,13 +10,14 @@ namespace Exiled.CustomItems.API.Features using System; using System.Linq; + using Exiled.API.Enums; using Exiled.API.Extensions; using Exiled.API.Features; using Exiled.API.Features.DamageHandlers; using Exiled.API.Features.Items; using Exiled.API.Features.Pickups; using Exiled.Events.EventArgs.Player; - + using InventorySystem; using InventorySystem.Items.Firearms.Attachments; using InventorySystem.Items.Firearms.Attachments.Components; using InventorySystem.Items.Firearms.Modules; @@ -230,9 +231,24 @@ private void OnInternalReloaded(ReloadedWeaponEventArgs ev) if (ClipSize > 0) { int ammoChambered = ((AutomaticActionModule)ev.Firearm.Base.Modules.FirstOrDefault(x => x is AutomaticActionModule))?.SyncAmmoChambered ?? 0; - int ammodrop = -(ClipSize - ev.Firearm.MagazineAmmo) - ammoChambered; - ev.Firearm.MagazineAmmo = ClipSize - ammoChambered; - ev.Player.AddAmmo(ev.Firearm.AmmoType, (ushort)Mathf.Clamp(ammodrop, ushort.MinValue, ushort.MaxValue)); + int ammoToGive = ClipSize - ammoChambered; + + AmmoType ammoType = ev.Firearm.AmmoType; + int firearmAmmo = ev.Firearm.MagazineAmmo; + int ammoDrop = -(ClipSize - firearmAmmo - ammoChambered); + + int ammoInInventory = ev.Player.Ammo[ammoType.GetItemType()] + firearmAmmo; + if (ammoToGive < ammoInInventory) + { + ev.Firearm.MagazineAmmo = ammoToGive; + int newAmmo = ev.Player.Inventory.GetCurAmmo(ammoType.GetItemType()) + ammoDrop; + ev.Player.Inventory.ServerSetAmmo(ammoType.GetItemType(), newAmmo); + } + else + { + ev.Firearm.MagazineAmmo = ammoInInventory; + ev.Player.Inventory.ServerSetAmmo(ammoType.GetItemType(), 0); + } } OnReloaded(ev); From cd7ba63f46801272d41eacd7b17a557b04c61388 Mon Sep 17 00:00:00 2001 From: Trevlouw <45270312+Trevlouw@users.noreply.github.com> Date: Thu, 30 Jan 2025 05:41:36 -0500 Subject: [PATCH 03/24] feat: UserTextInputSetting and SliderSetting (#416) * feat: ShadowType More features for the Light wrapper * Why did we make this This is about as cooked as the other EXILED SSS stuff, only useful in OnEnabled(); * I definitely didnt forget to cover my copy pasting --- .../Features/Core/UserSettings/SettingBase.cs | 2 + .../Core/UserSettings/SliderSetting.cs | 124 ++++++++++++++++++ .../Core/UserSettings/UserTextInputSetting.cs | 90 +++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 EXILED/Exiled.API/Features/Core/UserSettings/SliderSetting.cs create mode 100644 EXILED/Exiled.API/Features/Core/UserSettings/UserTextInputSetting.cs diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs b/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs index 5af5f615e7..776b80cca3 100644 --- a/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs +++ b/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs @@ -176,6 +176,8 @@ public static bool TryGetSetting(Player player, int id, out T setting) SSGroupHeader header => new HeaderSetting(header), SSKeybindSetting keybindSetting => new KeybindSetting(keybindSetting), SSTwoButtonsSetting twoButtonsSetting => new TwoButtonsSetting(twoButtonsSetting), + SSPlaintextSetting plainTextSetting => new UserTextInputSetting(plainTextSetting), + SSSliderSetting sliderSetting => new SliderSetting(sliderSetting), _ => new SettingBase(settingBase) }; diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/SliderSetting.cs b/EXILED/Exiled.API/Features/Core/UserSettings/SliderSetting.cs new file mode 100644 index 0000000000..66d88174d9 --- /dev/null +++ b/EXILED/Exiled.API/Features/Core/UserSettings/SliderSetting.cs @@ -0,0 +1,124 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.API.Features.Core.UserSettings +{ + using System; + + using Exiled.API.Interfaces; + using global::UserSettings.ServerSpecific; + + /// + /// Represents a slider setting. + /// + public class SliderSetting : SettingBase, IWrapper + { + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public SliderSetting(int id, string label, float minValue, float maxValue, float defaultValue, bool isInteger = false, string stringFormat = "0.##", string displayFormat = "{0}", string hintDescription = null) + : this(new SSSliderSetting(id, label, minValue, maxValue, defaultValue, isInteger, stringFormat, displayFormat, hintDescription)) + { + Base = (SSSliderSetting)base.Base; + } + + /// + /// Initializes a new instance of the class. + /// + /// A instance. + internal SliderSetting(SSSliderSetting settingBase) + : base(settingBase) + { + Base = settingBase; + } + + /// + /// Gets or sets the minimum value of the slider. + /// + public float MinimumValue + { + get => Base.MinValue; + set => Base.MinValue = value; + } + + /// + /// Gets or sets the maximum value of the slider. + /// + public float MaximumValue + { + get => Base.MaxValue; + set => Base.MaxValue = value; + } + + /// + /// Gets or sets the default value of the slider. + /// + public float DefaultValue + { + get => Base.DefaultValue; + set => Base.DefaultValue = value; + } + + /// + /// Gets or sets a value indicating whether the slider displays integers. + /// + public bool IsInteger + { + get => Base.Integer; + set => Base.Integer = value; + } + + /// + /// Gets a value indicating whether the slider is currently being dragged. + /// + public bool IsBeingDragged => Base.SyncDragging; + + /// + /// Gets a float that represents the current value of the slider. + /// + public float SliderValue => Base.Integer ? Base.SyncIntValue : Base.SyncFloatValue; + + /// + /// Gets or sets the formatting used for the number in the slider. + /// + public string StringFormat + { + get => Base.ValueToStringFormat; + set => Base.ValueToStringFormat = value; + } + + /// + /// Gets or sets the formatting used for the final display of the value of the slider. + /// + public string DisplayFormat + { + get => Base.FinalDisplayFormat; + set => Base.FinalDisplayFormat = value; + } + + /// + public new SSSliderSetting Base { get; } + + /// + /// Returns a representation of this . + /// + /// A string in human-readable format. + public override string ToString() + { + return base.ToString() + $" /{MinimumValue}/ *{MaximumValue}* +{DefaultValue}+ '{SliderValue}'"; + } + } +} \ No newline at end of file diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/UserTextInputSetting.cs b/EXILED/Exiled.API/Features/Core/UserSettings/UserTextInputSetting.cs new file mode 100644 index 0000000000..8944558e03 --- /dev/null +++ b/EXILED/Exiled.API/Features/Core/UserSettings/UserTextInputSetting.cs @@ -0,0 +1,90 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.API.Features.Core.UserSettings +{ + using System; + + using Exiled.API.Interfaces; + using global::UserSettings.ServerSpecific; + using TMPro; + + /// + /// Represents a user text input setting. + /// + public class UserTextInputSetting : SettingBase, IWrapper + { + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// + /// + /// + /// /// + public UserTextInputSetting(int id, string label, string placeHolder = "", int characterLimit = 64, TMP_InputField.ContentType contentType = TMP_InputField.ContentType.Standard, string hintDescription = null) + : this(new SSPlaintextSetting(id, label, placeHolder, characterLimit, contentType, hintDescription)) + { + Base = (SSPlaintextSetting)base.Base; + } + + /// + /// Initializes a new instance of the class. + /// + /// A instance. + internal UserTextInputSetting(SSPlaintextSetting settingBase) + : base(settingBase) + { + Base = settingBase; + } + + /// + public new SSPlaintextSetting Base { get; } + + /// + /// Gets the value of the text entered by a client. + /// + public string Text => Base.SyncInputText; + + /// + /// Gets or sets a value indicating the placeholder shown within the PlainTextSetting. + /// + public string PlaceHolder + { + get => Base.Placeholder; + set => Base.Placeholder = value; + } + + /// + /// Gets or sets a value indicating the type of content within the PlainTextSetting. + /// + public TMP_InputField.ContentType ContentType + { + get => Base.ContentType; + set => Base.ContentType = value; + } + + /// + /// Gets or sets a value indicating the max number of characters in the PlainTextSetting. + /// + public int CharacterLimit + { + get => Base.CharacterLimit; + set => Base.CharacterLimit = value; + } + + /// + /// Returns a representation of this . + /// + /// A string in human-readable format. + public override string ToString() + { + return base.ToString() + $" /{Text}/ *{ContentType}* +{CharacterLimit}+"; + } + } +} \ No newline at end of file From 936b864f96db402fea6f02109c851bd9b36d905c Mon Sep 17 00:00:00 2001 From: TtroubleTT <121741230+TtroubleTT@users.noreply.github.com> Date: Sun, 2 Feb 2025 11:15:56 -0800 Subject: [PATCH 04/24] fix: Potential Error Fix With Custom Weapon Reloading (#421) * fix potential dictionary error * apply suggestion Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com> --------- Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com> --- EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs index 0eb927dc3e..6e8cf58e29 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs @@ -237,7 +237,7 @@ private void OnInternalReloaded(ReloadedWeaponEventArgs ev) int firearmAmmo = ev.Firearm.MagazineAmmo; int ammoDrop = -(ClipSize - firearmAmmo - ammoChambered); - int ammoInInventory = ev.Player.Ammo[ammoType.GetItemType()] + firearmAmmo; + int ammoInInventory = ev.Player.GetAmmo(ammoType) + firearmAmmo; if (ammoToGive < ammoInInventory) { ev.Firearm.MagazineAmmo = ammoToGive; From 61c1c2340ca52a8c1a1204a958d855dbcfd4817a Mon Sep 17 00:00:00 2001 From: TtroubleTT <121741230+TtroubleTT@users.noreply.github.com> Date: Wed, 5 Feb 2025 05:33:48 -0800 Subject: [PATCH 05/24] fix: Fix Custom Roles Lagging Back When Spawning (#428) fix custom roles lagging back --- EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs b/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs index 7de3e2eefd..7d7fd8b5bf 100644 --- a/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs +++ b/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs @@ -861,7 +861,7 @@ protected virtual void SubscribeEvents() Log.Debug($"{Name}: Loading events."); Exiled.Events.Handlers.Player.ChangingNickname += OnInternalChangingNickname; Exiled.Events.Handlers.Player.ChangingRole += OnInternalChangingRole; - Exiled.Events.Handlers.Player.Spawning += OnInternalSpawning; + Exiled.Events.Handlers.Player.Spawned += OnInternalSpawned; Exiled.Events.Handlers.Player.SpawningRagdoll += OnSpawningRagdoll; Exiled.Events.Handlers.Player.Destroying += OnDestroying; } @@ -877,7 +877,7 @@ protected virtual void UnsubscribeEvents() Log.Debug($"{Name}: Unloading events."); Exiled.Events.Handlers.Player.ChangingNickname -= OnInternalChangingNickname; Exiled.Events.Handlers.Player.ChangingRole -= OnInternalChangingRole; - Exiled.Events.Handlers.Player.Spawning -= OnInternalSpawning; + Exiled.Events.Handlers.Player.Spawned -= OnInternalSpawned; Exiled.Events.Handlers.Player.SpawningRagdoll -= OnSpawningRagdoll; Exiled.Events.Handlers.Player.Destroying -= OnDestroying; } @@ -918,9 +918,9 @@ private void OnInternalChangingNickname(ChangingNicknameEventArgs ev) ev.Player.CustomInfo = $"{ev.NewName}\n{CustomInfo}"; } - private void OnInternalSpawning(SpawningEventArgs ev) + private void OnInternalSpawned(SpawnedEventArgs ev) { - if (!IgnoreSpawnSystem && SpawnChance > 0 && !Check(ev.Player) && ev.NewRole == Role && Loader.Random.NextDouble() * 100 <= SpawnChance) + if (!IgnoreSpawnSystem && SpawnChance > 0 && !Check(ev.Player) && ev.Player.Role.Type == Role && Loader.Random.NextDouble() * 100 <= SpawnChance) AddRole(ev.Player); } From 571f49ee43e428fdd6edf15615180585f1c7e11a Mon Sep 17 00:00:00 2001 From: Lumi Date: Thu, 13 Feb 2025 12:37:25 +0000 Subject: [PATCH 06/24] feat: send to player specific settings (#432) --- .../Exiled.API/Features/Core/UserSettings/SettingBase.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs b/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs index 776b80cca3..b27ae1fc78 100644 --- a/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs +++ b/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs @@ -218,6 +218,14 @@ public static void SendToAll(Func predicate) /// Target player. public static void SendToPlayer(Player player) => ServerSpecificSettingsSync.SendToPlayer(player.ReferenceHub); + /// + /// Syncs specific settings with the specified target. + /// + /// Target player. + /// Settings to send to the player. + public static void SendToPlayer(Player player, IEnumerable settings) => + ServerSpecificSettingsSync.SendToPlayer(player.ReferenceHub, settings.Select(setting => setting.Base).ToArray()); + /// /// Registers all settings from the specified collection. /// From a7d8d2bd9e3fac4f20cf6f515e533fe0b8655348 Mon Sep 17 00:00:00 2001 From: Nameless <85962933+Misfiy@users.noreply.github.com> Date: Thu, 13 Feb 2025 13:38:50 +0100 Subject: [PATCH 07/24] fix: Npc cant get flashed (#429) --- .../Patches/Events/Map/ExplodingFlashGrenade.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs index 4413d18299..0884e28710 100644 --- a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs +++ b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs @@ -8,6 +8,7 @@ namespace Exiled.Events.Patches.Events.Map { using System.Collections.Generic; + using System.Linq; using System.Reflection.Emit; using API.Features; @@ -64,7 +65,7 @@ private static IEnumerable Transpiler(IEnumerable targetToAffect = HashSetPool.Pool.Get(); - foreach (Player player in Player.List) + foreach (Player player in ReferenceHub.AllHubs.Select(Player.Get)) { if ((instance.transform.position - player.Position).sqrMagnitude >= distance) continue; @@ -88,9 +89,7 @@ private static void ProcessEvent(FlashbangGrenade instance, float distance) return; foreach (Player player in explodingGrenadeEvent.TargetsToAffect) - { instance.ProcessPlayer(player.ReferenceHub); - } } } } \ No newline at end of file From 6eb4b1ea08979bc020371da21e72b6069b197a8f Mon Sep 17 00:00:00 2001 From: Nameless <85962933+Misfiy@users.noreply.github.com> Date: Thu, 13 Feb 2025 13:45:37 +0100 Subject: [PATCH 08/24] feat: remove sex (#395) --- EXILED/Exiled.Loader/Features/LoaderMessages.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/EXILED/Exiled.Loader/Features/LoaderMessages.cs b/EXILED/Exiled.Loader/Features/LoaderMessages.cs index f53aac3870..a1834e35ea 100644 --- a/EXILED/Exiled.Loader/Features/LoaderMessages.cs +++ b/EXILED/Exiled.Loader/Features/LoaderMessages.cs @@ -29,7 +29,7 @@ public static class LoaderMessages ▀ "; /// - /// Gets the easter egg loader message. + /// Gets the Easter egg loader message. /// public static string EasterEgg => @" ▄████████ ▄████████ ▀████ ▐████▀ ▄█ ▄█ ▄████████ ████████▄ @@ -43,7 +43,7 @@ public static class LoaderMessages "; /// - /// Gets the christmas loader message. + /// Gets the Christmas loader message. /// public static string Christmas => @" __ @@ -60,7 +60,7 @@ public static class LoaderMessages |____)_)"; /// - /// Gets the halloween loader message. + /// Gets the Halloween loader message. /// public static string Halloween => @" @@@@@@@@ @@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@@ @@ -81,7 +81,10 @@ @@@@@@@@ @@@ @@@ @@@ @@@ @@@@@@@@ @@@@@@@@ /// The correspondent loader message. public static string GetMessage() { - if (Loader.Version.ToString().Contains("6.9") || Loader.Random.NextDouble() <= 0.069) + if (Environment.GetCommandLineArgs().Contains("--defaultloadmessage")) + return Default; + + if (!Environment.GetCommandLineArgs().Contains("--noeasteregg") && (Loader.Version.ToString().Contains("6.9") || Loader.Random.NextDouble() <= 0.069)) return EasterEgg; return DateTime.Today.Month switch From f52bab7a6c31394b229554d0f8dfbc90a4002744 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Thu, 13 Feb 2025 13:54:36 +0100 Subject: [PATCH 09/24] feat: Server.IsHeavilyModded is Obsolete (#419) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Server.IsHeavilyModded * Update EXILED/Exiled.API/Features/Server.cs Co-authored-by: Vladislav Popovič * Update EXILED/Exiled.API/Features/Server.cs Co-authored-by: Vladislav Popovič * Update EXILED/Exiled.API/Features/Server.cs Co-authored-by: Vladislav Popovič --------- Co-authored-by: Vladislav Popovič --- EXILED/Exiled.API/Features/Server.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/EXILED/Exiled.API/Features/Server.cs b/EXILED/Exiled.API/Features/Server.cs index c79d0c4c1d..57d1752725 100644 --- a/EXILED/Exiled.API/Features/Server.cs +++ b/EXILED/Exiled.API/Features/Server.cs @@ -174,7 +174,20 @@ public static int MaxPlayerCount /// Read the VSR for more info about its usage. /// /// + [Obsolete("This field has been deleted because it used the wrong field (TransparentlyModded)")] public static bool IsHeavilyModded + { + get => false; + set => _ = value; + } + + /// + /// Gets or sets a value indicating whether the server is marked as Transparently Modded. + /// + /// It is not used now, wait for a new VSR update. + /// + /// + public static bool IsTransparentlyModded { get => ServerConsole.TransparentlyModdedServerConfig; set => ServerConsole.TransparentlyModdedServerConfig = value; From dafca44a0968e4c84112f0d61b2c77dbc96f1a33 Mon Sep 17 00:00:00 2001 From: TtroubleTT <121741230+TtroubleTT@users.noreply.github.com> Date: Thu, 13 Feb 2025 04:55:26 -0800 Subject: [PATCH 10/24] fix: Player Custom Firearm Reloading Exploit (#422) * fix player exploiting ammo amount by switching off weapon * fix quick reload exploit * abort it made things worse --- EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs index 6e8cf58e29..e775ee3e9f 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs @@ -225,7 +225,7 @@ private void OnInternalReloading(ReloadingWeaponEventArgs ev) private void OnInternalReloaded(ReloadedWeaponEventArgs ev) { - if (!Check(ev.Player.CurrentItem)) + if (!Check(ev.Item)) return; if (ClipSize > 0) From 19122697ffcdf89a4c64fdb391910a301efe1e50 Mon Sep 17 00:00:00 2001 From: TtroubleTT <121741230+TtroubleTT@users.noreply.github.com> Date: Thu, 13 Feb 2025 05:42:07 -0800 Subject: [PATCH 11/24] fix: Add SCP-1344 Effect to IsPositive Extension (#426) add 1344 to ispostive extension --- EXILED/Exiled.API/Extensions/EffectTypeExtension.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.API/Extensions/EffectTypeExtension.cs b/EXILED/Exiled.API/Extensions/EffectTypeExtension.cs index ad8119fe3d..dc209c3ba0 100644 --- a/EXILED/Exiled.API/Extensions/EffectTypeExtension.cs +++ b/EXILED/Exiled.API/Extensions/EffectTypeExtension.cs @@ -175,7 +175,7 @@ or EffectType.Disabled or EffectType.Ensnared or EffectType.Exhausted or EffectT /// public static bool IsPositive(this EffectType effect) => effect is EffectType.BodyshotReduction or EffectType.DamageReduction or EffectType.Invigorated or EffectType.Invisible or EffectType.MovementBoost or EffectType.RainbowTaste - or EffectType.Scp207 or EffectType.Scp1853 or EffectType.Vitality or EffectType.AntiScp207 or EffectType.Ghostly; + or EffectType.Scp207 or EffectType.Scp1853 or EffectType.Vitality or EffectType.AntiScp207 or EffectType.Ghostly or EffectType.Scp1344; /// /// Returns whether the provided affects the player's movement speed. From 403f449fac5dfa3af507b40dc92cb4ed3ac37966 Mon Sep 17 00:00:00 2001 From: Banalny-Banan <133122450+Banalny-Banan@users.noreply.github.com> Date: Thu, 13 Feb 2025 16:44:02 +0200 Subject: [PATCH 12/24] feat: added GameObject and Transform properties to AdminToy (#431) --- EXILED/Exiled.API/Features/Toys/AdminToy.cs | 10 ++++++++++ EXILED/Exiled.API/Features/Toys/ShootingTargetToy.cs | 6 ++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/EXILED/Exiled.API/Features/Toys/AdminToy.cs b/EXILED/Exiled.API/Features/Toys/AdminToy.cs index 01f54e8d26..a3ffa539cd 100644 --- a/EXILED/Exiled.API/Features/Toys/AdminToy.cs +++ b/EXILED/Exiled.API/Features/Toys/AdminToy.cs @@ -115,6 +115,16 @@ public Vector3 Scale } } + /// + /// Gets the of the toy. + /// + public GameObject GameObject => AdminToyBase.gameObject; + + /// + /// Gets the of the toy. + /// + public Transform Transform => AdminToyBase.transform; + /// /// Gets or sets the movement smoothing value of the toy. /// diff --git a/EXILED/Exiled.API/Features/Toys/ShootingTargetToy.cs b/EXILED/Exiled.API/Features/Toys/ShootingTargetToy.cs index a9051baed8..86246ffd28 100644 --- a/EXILED/Exiled.API/Features/Toys/ShootingTargetToy.cs +++ b/EXILED/Exiled.API/Features/Toys/ShootingTargetToy.cs @@ -66,10 +66,8 @@ internal ShootingTargetToy(ShootingTarget target) /// public ShootingTarget Base { get; } - /// - /// Gets the of the target. - /// - public GameObject GameObject => Base.gameObject; + /// + public new GameObject GameObject => base.GameObject; /// /// Gets the of the bullseye. From c85a92dd993fb240592eaceb0d8a3dd786cfa57c Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Thu, 13 Feb 2025 15:45:14 +0100 Subject: [PATCH 13/24] fix: Fixing TriggeringTesla not detecting NPC (#424) --- EXILED/Exiled.Events/Patches/Events/Player/TriggeringTesla.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/EXILED/Exiled.Events/Patches/Events/Player/TriggeringTesla.cs b/EXILED/Exiled.Events/Patches/Events/Player/TriggeringTesla.cs index 05f9b37280..4034169a6a 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/TriggeringTesla.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/TriggeringTesla.cs @@ -8,6 +8,7 @@ namespace Exiled.Events.Patches.Events.Player { using System.Collections.Generic; + using System.Linq; using System.Reflection.Emit; using API.Features; @@ -68,7 +69,7 @@ private static void TriggeringTeslaEvent(BaseTeslaGate baseTeslaGate, ref bool i { TeslaGate teslaGate = TeslaGate.Get(baseTeslaGate); - foreach (Player player in Player.List) + foreach (Player player in ReferenceHub.AllHubs.Select(Player.Get)) { if (player is null || !teslaGate.CanBeIdle(player)) continue; From 02e2bf699f27b79b92b406140b1cd08c8f49ce05 Mon Sep 17 00:00:00 2001 From: Snivy Films <120346554+SnivyFilms@users.noreply.github.com> Date: Fri, 14 Feb 2025 02:38:55 -0500 Subject: [PATCH 14/24] feat: Dynamic spawn location additions (#388) --- EXILED/Exiled.API/Enums/SpawnLocationType.cs | 25 +++++++++++++++++++ .../Exiled.API/Extensions/SpawnExtensions.cs | 6 +++++ 2 files changed, 31 insertions(+) diff --git a/EXILED/Exiled.API/Enums/SpawnLocationType.cs b/EXILED/Exiled.API/Enums/SpawnLocationType.cs index 1ebd57cc95..ae957d3362 100644 --- a/EXILED/Exiled.API/Enums/SpawnLocationType.cs +++ b/EXILED/Exiled.API/Enums/SpawnLocationType.cs @@ -143,5 +143,30 @@ public enum SpawnLocationType /// Just inside the LCZ WC door. /// InsideLczWc, + + /// + /// Inside the Glass Box in GR-18. + /// + InsideGr18Glass, + + /// + /// Inside 106's Primary Door + /// + Inside106Primary, + + /// + /// Inside 106's Secondary Door + /// + Inside106Secondary, + + /// + /// Inside 939 Cryo Chamber + /// + Inside939Cryo, + + /// + /// Inside SCP-079's Armory + /// + Inside079Armory, } } \ No newline at end of file diff --git a/EXILED/Exiled.API/Extensions/SpawnExtensions.cs b/EXILED/Exiled.API/Extensions/SpawnExtensions.cs index a987a56265..29da4ab802 100644 --- a/EXILED/Exiled.API/Extensions/SpawnExtensions.cs +++ b/EXILED/Exiled.API/Extensions/SpawnExtensions.cs @@ -34,6 +34,7 @@ public static class SpawnExtensions SpawnLocationType.Inside914, SpawnLocationType.Inside049Armory, SpawnLocationType.InsideLczCafe, + SpawnLocationType.Inside939Cryo, }; /// @@ -102,6 +103,11 @@ public static Vector3 GetPosition(this SpawnLocationType location) SpawnLocationType.Inside173Connector => "173_CONNECTOR", SpawnLocationType.InsideEscapePrimary => "ESCAPE_PRIMARY", SpawnLocationType.InsideEscapeSecondary => "ESCAPE_SECONDARY", + SpawnLocationType.InsideGr18Glass => "GR18_INNER", + SpawnLocationType.Inside106Primary => "106_PRIMARY", + SpawnLocationType.Inside106Secondary => "106_SECONDARY", + SpawnLocationType.Inside939Cryo => "939_CRYO", + SpawnLocationType.Inside079Armory => "079_ARMORY", _ => default, }; } From 1c27f25deaecfde1945b4f8ecdc164366a3d6f27 Mon Sep 17 00:00:00 2001 From: Banalny-Banan <133122450+Banalny-Banan@users.noreply.github.com> Date: Fri, 14 Feb 2025 22:12:28 +0200 Subject: [PATCH 15/24] feat: Added ICommandSender to Kicking/Banning EventArgs (#436) initial --- .../EventArgs/Player/BanningEventArgs.cs | 6 ++++-- .../EventArgs/Player/KickingEventArgs.cs | 13 +++++++++++-- .../Exiled.Events/Patches/Events/Player/Banning.cs | 10 ++++++++++ .../Exiled.Events/Patches/Events/Player/Kicking.cs | 5 ++++- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/EXILED/Exiled.Events/EventArgs/Player/BanningEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/BanningEventArgs.cs index 585e244773..86d15bf8d8 100644 --- a/EXILED/Exiled.Events/EventArgs/Player/BanningEventArgs.cs +++ b/EXILED/Exiled.Events/EventArgs/Player/BanningEventArgs.cs @@ -10,6 +10,7 @@ namespace Exiled.Events.EventArgs.Player using System.Reflection; using API.Features; + using CommandSystem; /// /// Contains all information before banning a player from the server. @@ -23,12 +24,13 @@ public class BanningEventArgs : KickingEventArgs /// /// The ban target. /// The ban issuer. + /// The ban command sender. /// The ban seconds duration. /// The ban reason. /// The ban full message. /// Indicates whether the event can be executed or not. - public BanningEventArgs(Player target, Player issuer, long duration, string reason, string fullMessage, bool isAllowed = true) - : base(target, issuer, reason, fullMessage, isAllowed) + public BanningEventArgs(Player target, Player issuer, ICommandSender commandSender, long duration, string reason, string fullMessage, bool isAllowed = true) + : base(target, issuer, commandSender, reason, fullMessage, isAllowed) { Duration = duration; } diff --git a/EXILED/Exiled.Events/EventArgs/Player/KickingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/KickingEventArgs.cs index 036b2aa4c2..cfa2864b85 100644 --- a/EXILED/Exiled.Events/EventArgs/Player/KickingEventArgs.cs +++ b/EXILED/Exiled.Events/EventArgs/Player/KickingEventArgs.cs @@ -10,7 +10,7 @@ namespace Exiled.Events.EventArgs.Player using System.Reflection; using API.Features; - + using CommandSystem; using Interfaces; /// @@ -32,6 +32,9 @@ public class KickingEventArgs : IPlayerEvent, IDeniableEvent /// /// /// + /// + /// + /// /// /// /// @@ -41,10 +44,11 @@ public class KickingEventArgs : IPlayerEvent, IDeniableEvent /// /// /// - public KickingEventArgs(Player target, Player issuer, string reason, string fullMessage, bool isAllowed = true) + public KickingEventArgs(Player target, Player issuer, ICommandSender commandSender, string reason, string fullMessage, bool isAllowed = true) { Target = target; Player = issuer ?? Server.Host; + CommandSender = commandSender; Reason = reason; startkickmessage = fullMessage; IsAllowed = isAllowed; @@ -114,6 +118,11 @@ public Player Player } } + /// + /// Gets the command sender. + /// + public ICommandSender CommandSender { get; } + /// /// Logs the kick, anti-backdoor protection from malicious plugins. /// diff --git a/EXILED/Exiled.Events/Patches/Events/Player/Banning.cs b/EXILED/Exiled.Events/Patches/Events/Player/Banning.cs index 271d22ffe5..573c2bd820 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/Banning.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/Banning.cs @@ -46,16 +46,24 @@ private static IEnumerable Transpiler(IEnumerable Transpiler(IEnumerable Transpiler(IEnumerable Transpiler(IEnumerable Date: Mon, 17 Feb 2025 19:02:24 +0200 Subject: [PATCH 16/24] fix: OnShooting target freeze (#438) initial --- .../Patches/Events/Player/Shooting.cs | 66 ++++++++++++------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/EXILED/Exiled.Events/Patches/Events/Player/Shooting.cs b/EXILED/Exiled.Events/Patches/Events/Player/Shooting.cs index 501c1f812b..7fe54c41a3 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/Shooting.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/Shooting.cs @@ -7,6 +7,7 @@ namespace Exiled.Events.Patches.Events.Player { + using System; using System.Collections.Generic; using System.Reflection; using System.Reflection.Emit; @@ -34,8 +35,6 @@ private static IEnumerable Transpiler(IEnumerable newInstructions = ListPool.Pool.Get(instructions); Label returnLabel = generator.DefineLabel(); - Label continueLabel1 = generator.DefineLabel(); - Label continueLabel2 = generator.DefineLabel(); /* [] <= Here @@ -59,37 +58,60 @@ private static IEnumerable Transpiler(IEnumerable - new[] - { - // ShootingEventArgs ev = new(firearm, this) - new(OpCodes.Ldarg_1), - new(OpCodes.Ldarg_0), - new(OpCodes.Newobj, constructorInfo), + // Handlers.Player.OnShooting(ev) + new(OpCodes.Dup), // Dup to keep ev on the stack + new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnShooting))), - // Handlers.Player.OnShooting(ev) - new(OpCodes.Dup), // Dup to keep ev on the stack - new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnShooting))), + // if (!ev.IsAllowed) return + new(OpCodes.Callvirt, PropertyGetter(typeof(ShootingEventArgs), nameof(ShootingEventArgs.IsAllowed))), + new(OpCodes.Brtrue_S, continueLabel2), - // if (!ev.IsAllowed) return - new(OpCodes.Callvirt, PropertyGetter(typeof(ShootingEventArgs), nameof(ShootingEventArgs.IsAllowed))), - new(OpCodes.Brtrue_S, continueLabel), - new(OpCodes.Leave_S, returnLabel), + // Dispose target FpcBacktracker + new(OpCodes.Ldloc_S, 5), + new(OpCodes.Callvirt, Method(typeof(IDisposable), nameof(IDisposable.Dispose))), - new CodeInstruction(OpCodes.Nop).WithLabels(continueLabel), - }; + new(OpCodes.Leave_S, returnLabel), + new CodeInstruction(OpCodes.Nop).WithLabels(continueLabel2), + }; newInstructions.InsertRange( // noTargetIndex goes first because it's higher then hasTargetIndex so it won't mess it up noTargetIndex, - patchInstructions1); + noTargetInstructions); newInstructions[noTargetIndex].WithLabels(noTargetLabels); newInstructions.InsertRange( hasTargetIndex, - patchInstructions2); + hasTargetInstructions); newInstructions[newInstructions.Count - 1].WithLabels(returnLabel); From 57d043f3eb1763dee60f32ddbeb17103b36922f0 Mon Sep 17 00:00:00 2001 From: Banalny-Banan <133122450+Banalny-Banan@users.noreply.github.com> Date: Mon, 17 Feb 2025 19:03:48 +0200 Subject: [PATCH 17/24] fix: randomized firearm attachments (#430) * first * backward compatibility --- EXILED/Exiled.API/Features/Items/Firearm.cs | 27 +++++++++---------- .../Features/Pickups/FirearmPickup.cs | 22 +++++++-------- .../Patches/Generic/FirearmDistribution.cs | 27 ------------------- 3 files changed, 24 insertions(+), 52 deletions(-) delete mode 100644 EXILED/Exiled.Events/Patches/Generic/FirearmDistribution.cs diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs index 663144ff8f..eeee66adcd 100644 --- a/EXILED/Exiled.API/Features/Items/Firearm.cs +++ b/EXILED/Exiled.API/Features/Items/Firearm.cs @@ -364,30 +364,29 @@ public static Firearm Create(FirearmType type) /// The to add. public void AddAttachment(AttachmentIdentifier identifier) { - uint toRemove = 0; - uint code = 1; + // Fallback addedCode onto AvailableAttachments' code in case it's 0 + uint addedCode = identifier.Code == 0 + ? AvailableAttachments[FirearmType].FirstOrDefault(attId => attId.Name == identifier.Name).Code + : identifier.Code; + + // Look for conflicting attachment (attachment that occupies the same slot) + uint conflicting = 0; + uint current = 1; foreach (Attachment attachment in Base.Attachments) { if (attachment.Slot == identifier.Slot && attachment.IsEnabled) { - toRemove = code; + conflicting = current; break; } - code *= 2; + current *= 2; } - uint newCode = identifier.Code == 0 - ? AvailableAttachments[FirearmType].FirstOrDefault( - attId => - attId.Name == identifier.Name).Code - : identifier.Code; - - Base.ApplyAttachmentsCode((Base.GetCurrentAttachmentsCode() & ~toRemove) | newCode, true); - - // TODO Not finish - // Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags, Base.GetCurrentAttachmentsCode()); + uint code = Base.ValidateAttachmentsCode((Base.GetCurrentAttachmentsCode() & ~conflicting) | addedCode); + Base.ApplyAttachmentsCode(code, false); + AttachmentCodeSync.ServerSetCode(Serial, code); } /// diff --git a/EXILED/Exiled.API/Features/Pickups/FirearmPickup.cs b/EXILED/Exiled.API/Features/Pickups/FirearmPickup.cs index feb8d4c57e..b1534a0ef8 100644 --- a/EXILED/Exiled.API/Features/Pickups/FirearmPickup.cs +++ b/EXILED/Exiled.API/Features/Pickups/FirearmPickup.cs @@ -7,6 +7,8 @@ namespace Exiled.API.Features.Pickups { + using System; + using Exiled.API.Interfaces; using InventorySystem.Items; @@ -56,7 +58,8 @@ internal FirearmPickup(ItemType type) /// /// Gets a value indicating whether the pickup is already distributed. /// - public bool IsDistributed { get; internal set; } + [Obsolete("Feature deprecated")] + public bool IsDistributed { get; } /// /// Gets or sets a value indicating how much ammo can contain this . @@ -104,7 +107,7 @@ public int Ammo } /// - /// Gets or sets a ammo drain per shoot. + /// Gets or sets the ammo drain per shoot. /// /// /// Always by default. @@ -121,19 +124,16 @@ public uint Attachments set => Base.Worldmodel.Setup(Base.CurId, Base.Worldmodel.WorldmodelType, value); } - /// - public override void Spawn() - { - base.Spawn(); - if (!IsDistributed) - Base.OnDistributed(); - } + /// + /// Initializes the item as if it was spawned naturally by map generation. + /// + public void Distribute() => Base.OnDistributed(); /// - /// Returns the FirearmPickup in a human readable format. + /// Returns the FirearmPickup in a human-readable format. /// /// A string containing FirearmPickup related data. - public override string ToString() => $"{Type} ({Serial}) [{Weight}] *{Scale}* |{IsDistributed}| -{/*Ammo*/0}-"; + public override string ToString() => $"{Type} ({Serial}) [{Weight}] *{Scale}*"; /// internal override void ReadItemInfo(Items.Item item) diff --git a/EXILED/Exiled.Events/Patches/Generic/FirearmDistribution.cs b/EXILED/Exiled.Events/Patches/Generic/FirearmDistribution.cs deleted file mode 100644 index 30deefa442..0000000000 --- a/EXILED/Exiled.Events/Patches/Generic/FirearmDistribution.cs +++ /dev/null @@ -1,27 +0,0 @@ -// ----------------------------------------------------------------------- -// -// Copyright (c) ExMod Team. All rights reserved. -// Licensed under the CC BY-SA 3.0 license. -// -// ----------------------------------------------------------------------- - -namespace Exiled.Events.Patches.Generic -{ -#pragma warning disable SA1313 - using Exiled.API.Features.Pickups; - using HarmonyLib; - - using BaseFirearm = InventorySystem.Items.Firearms.FirearmPickup; - - /// - /// Patch to add . - /// - [HarmonyPatch(typeof(BaseFirearm), nameof(BaseFirearm.OnDistributed))] - internal static class FirearmDistribution - { - private static void Postfix(BaseFirearm __instance) - { - Pickup.Get(__instance).IsDistributed = true; - } - } -} \ No newline at end of file From 9be51adf9074c7605395c11fb45390fab730607c Mon Sep 17 00:00:00 2001 From: Num1ock <71600441+Num10ck@users.noreply.github.com> Date: Tue, 18 Feb 2025 17:32:23 +0400 Subject: [PATCH 18/24] feat: Added method `Exiled.API.Features.Map.Clean` (#437) --- EXILED/Exiled.API/Features/Map.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/EXILED/Exiled.API/Features/Map.cs b/EXILED/Exiled.API/Features/Map.cs index c51fd1665b..4a953744f2 100644 --- a/EXILED/Exiled.API/Features/Map.cs +++ b/EXILED/Exiled.API/Features/Map.cs @@ -13,6 +13,8 @@ namespace Exiled.API.Features using System.Collections.ObjectModel; using System.Linq; + using CommandSystem.Commands.RemoteAdmin.Cleanup; + using Decals; using Enums; using Exiled.API.Extensions; using Exiled.API.Features.Hazards; @@ -27,6 +29,7 @@ namespace Exiled.API.Features using PlayerRoles.Ragdolls; using UnityEngine; using Utils; + using Utils.Networking; using Object = UnityEngine.Object; @@ -271,6 +274,19 @@ public static void CleanAllRagdolls(IEnumerable ragDolls) ragDoll.Destroy(); } + /// + /// Destroy specified amount of specified object. + /// + /// Decal type to destroy. + /// Amount of decals to destroy. + public static void Clean(DecalPoolType decalType, int amount) => new DecalCleanupMessage(decalType, amount).SendToAuthenticated(); + + /// + /// Destroy all specified objects. + /// + /// Decal type to destroy. + public static void Clean(DecalPoolType decalType) => Clean(decalType, int.MaxValue); + /// /// Places a blood decal. /// From 95d2d54bcc9f61ac4be7b569d36cbce48e9b8ad8 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Sat, 22 Feb 2025 00:08:44 +0100 Subject: [PATCH 19/24] fix: Fix NW Hypothermia bug (#441) Fix NW Hypothermia bug --- EXILED/Exiled.Events/Handlers/Internal/Round.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/EXILED/Exiled.Events/Handlers/Internal/Round.cs b/EXILED/Exiled.Events/Handlers/Internal/Round.cs index 87d5d2a2ca..99212af062 100644 --- a/EXILED/Exiled.Events/Handlers/Internal/Round.cs +++ b/EXILED/Exiled.Events/Handlers/Internal/Round.cs @@ -27,6 +27,7 @@ namespace Exiled.Events.Handlers.Internal using InventorySystem.Items.Firearms.Attachments; using InventorySystem.Items.Firearms.Attachments.Components; using InventorySystem.Items.Usables; + using InventorySystem.Items.Usables.Scp244.Hypothermia; using PlayerRoles; using PlayerRoles.RoleAssign; using Utils.NonAllocLINQ; @@ -105,6 +106,12 @@ public static void OnVerified(VerifiedEventArgs ev) ev.Player.SendFakeSyncVar(room.RoomLightControllerNetIdentity, typeof(RoomLightController), nameof(RoomLightController.NetworkLightsEnabled), true); ev.Player.SendFakeSyncVar(room.RoomLightControllerNetIdentity, typeof(RoomLightController), nameof(RoomLightController.NetworkLightsEnabled), false); } + + // TODO: Remove if this has been fixed for https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/947 + if (ev.Player.TryGetEffect(out Hypothermia hypothermia)) + { + hypothermia.SubEffects = hypothermia.SubEffects.Where(x => x.GetType() != typeof(PostProcessSubEffect)).ToArray(); + } } private static void GenerateAttachments() From 1f28777f2ef4e9abc0cc3a843b77a2b9aa757136 Mon Sep 17 00:00:00 2001 From: TtroubleTT <121741230+TtroubleTT@users.noreply.github.com> Date: Tue, 25 Feb 2025 04:08:39 -0800 Subject: [PATCH 20/24] feat: Have NPC In Player List (#445) npc are in player list --- EXILED/Exiled.API/Features/Player.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/Exiled.API/Features/Player.cs b/EXILED/Exiled.API/Features/Player.cs index ada3c952af..498f7c0c1f 100644 --- a/EXILED/Exiled.API/Features/Player.cs +++ b/EXILED/Exiled.API/Features/Player.cs @@ -138,7 +138,7 @@ public Player(GameObject gameObject) /// /// Gets a list of all 's on the server. /// - public static IReadOnlyCollection List => Dictionary.Values.Where(x => !x.IsNPC).ToList(); + public static IReadOnlyCollection List => Dictionary.Values.ToList(); /// /// Gets a containing cached and their user ids. From f6cd7d6be1ec2ab76d03dfa908180cfcf8978ebc Mon Sep 17 00:00:00 2001 From: Num1ock <71600441+Num10ck@users.noreply.github.com> Date: Tue, 25 Feb 2025 16:09:54 +0400 Subject: [PATCH 21/24] feat: Spawning NPCs via RA adds them to the `Npc.List` (#440) * feat: Spawning NPCs via RA adds them to the `Npc.List` * Update RemoteAdminNpcCommandAddToDictionaryFix.cs RemoteAdminNpcCommandAddToDictionaryFix is now static. * Code style changes. Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com> * Documentation fix. --------- Co-authored-by: Yamato <66829532+louis1706@users.noreply.github.com> --- ...RemoteAdminNpcCommandAddToDictionaryFix.cs | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 EXILED/Exiled.Events/Patches/Fixes/RemoteAdminNpcCommandAddToDictionaryFix.cs diff --git a/EXILED/Exiled.Events/Patches/Fixes/RemoteAdminNpcCommandAddToDictionaryFix.cs b/EXILED/Exiled.Events/Patches/Fixes/RemoteAdminNpcCommandAddToDictionaryFix.cs new file mode 100644 index 0000000000..cb7b867f77 --- /dev/null +++ b/EXILED/Exiled.Events/Patches/Fixes/RemoteAdminNpcCommandAddToDictionaryFix.cs @@ -0,0 +1,70 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.Patches.Fixes +{ + using System.Collections.Generic; + using System.Reflection; + using System.Reflection.Emit; + + using CommandSystem.Commands.RemoteAdmin.Dummies; + using Exiled.API.Features; + using Exiled.API.Features.Pools; + using GameCore; + using HarmonyLib; + using UnityEngine; + + using static HarmonyLib.AccessTools; + + /// + /// Fix to add created via RA to the . + /// + [HarmonyPatch(typeof(SpawnDummyCommand), nameof(SpawnDummyCommand.Execute))] + internal static class RemoteAdminNpcCommandAddToDictionaryFix + { + private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) + { + List newInstructions = ListPool.Pool.Get(instructions); + + MethodBase method = Method(typeof(DummyUtils), nameof(DummyUtils.SpawnDummy)); + + // call ReferenceHub GameCore.DummyUtils::SpawnDummy(string) + int index = newInstructions.FindIndex(instruction => + instruction.operand == (object)method) + 1; + + LocalBuilder npc = generator.DeclareLocal(typeof(Npc)); + + // pop + newInstructions.RemoveAt(index); + + newInstructions.InsertRange( + index, + new CodeInstruction[] + { + // Npc::.ctor(ReferenceHub) + new(OpCodes.Newobj, Constructor(typeof(Npc), new[] { typeof(ReferenceHub) })), + new(OpCodes.Stloc_S, npc.LocalIndex), + + // Player.Dictionary.get_Dictionary + new(OpCodes.Call, PropertyGetter(typeof(Player), nameof(Player.Dictionary))), + new(OpCodes.Ldloc_S, npc.LocalIndex), + + // Player::GameObject.get_GameObject + new(OpCodes.Callvirt, PropertyGetter(typeof(Player), nameof(Player.GameObject))), + new(OpCodes.Ldloc_S, npc.LocalIndex), + + // Player.Dictionary.Add(GameObject, ReferenceHub) + new(OpCodes.Callvirt, Method(typeof(Dictionary), nameof(Dictionary.Add))), + }); + + for (int i = 0; i < newInstructions.Count; i++) + yield return newInstructions[i]; + + ListPool.Pool.Return(newInstructions); + } + } +} From 8485d8f971d566fa096f7607ad7c2421a4701baf Mon Sep 17 00:00:00 2001 From: R2kip <56793105+R2kip@users.noreply.github.com> Date: Tue, 25 Feb 2025 15:10:07 +0300 Subject: [PATCH 22/24] fix: IntercomSpeaking event (#442) * Fix IntercomSpeaking event * ops --- .../Patches/Events/Player/IntercomSpeaking.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/EXILED/Exiled.Events/Patches/Events/Player/IntercomSpeaking.cs b/EXILED/Exiled.Events/Patches/Events/Player/IntercomSpeaking.cs index 902b3d7ed6..08542cd432 100644 --- a/EXILED/Exiled.Events/Patches/Events/Player/IntercomSpeaking.cs +++ b/EXILED/Exiled.Events/Patches/Events/Player/IntercomSpeaking.cs @@ -38,15 +38,14 @@ private static IEnumerable Transpiler(IEnumerable instruction.Calls(Method(typeof(Stopwatch), nameof(Stopwatch.Restart)))) + offset; + int index = newInstructions.FindIndex(instruction => instruction.StoresField(Field(typeof(Intercom), nameof(Intercom._curSpeaker)))) + offset; newInstructions.InsertRange( index, new CodeInstruction[] { - // Player.Get(this._curSpeaker) - new(OpCodes.Ldarg_0), - new(OpCodes.Ldfld, Field(typeof(Intercom), nameof(Intercom._curSpeaker))), + // Player.Get(first) + new(OpCodes.Ldloc_1), new(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })), // true @@ -73,4 +72,4 @@ private static IEnumerable Transpiler(IEnumerable.Pool.Return(newInstructions); } } -} \ No newline at end of file +} From 6885df86a6b25449ad16b20b94cdc7327c88f075 Mon Sep 17 00:00:00 2001 From: Yamato Date: Wed, 26 Feb 2025 13:21:02 +0100 Subject: [PATCH 23/24] 9.5.1 --- EXILED/EXILED.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXILED/EXILED.props b/EXILED/EXILED.props index 45f9709b8e..641692ba4d 100644 --- a/EXILED/EXILED.props +++ b/EXILED/EXILED.props @@ -15,7 +15,7 @@ - 9.5.0 + 9.5.1 false From 7e326a0e7df7cb599e0603153fd1c141eba6868e Mon Sep 17 00:00:00 2001 From: hatulaile <158590752+hatulaile@users.noreply.github.com> Date: Thu, 27 Feb 2025 14:14:38 +0800 Subject: [PATCH 24/24] feat: Added a list of players who are turned away from SCP-939 AmnesticCloud (#446) --- .../Exiled.API/Features/Roles/Scp939Role.cs | 5 ++ EXILED/Exiled.Events/Config.cs | 6 ++ .../Exiled.Events/Handlers/Internal/Round.cs | 1 + .../Patches/Generic/StayAtAmnesticCloud.cs | 85 +++++++++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 EXILED/Exiled.Events/Patches/Generic/StayAtAmnesticCloud.cs diff --git a/EXILED/Exiled.API/Features/Roles/Scp939Role.cs b/EXILED/Exiled.API/Features/Roles/Scp939Role.cs index 4396f8f87b..65ab01864a 100644 --- a/EXILED/Exiled.API/Features/Roles/Scp939Role.cs +++ b/EXILED/Exiled.API/Features/Roles/Scp939Role.cs @@ -90,6 +90,11 @@ internal Scp939Role(Scp939GameRole baseRole) /// ~Scp939Role() => ListPool.Pool.Return(VisiblePlayers); + /// + /// Gets a list of players who are turned away from SCP-939 AmnesticCloud Ability. + /// + public static HashSet TurnedPlayers { get; } = new(20); + /// public override RoleTypeId Type { get; } = RoleTypeId.Scp939; diff --git a/EXILED/Exiled.Events/Config.cs b/EXILED/Exiled.Events/Config.cs index 56a8206e74..5559774efa 100644 --- a/EXILED/Exiled.Events/Config.cs +++ b/EXILED/Exiled.Events/Config.cs @@ -44,6 +44,12 @@ public sealed class Config : IConfig [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-939 Amnestic Cloud. + /// + [Description("Indicates whether Tutorial is affected by Scp-939 Amnestic Cloud")] + public bool TutorialAffectedByScp939AmnesticCloud { get; set; } = true; + /// /// Gets or sets a value indicating whether tutorial is affected by SCP-079 scan. /// diff --git a/EXILED/Exiled.Events/Handlers/Internal/Round.cs b/EXILED/Exiled.Events/Handlers/Internal/Round.cs index 99212af062..2091870dfa 100644 --- a/EXILED/Exiled.Events/Handlers/Internal/Round.cs +++ b/EXILED/Exiled.Events/Handlers/Internal/Round.cs @@ -62,6 +62,7 @@ public static void OnRestartingRound() Scp173Role.TurnedPlayers.Clear(); Scp096Role.TurnedPlayers.Clear(); Scp079Role.TurnedPlayers.Clear(); + Scp939Role.TurnedPlayers.Clear(); MultiAdminFeatures.CallEvent(MultiAdminFeatures.EventType.ROUND_END); diff --git a/EXILED/Exiled.Events/Patches/Generic/StayAtAmnesticCloud.cs b/EXILED/Exiled.Events/Patches/Generic/StayAtAmnesticCloud.cs new file mode 100644 index 0000000000..6541c383f3 --- /dev/null +++ b/EXILED/Exiled.Events/Patches/Generic/StayAtAmnesticCloud.cs @@ -0,0 +1,85 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- + +namespace Exiled.Events.Patches.Generic +{ + using System.Collections.Generic; + using System.Reflection.Emit; + + using Exiled.API.Features; + using Exiled.API.Features.Pools; + using HarmonyLib; + using PlayerRoles; + using PlayerRoles.PlayableScps.Scp939; + + using static HarmonyLib.AccessTools; + + using ExiledEvents = Exiled.Events.Events; + using Scp939Role = API.Features.Roles.Scp939Role; + + /// + /// Patches . + /// . + /// + [HarmonyPatch(typeof(Scp939AmnesticCloudInstance), nameof(Scp939AmnesticCloudInstance.OnStay))] + internal static class StayAtAmnesticCloud + { + private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator) + { + List newInstructions = ListPool.Pool.Get(instructions); + + Label continueLabel = generator.DefineLabel(); + + Label returnLabel = generator.DefineLabel(); + + // Second check pointer + // We use it to pass execution + // to the second check if the first check fails, + // otherwise the second check won't be executed + Label secondCheckPointer = generator.DefineLabel(); + + newInstructions[0].WithLabels(continueLabel); + + // if (referenceHub.roleManager.CurrentRole.RoleTypeId == RoleTypeId.Tutorial && ExiledEvents.Instance.Config.TutorialAffectedByScp939AmnesticCloud + // || Scp939Role.TurnedPlayers.Contains(Player.Get(referenceHub))) + // return; + newInstructions.InsertRange( + 0, + new[] + { + // if ((referenceHub.roleManager.CurrentRole.RoleTypeId == RoleTypeId.Tutorial && + new(OpCodes.Ldarg_1), + new(OpCodes.Ldfld, Field(typeof(ReferenceHub), nameof(ReferenceHub.roleManager))), + new(OpCodes.Callvirt, PropertyGetter(typeof(PlayerRoleManager), nameof(PlayerRoleManager.CurrentRole))), + new(OpCodes.Callvirt, PropertyGetter(typeof(PlayerRoleBase), nameof(PlayerRoleBase.RoleTypeId))), + new(OpCodes.Ldc_I4_S, (sbyte)RoleTypeId.Tutorial), + new(OpCodes.Bne_Un_S, secondCheckPointer), + + // ExiledEvents.Instance.Config.TutorialAffectedByScp939AmnesticCloud) + new(OpCodes.Call, PropertyGetter(typeof(ExiledEvents), nameof(ExiledEvents.Instance))), + new(OpCodes.Callvirt, PropertyGetter(typeof(Plugin), nameof(Plugin.Config))), + new(OpCodes.Callvirt, PropertyGetter(typeof(Config), nameof(Config.TutorialAffectedByScp939AmnesticCloud))), + new(OpCodes.Brtrue_S, returnLabel), + + // || Scp939Role.TurnedPlayers.Contains(Player.Get(referenceHub)) + new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(Scp939Role), nameof(Scp939Role.TurnedPlayers))).WithLabels(secondCheckPointer), + 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))), + new(OpCodes.Brfalse_S, continueLabel), + + // return; + new CodeInstruction(OpCodes.Ret).WithLabels(returnLabel), + }); + + for (int i = 0; i < newInstructions.Count; i++) + yield return newInstructions[i]; + + ListPool.Pool.Return(newInstructions); + } + } +} \ No newline at end of file