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);
}
}