Decompiled source of CrossbowSprintReload v1.1.1

CrossbowSprintReload.dll

Decompiled 17 hours ago
using 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)
		{
		}
	}
}