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 CrossbowSprintReload v1.1.1
CrossbowSprintReload.dll
Decompiled 17 hours agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Valheim Overhaul")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Reload crossbows while sprinting (vanilla speed); slightly faster reload while standing or walking.")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1")] [assembly: AssemblyProduct("CrossbowSprintReload")] [assembly: AssemblyTitle("CrossbowSprintReload")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CrossbowSprintReload { internal static class ReloadUtil { internal const string LoadedCustomDataKey = "VO_CrossbowLoaded"; internal static bool ForceWipeReload; internal static int HolsterDepth; private static MethodInfo _setWeaponLoaded; internal static bool IsReloadWeapon(ItemData weapon) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 if (weapon?.m_shared?.m_attack == null || !weapon.m_shared.m_attack.m_requiresReload) { return false; } if ((int)weapon.m_shared.m_skillType == 14) { return true; } return Plugin.AffectDundr.Value; } internal static bool IsKeepLoadedCandidate(ItemData weapon) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 if (weapon?.m_shared?.m_attack == null) { return false; } if ((int)weapon.m_shared.m_skillType == 14) { return true; } if (Plugin.AffectDundr.Value) { return weapon.m_shared.m_attack.m_requiresReload; } return false; } internal static MinorActionData FindReloadAction(Player player) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 if (player?.m_actionQueue == null) { return null; } for (int i = 0; i < player.m_actionQueue.Count; i++) { MinorActionData val = player.m_actionQueue[i]; if (val != null && (int)val.m_type == 2 && IsReloadWeapon(val.m_item)) { return val; } } return null; } internal static bool IsSprintIntent(Player player) { if ((Object)(object)player == (Object)null) { return false; } if (((Character)player).IsRunning()) { return true; } try { if (ZInput.GetButton("Run") || ZInput.GetButton("JoyRun")) { return true; } } catch { try { if (ZInput.GetButton("Run")) { return true; } } catch { } } return false; } internal static void MarkLoaded(ItemData item, bool loaded) { if (item?.m_customData != null) { if (loaded) { item.m_customData["VO_CrossbowLoaded"] = "1"; } else { item.m_customData.Remove("VO_CrossbowLoaded"); } } } internal static bool WasMarkedLoaded(ItemData item) { if (item?.m_customData != null && item.m_customData.TryGetValue("VO_CrossbowLoaded", out var value)) { return value == "1"; } return false; } internal static void SetWeaponLoaded(Player player, ItemData weapon) { if (!((Object)(object)player == (Object)null)) { if (_setWeaponLoaded == null) { _setWeaponLoaded = AccessTools.Method(typeof(Player), "SetWeaponLoaded", new Type[1] { typeof(ItemData) }, (Type[])null); } _setWeaponLoaded?.Invoke(player, new object[1] { weapon }); } } } [HarmonyPatch(typeof(Player), "ClearActionQueue")] internal static class PlayerClearActionQueuePatch { private static bool Prefix(Player __instance) { if (!Plugin.Enabled.Value || !Plugin.AllowSprintReload.Value) { return true; } if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return true; } if (ReloadUtil.ForceWipeReload) { ReloadUtil.ForceWipeReload = false; return true; } MinorActionData val = ReloadUtil.FindReloadAction(__instance); if (val == null) { return true; } __instance.m_actionQueue.Clear(); __instance.m_actionQueue.Add(val); return false; } } [HarmonyPatch(typeof(Player), "OnJump")] internal static class PlayerOnJumpPatch { private static void Prefix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && Plugin.Enabled.Value && !Plugin.AllowJumpReload.Value) { ReloadUtil.ForceWipeReload = true; } } } [HarmonyPatch(typeof(Player), "UpdateActionQueue")] internal static class PlayerUpdateActionQueuePatch { private static void Prefix(Player __instance, float dt) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Invalid comparison between Unknown and I4 if (!Plugin.Enabled.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || dt <= 0f || __instance.m_actionQueue == null || __instance.m_actionQueue.Count == 0) { return; } MinorActionData val = __instance.m_actionQueue[0]; if (val != null && (int)val.m_type == 2 && ReloadUtil.IsReloadWeapon(val.m_item) && !ReloadUtil.IsSprintIntent(__instance)) { float value = Plugin.NonSprintReloadSpeed.Value; if (!(value <= 1.001f)) { val.m_time += dt * (value - 1f); } } } } [HarmonyPatch(typeof(Humanoid), "HideHandItems")] internal static class HumanoidHideHandItemsPatch { private static void Prefix() { ReloadUtil.HolsterDepth++; } private static void Finalizer() { if (ReloadUtil.HolsterDepth > 0) { ReloadUtil.HolsterDepth--; } } } [HarmonyPatch(typeof(Humanoid), "UnequipItem")] internal static class HumanoidUnequipItemPatch { private static void Prefix(Humanoid __instance, ItemData item) { if (Plugin.Enabled.Value && Plugin.KeepLoadedOnHolster.Value && !Plugin.HasSaveCrossbowState && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && item != null && ReloadUtil.IsKeepLoadedCandidate(item)) { if (ReloadUtil.HolsterDepth > 0) { Player localPlayer = Player.m_localPlayer; bool loaded = (Object)(object)localPlayer != (Object)null && ((Humanoid)localPlayer).IsWeaponLoaded() && (((Humanoid)localPlayer).GetCurrentWeapon() == item || ((Humanoid)localPlayer).m_rightItem == item || ((Humanoid)localPlayer).m_leftItem == item); ReloadUtil.MarkLoaded(item, loaded); } else { ReloadUtil.MarkLoaded(item, loaded: false); } } } } [HarmonyPatch(typeof(Humanoid), "EquipItem")] internal static class HumanoidEquipItemPatch { private static void Postfix(Humanoid __instance, ItemData item, bool __result) { if (__result && Plugin.Enabled.Value && Plugin.KeepLoadedOnHolster.Value && !Plugin.HasSaveCrossbowState && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && item != null && ReloadUtil.WasMarkedLoaded(item)) { ReloadUtil.SetWeaponLoaded(Player.m_localPlayer, item); } } } [HarmonyPatch(typeof(Attack), "OnAttackTrigger")] internal static class AttackOnAttackTriggerPatch { private static void Prefix(Attack __instance) { if (Plugin.Enabled.Value && Plugin.KeepLoadedOnHolster.Value && !Plugin.HasSaveCrossbowState && !((Object)(object)__instance?.m_character == (Object)null) && ((Character)__instance.m_character).IsPlayer() && !((Object)(object)__instance.m_character != (Object)(object)Player.m_localPlayer)) { ItemData currentWeapon = __instance.m_character.GetCurrentWeapon(); if (currentWeapon != null) { ReloadUtil.MarkLoaded(currentWeapon, loaded: false); } } } } [BepInPlugin("valheimoverhaul.crossbow.sprintreload", "Crossbow Sprint Reload", "1.1.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "valheimoverhaul.crossbow.sprintreload"; public const string PluginName = "Crossbow Sprint Reload"; public const string PluginVersion = "1.1.1"; internal static Plugin Instance; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> AllowSprintReload; internal static ConfigEntry<bool> AllowJumpReload; internal static ConfigEntry<float> NonSprintReloadSpeed; internal static ConfigEntry<bool> AffectDundr; internal static ConfigEntry<bool> KeepLoadedOnHolster; internal static bool HasSaveCrossbowState; private void Awake() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_011d: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable crossbow sprint reload tweaks."); AllowSprintReload = ((BaseUnityPlugin)this).Config.Bind<bool>("Reload", "Allow Sprint Reload", true, "Keep reloading while sprinting (vanilla cancels reload on sprint)."); AllowJumpReload = ((BaseUnityPlugin)this).Config.Bind<bool>("Reload", "Allow Jump Reload", false, "Keep reloading while jumping (vanilla cancels reload on jump)."); NonSprintReloadSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Reload", "Non-Sprint Reload Speed", 1.5f, new ConfigDescription("Reload speed while standing still or walking/trotting (not sprinting). 1.0 = vanilla, 1.5 = 50% faster, 2.0 = twice as fast.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f), Array.Empty<object>())); AffectDundr = ((BaseUnityPlugin)this).Config.Bind<bool>("Reload", "Affect Dundr", true, "Also apply these rules to Dundr (staff that uses the reload system)."); KeepLoadedOnHolster = ((BaseUnityPlugin)this).Config.Bind<bool>("Reload", "Keep Loaded When Holstered", true, "Keep a loaded bolt only when holstering to the back (R / HideHandItems, e.g. Weapon Holster Overhaul). Fully unequipping or swapping via hotbar clears the load and requires a reload."); HasSaveCrossbowState = Chainloader.PluginInfos.ContainsKey("Azumatt.SaveCrossbowState"); if (HasSaveCrossbowState) { Log.LogInfo((object)"SaveCrossbowState detected — Keep Loaded When Holstered will defer to that mod."); } new Harmony("valheimoverhaul.crossbow.sprintreload").PatchAll(); Log.LogInfo((object)"Crossbow Sprint Reload 1.1.1 loaded."); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }