using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Weapon Durability Loss Multiplier")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Weapon Durability Loss Multiplier")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("a36594ec-9420-44c2-b3b7-b017e7e18ccf")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace WeaponDurabilityLossMultiplier; [BepInPlugin("kumo.sulfur.weapon_durability_loss_multiplier", "Weapon Durability Loss Multiplier", "1.0.0")] public sealed class Plugin : BaseUnityPlugin { [CompilerGenerated] private sealed class d__9 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable instructions; public IEnumerable <>3__instructions; private int 5__1; private IEnumerator <>s__2; private CodeInstruction 5__3; private CodeInstruction 5__4; CodeInstruction IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__9(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } <>s__2 = null; 5__3 = null; 5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__1 = 0; <>s__2 = instructions.GetEnumerator(); <>1__state = -3; goto IL_0124; case 1: <>1__state = -3; 5__1++; 5__4 = null; goto IL_00fa; case 2: { <>1__state = -3; 5__3 = null; goto IL_0124; } IL_0124: if (<>s__2.MoveNext()) { 5__3 = <>s__2.Current; if (IsModifyDurabilityCall(5__3)) { 5__4 = new CodeInstruction(OpCodes.Call, (object)applyMultiplierMethod); 5__4.labels.AddRange(5__3.labels); 5__3.labels.Clear(); <>2__current = 5__4; <>1__state = 1; return true; } goto IL_00fa; } <>m__Finally1(); <>s__2 = null; if (5__1 == 0) { ManualLogSource log = Log; if (log != null) { log.LogError((object)"Transpiler failed: no call to InventoryItem.ModifyDurability(float) was found."); } } else { ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)("Transpiler applied. Injected weapon durability multiplier before ModifyDurability call(s): " + 5__1)); } } return false; IL_00fa: <>2__current = 5__3; <>1__state = 2; return true; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>s__2 != null) { <>s__2.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__9 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__9(0); } d__.instructions = <>3__instructions; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } internal static ManualLogSource Log; internal static ConfigEntry EnableMod; internal static ConfigEntry WeaponDurabilityLossMultiplier; internal static ConfigEntry LogDurabilityChanges; private Harmony harmony; private static MethodInfo modifyDurabilityMethod; private static MethodInfo applyMultiplierMethod; private void Awake() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; EnableMod = ((BaseUnityPlugin)this).Config.Bind("General", "EnableMod", true, "Enable weapon durability loss multiplier."); WeaponDurabilityLossMultiplier = ((BaseUnityPlugin)this).Config.Bind("Weapon", "WeaponDurabilityLossMultiplier", 0.5f, new ConfigDescription("Multiplier applied to final weapon durability loss from shooting. 1.0 = vanilla, 0.5 = half loss, 0 = no loss, 2 = double loss.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 10f), Array.Empty())); LogDurabilityChanges = ((BaseUnityPlugin)this).Config.Bind("Debug", "LogDurabilityChanges", false, "Log adjusted shooting durability loss. Keep false for normal gameplay."); harmony = new Harmony("kumo.sulfur.weapon_durability_loss_multiplier"); Type type = AccessTools.TypeByName("PerfectRandom.Sulfur.Core.Items.InventoryItem"); if (type == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not find type: PerfectRandom.Sulfur.Core.Items.InventoryItem"); return; } MethodInfo methodInfo = AccessTools.Method(type, "TakeDurabilityLossFromShoot", (Type[])null, (Type[])null); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not find method: InventoryItem.TakeDurabilityLossFromShoot()"); return; } modifyDurabilityMethod = AccessTools.Method(type, "ModifyDurability", new Type[1] { typeof(float) }, (Type[])null); if (modifyDurabilityMethod == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not find method: InventoryItem.ModifyDurability(float)"); return; } applyMultiplierMethod = AccessTools.Method(typeof(Plugin), "ApplyWeaponDurabilityLossMultiplier", (Type[])null, (Type[])null); if (applyMultiplierMethod == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not find method: ApplyWeaponDurabilityLossMultiplier(float)"); return; } HarmonyMethod val = new HarmonyMethod(typeof(Plugin).GetMethod("TakeDurabilityLossFromShootTranspiler", BindingFlags.Static | BindingFlags.NonPublic)); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Weapon Durability Loss Multiplier loaded."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Patched InventoryItem.TakeDurabilityLossFromShoot()."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } [IteratorStateMachine(typeof(d__9))] private static IEnumerable TakeDurabilityLossFromShootTranspiler(IEnumerable instructions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__9(-2) { <>3__instructions = instructions }; } private static bool IsModifyDurabilityCall(CodeInstruction instruction) { if (modifyDurabilityMethod == null) { return false; } if (instruction.opcode != OpCodes.Call && instruction.opcode != OpCodes.Callvirt) { return false; } MethodInfo methodInfo = instruction.operand as MethodInfo; if (methodInfo == null) { return false; } return methodInfo == modifyDurabilityMethod; } private static float ApplyWeaponDurabilityLossMultiplier(float durabilityChange) { if (!EnableMod.Value) { return durabilityChange; } if (durabilityChange >= 0f) { return durabilityChange; } float num = WeaponDurabilityLossMultiplier.Value; if (float.IsNaN(num) || float.IsInfinity(num)) { num = 1f; } num = Math.Max(0f, Math.Min(10f, num)); float result = durabilityChange * num; if (LogDurabilityChanges.Value) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("Weapon shooting durability loss adjusted: " + durabilityChange + " -> " + result + " multiplier=" + num)); } } return result; } }