Decompiled source of HexEquipWhileRunning v1.1.3

plugins/EquipWhileRunning.dll

Decompiled 9 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("EquipWhileRunning")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EquipWhileRunning")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("57d83928-d14a-44c1-a89f-9da8067d326d")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace EquipWhileRunning
{
	[BepInPlugin("hex.EquipWhileRunning", "Equip While Running", "1.1.3")]
	public class Plugin : BaseUnityPlugin
	{
		private const string pluginGUID = "hex.EquipWhileRunning";

		private const string pluginName = "Equip While Running";

		private const string pluginVersion = "1.1.3";

		private const float messageCooldown = 0.2f;

		private const KeyCode defaultKeyCode = (KeyCode)288;

		private Harmony _harmony;

		private float _lastMessageTime;

		internal ConfigEntry<bool> IsModEnabled;

		internal ConfigEntry<KeyboardShortcut> ToggleKey;

		internal ConfigEntry<bool> EnableGrapplingHookAutoReload;

		internal ConfigEntry<int> GrapplingHookAutoReloadCooldown;

		internal Player GrapplingHookCooldownPlayer;

		internal float GrapplingHookCooldownStartedAt = float.NegativeInfinity;

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading Equip While Running");
			Instance = this;
			IsModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Allow equip and unequip actions while running");
			ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Key Binds", "ToggleKey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Hotkey to toggle equip while running");
			EnableGrapplingHookAutoReload = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableGrapplingHookAutoReload", true, "Instantly load the grappling hook when equipped, without a reload animation. Reloading after use is unchanged.");
			GrapplingHookAutoReloadCooldown = ((BaseUnityPlugin)this).Config.Bind<int>("General", "GrapplingHookAutoReloadCooldown", 2, new ConfigDescription("Seconds after releasing the grapple before equipping can instantly load the hook. Also applies after firing if no grapple attaches. Auto-loading is blocked while grappling or while the game's reload block is active. Normal reloading is unaffected.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 60), Array.Empty<object>()));
			_harmony = new Harmony("hex.EquipWhileRunning");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Equip While Running 1.1.3 loaded.");
		}

		private void Update()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (Time.timeScale == 0f || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			KeyboardShortcut value = ToggleKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				IsModEnabled.Value = !IsModEnabled.Value;
				if ((Object)(object)MessageHud.instance != (Object)null)
				{
					ShowStatus(IsModEnabled.Value);
				}
			}
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Equip While Running 1.1.3 unloaded.");
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			Instance = null;
		}

		private void ShowStatus(bool isEnabled)
		{
			if (!(Time.time - _lastMessageTime < 0.2f))
			{
				_lastMessageTime = Time.time;
				string text = (isEnabled ? "Equip While Running: ENABLED" : "Equip While Running: DISABLED");
				MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, true);
			}
		}
	}
}
namespace EquipWhileRunning.Patches
{
	[HarmonyPatch(typeof(Humanoid), "EquipItem")]
	public static class HumanoidEquipItemPatch
	{
		private static readonly FieldInfo GrapplingField = AccessTools.Field(typeof(Player), "m_grappling");

		private static readonly FieldInfo BlockReloadField = AccessTools.Field(typeof(Player), "m_blockReload");

		[HarmonyPostfix]
		private static void ReloadGrapplingHookOnEquip(Humanoid __instance, ItemData item, bool __result)
		{
			Plugin instance = Plugin.Instance;
			if (!__result || (Object)(object)instance == (Object)null || !instance.IsModEnabled.Value || !instance.EnableGrapplingHookAutoReload.Value)
			{
				return;
			}
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val != (Object)(object)Player.m_localPlayer) && item != null && !(item.m_shared.m_name != "$item_graplinghook") && ((Humanoid)val).GetCurrentWeapon() == item && !((Humanoid)val).IsWeaponLoaded())
			{
				float num = instance.GrapplingHookAutoReloadCooldown.Value;
				float num2 = (float)GrapplingField.GetValue(val);
				float num3 = (float)BlockReloadField.GetValue(val);
				if (!(num2 > 0f) && !(num3 > 0f) && (!((Object)(object)instance.GrapplingHookCooldownPlayer == (Object)(object)val) || !(Time.time - instance.GrapplingHookCooldownStartedAt < num)))
				{
					val.SetWeaponLoaded(item);
				}
			}
		}
	}
	[HarmonyPatch(typeof(GrapplingPoint), "Break")]
	public static class GrapplingPointBreakPatch
	{
		[HarmonyPrefix]
		private static void StartCooldownBeforeGrappleRelease(Character ___m_character, ZNetView ___m_nview)
		{
			Plugin instance = Plugin.Instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)___m_character == (Object)null) && !((Object)(object)___m_character != (Object)(object)Player.m_localPlayer) && !((Object)(object)___m_nview == (Object)null) && ___m_nview.IsOwner())
			{
				instance.GrapplingHookCooldownPlayer = Player.m_localPlayer;
				instance.GrapplingHookCooldownStartedAt = Time.time;
			}
		}
	}
	[HarmonyPatch(typeof(Attack), "OnAttackTrigger")]
	public static class AttackOnAttackTriggerPatch
	{
		[HarmonyPrefix]
		private static void SaveGrapplingHookBeforeAttack(Attack __instance, Humanoid ___m_character, ref bool __state)
		{
			Player val = (Player)(object)((___m_character is Player) ? ___m_character : null);
			__state = (Object)(object)val != (Object)null && (Object)(object)val == (Object)(object)Player.m_localPlayer && __instance.m_requiresReload && __instance.GetWeapon()?.m_shared.m_name == "$item_graplinghook";
		}

		[HarmonyPostfix]
		private static void StartCooldownAfterGrapplingHookAttack(Humanoid ___m_character, bool __state)
		{
			Plugin instance = Plugin.Instance;
			if (__state && !((Object)(object)instance == (Object)null))
			{
				Player val = (Player)(object)((___m_character is Player) ? ___m_character : null);
				if (!((Object)(object)val == (Object)null) && !((Humanoid)val).IsWeaponLoaded())
				{
					instance.GrapplingHookCooldownPlayer = val;
					instance.GrapplingHookCooldownStartedAt = Time.time;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "CheckRun")]
	public static class PlayerCheckRunPatch
	{
		private static readonly FieldInfo ActionQueueField = AccessTools.Field(typeof(Player), "m_actionQueue");

		[HarmonyPrefix]
		private static void SaveActionsBeforeCheckRun(Player __instance, ref List<MinorActionData> __state)
		{
			__state = null;
			if (!((Object)(object)Plugin.Instance == (Object)null) && Plugin.Instance.IsModEnabled.Value && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ActionQueueField?.GetValue(__instance) is List<MinorActionData> { Count: not 0 } list)
			{
				__state = new List<MinorActionData>(list);
			}
		}

		[HarmonyPostfix]
		private static void RestoreActionsAfterCheckRun(Player __instance, List<MinorActionData> __state)
		{
			if ((Object)(object)Plugin.Instance == (Object)null || !Plugin.Instance.IsModEnabled.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || __state == null || !(ActionQueueField?.GetValue(__instance) is List<MinorActionData> list))
			{
				return;
			}
			foreach (MinorActionData item in __state)
			{
				if (item != null && !list.Contains(item))
				{
					list.Add(item);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "InMinorActionSlowdown")]
	public static class PlayerInMinorActionSlowdownPatch
	{
		[HarmonyPrefix]
		private static bool PreventMinorActionSlowdownWhenRunning(Player __instance, ref bool __result)
		{
			if ((Object)(object)Plugin.Instance == (Object)null || !Plugin.Instance.IsModEnabled.Value)
			{
				return true;
			}
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			if (!((Character)__instance).IsRunning())
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
}