Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SaveCrossbowStateIncludeHook v1.0.0
SaveCrossbowStateIncludeHook.dll
Decompiled a day agousing System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("SaveCrossbowStateIncludeHook")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SaveCrossbowStateIncludeHook")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("20f1c208-37ae-4ce8-910c-93b4ea342dc5")] [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 SaveCrossbowStateIncludeHook; [BepInPlugin("Pan_kapkan.SaveCrossbowStateIncludeHook", "SaveCrossbowStateIncludeHook", "1.0.0")] [BepInIncompatibility("Azumatt.SaveCrossbowState")] public class SaveCrossbowStateIncludeHookPlugin : BaseUnityPlugin { internal const string ModName = "SaveCrossbowStateIncludeHook"; internal const string ModVersion = "1.0.0"; internal const string Author = "Pan_kapkan"; private const string ModGUID = "Pan_kapkan.SaveCrossbowStateIncludeHook"; public const string CrossbowLoaded = "crossbowLoaded"; public const string CrossbowLoadedChanged = "crossbowLoaded_changed"; private const string GrapplingHookPrefabName = "GrapplingHook"; private readonly Harmony _harmony = new Harmony("Pan_kapkan.SaveCrossbowStateIncludeHook"); internal static ManualLogSource Log; internal static ConfigEntry<bool> DebugLogging; public void Awake() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 Log = ((BaseUnityPlugin)this).Logger; DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Write item details (prefab, skill, reload state) to the BepInEx log when a reloadable item is unequipped or fired. Useful for troubleshooting."); if ((int)SystemInfo.graphicsDeviceType == 4) { Log.LogWarning((object)"This mod is client-side only and is not needed on a dedicated server. Plugin patches will not be applied."); } else { _harmony.PatchAll(Assembly.GetExecutingAssembly()); } } public void OnDestroy() { _harmony.UnpatchSelf(); } public static bool IsGrapplingHook(ItemData item) { return item != null && (Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == "GrapplingHook"; } public static bool IsCrossbowItem(ItemData item) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 if (item == null || item.m_shared == null) { return false; } if (IsGrapplingHook(item)) { return true; } SkillType skillType = item.m_shared.m_skillType; SkillType val = skillType; if ((int)val == 9 || (int)val == 14) { return true; } return false; } internal static void DebugLog(string where, ItemData item, bool tracked) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if (DebugLogging != null && DebugLogging.Value && item != null && item.m_shared != null) { bool flag = item.m_shared.m_attack?.m_requiresReload ?? false; if (tracked || flag) { string text = (((Object)(object)item.m_dropPrefab != (Object)null) ? ((Object)item.m_dropPrefab).name : "(none)"); Log.LogInfo((object)$"{where}: prefab={text}, skill={item.m_shared.m_skillType}, itemType={item.m_shared.m_itemType}, requiresReload={flag}, tracked={tracked}"); } } } } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] internal static class CheckIfCrossbowWasUnequipped { private static void Prefix(Humanoid __instance, ItemData item) { Player localPlayer = Player.m_localPlayer; if (item == null || (Object)(object)localPlayer == (Object)null || (Object)(object)__instance != (Object)(object)localPlayer || Traverse.Create((object)localPlayer).Field("m_isLoading").GetValue<bool>()) { return; } bool flag = SaveCrossbowStateIncludeHookPlugin.IsCrossbowItem(item); bool flag2 = flag && ((Humanoid)localPlayer).IsWeaponLoaded(); SaveCrossbowStateIncludeHookPlugin.DebugLog("Unequip (weaponLoaded=" + flag2 + ")", item, flag); if (flag2) { item.m_customData["crossbowLoaded"] = "true"; if (item.m_shared.m_attack.m_requiresReload) { item.m_customData["crossbowLoaded_changed"] = "true"; item.m_shared.m_attack.m_requiresReload = false; } } } } [HarmonyPatch(typeof(Attack), "OnAttackTrigger")] internal static class ResetLoaded { private static void Prefix(Humanoid ___m_character) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)___m_character == (Object)null || (Object)(object)localPlayer == (Object)null || (Object)(object)___m_character != (Object)(object)localPlayer) { return; } ItemData currentWeapon = ___m_character.GetCurrentWeapon(); if (SaveCrossbowStateIncludeHookPlugin.IsCrossbowItem(currentWeapon)) { SaveCrossbowStateIncludeHookPlugin.DebugLog("Attack", currentWeapon, tracked: true); currentWeapon.m_customData["crossbowLoaded"] = "false"; bool result = default(bool); if (currentWeapon.m_customData.TryGetValue("crossbowLoaded_changed", out var value) && bool.TryParse(value, out result) && result) { currentWeapon.m_customData.Remove("crossbowLoaded_changed"); currentWeapon.m_shared.m_attack.m_requiresReload = true; } } } }