From d809b6622098b14ff8dd52c05a95c7f1e610add1 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Mon, 3 Aug 2026 00:48:09 +0200 Subject: [PATCH 1/3] fix: NWBug on Explosion Armor --- .../Patches/Fixes/FixExplosionArmor.cs | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs diff --git a/EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs b/EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs new file mode 100644 index 000000000..7bea0768d --- /dev/null +++ b/EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs @@ -0,0 +1,113 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) ExMod Team. All rights reserved. +// Licensed under the CC BY-SA 3.0 license. +// +// ----------------------------------------------------------------------- +#pragma warning disable SA1402 // File may only contain a single type + +namespace Exiled.Events.Patches.Fixes +{ + using System; + using System.Collections.Generic; + using System.Reflection.Emit; + using System.Runtime.CompilerServices; + + using Exiled.API.Features.Pools; + + using Footprinting; + + using HarmonyLib; + + using InventorySystem.Items.Armor; + + using PlayerStatsSystem; + + using UnityEngine; + + using static HarmonyLib.AccessTools; + + /// + /// Patches cttor. + /// Fix Explosion damage calculation using Attacker BodyArmor instead of the one from Victim. + /// Bug was already reported to NW (https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/work_items/3243). + /// + [HarmonyPatch(typeof(ExplosionDamageHandler), MethodType.Constructor, new Type[] { typeof(Footprint), typeof(Vector3), typeof(float), typeof(int), typeof(ExplosionType) })] + + internal class FixExplosionArmor + { +#pragma warning disable SA1600 // Elements should be documented + internal static readonly ConditionalWeakTable> Memory = new(); +#pragma warning restore SA1600 // Elements should be documented + + private static IEnumerable Transpiler(IEnumerable instructions) + { + List newInstructions = ListPool.Pool.Get(instructions); + + // remove the "if (armorPenetration == 0) return;" + newInstructions.RemoveRange(0, 5); + + int offset = 0; + int index = newInstructions.FindLastIndex(x => x.LoadsField(Field(typeof(ExplosionDamageHandler), nameof(ExplosionDamageHandler._serverLogsText)))) + offset; + + newInstructions.InsertRange(index, new List() + { + // this.Damage = damage; + new(OpCodes.Ldarg_0), + new(OpCodes.Ldarg_3), + new(OpCodes.Callvirt, PropertySetter(typeof(StandardDamageHandler), nameof(StandardDamageHandler.Damage))), + + // FixExplosionArmor.Memory.Add(this, new StrongBox(value)) + new(OpCodes.Ldfld, Field(typeof(FixExplosionArmor), nameof(FixExplosionArmor.Memory))), + new(OpCodes.Ldarg_0), + new(OpCodes.Ldarga_S, 4), + new(OpCodes.Call, DeclaredConstructor(typeof(StrongBox), new Type[] { typeof(int).MakeGenericType(), }, false)), + new(OpCodes.Callvirt, Method(typeof(ConditionalWeakTable>), nameof(ConditionalWeakTable>.Add))), + }); + for (int z = 0; z < newInstructions.Count; z++) + yield return newInstructions[z]; + + ListPool.Pool.Return(newInstructions); + } + } + + /// + /// Patches . + /// Fix Explosion damage calculation using Attacker BodyArmor instead of the one from Victim. + /// Bug was already reported to NW (https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/work_items/3243). + /// + [HarmonyPatch(typeof(ExplosionDamageHandler), nameof(ExplosionDamageHandler.ApplyDamage))] + internal class FixExplosionArmor2 + { +#pragma warning disable SA1600 // Elements should be documented + internal static float HelperMethod(ExplosionDamageHandler @this, ReferenceHub ply) +#pragma warning restore SA1600 // Elements should be documented + { + if (ply.inventory.TryGetBodyArmor(out BodyArmor bodyArmor) && FixExplosionArmor.Memory.TryGetValue(@this, out StrongBox armorPenetration)) + { + return BodyArmorUtils.ProcessDamage(bodyArmor.VestEfficacy, @this.Damage, armorPenetration.Value); + } + + return @this.Damage; + } + + private static IEnumerable Transpiler(IEnumerable instructions) + { + List newInstructions = ListPool.Pool.Get(instructions); + + newInstructions.InsertRange(0, new List() + { + // base.Damage = FixExplosionArmor2.HelperMethod(this, ply); + new(OpCodes.Ldarg_0), + new(OpCodes.Ldarg_0), + new(OpCodes.Ldarg_1), + new(OpCodes.Call, Method(typeof(FixExplosionArmor2), nameof(FixExplosionArmor2.HelperMethod))), + new(OpCodes.Callvirt, PropertySetter(typeof(StandardDamageHandler), nameof(StandardDamageHandler.Damage))), + }); + for (int z = 0; z < newInstructions.Count; z++) + yield return newInstructions[z]; + + ListPool.Pool.Return(newInstructions); + } + } +} \ No newline at end of file From e2c64b5421134d5ea29658144067d8d5616abffc Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Mon, 3 Aug 2026 01:06:10 +0200 Subject: [PATCH 2/3] fix: All yamato brain moment not writting stuff correctly --- .../Exiled.Events/Patches/Fixes/FixExplosionArmor.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs b/EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs index 7bea0768d..72f1a6832 100644 --- a/EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs +++ b/EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs @@ -47,8 +47,8 @@ private static IEnumerable Transpiler(IEnumerable x.LoadsField(Field(typeof(ExplosionDamageHandler), nameof(ExplosionDamageHandler._serverLogsText)))) + offset; + int offset = 1; + int index = newInstructions.FindLastIndex(x => x.StoresField(Field(typeof(ExplosionDamageHandler), nameof(ExplosionDamageHandler._serverLogsText)))) + offset; newInstructions.InsertRange(index, new List() { @@ -58,14 +58,12 @@ private static IEnumerable Transpiler(IEnumerable), new Type[] { typeof(int).MakeGenericType(), }, false)), + new(OpCodes.Ldarg_S, 4), + new(OpCodes.Newobj, DeclaredConstructor(typeof(StrongBox), new Type[] { typeof(int), }, false)), new(OpCodes.Callvirt, Method(typeof(ConditionalWeakTable>), nameof(ConditionalWeakTable>.Add))), }); - for (int z = 0; z < newInstructions.Count; z++) - yield return newInstructions[z]; ListPool.Pool.Return(newInstructions); } From 75372b5c105cca1c4c1a8c984f05ef558cae5304 Mon Sep 17 00:00:00 2001 From: Yamato <66829532+louis1706@users.noreply.github.com> Date: Mon, 3 Aug 2026 01:10:53 +0200 Subject: [PATCH 3/3] really ? --- EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs b/EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs index 72f1a6832..3561619ba 100644 --- a/EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs +++ b/EXILED/Exiled.Events/Patches/Fixes/FixExplosionArmor.cs @@ -65,6 +65,9 @@ private static IEnumerable Transpiler(IEnumerable>), nameof(ConditionalWeakTable>.Add))), }); + for (int z = 0; z < newInstructions.Count; z++) + yield return newInstructions[z]; + ListPool.Pool.Return(newInstructions); } }