Decompiled source of SprintReloadCancel v1.3.0

SprintReloadCancel.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Agents;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Utils.Collections;
using GTFO.API.Utilities;
using GameData;
using HarmonyLib;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Player;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SprintReloadCancel")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+637799f0a8dec2bbb6735cc9a77b9b3b88cacc46")]
[assembly: AssemblyProduct("SprintReloadCancel")]
[assembly: AssemblyTitle("SprintReloadCancel")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace SprintReloadCancel
{
	internal static class Configuration
	{
		public static bool sprintCancelEnabled = true;

		public static bool aimCancelEnabled = false;

		public static bool shootCancelEnabled = false;

		public static bool swapBuffer = true;

		private static ConfigFile configFile;

		internal static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			configFile = new ConfigFile(Path.Combine(Paths.ConfigPath, "SprintReloadCancel.cfg"), true);
			BindAll(configFile);
			LiveEdit.CreateListener(Paths.ConfigPath, "SprintReloadCancel.cfg", false).FileChanged += new LiveEditEventHandler(OnFileChanged);
		}

		private static void OnFileChanged(LiveEditEventArgs _)
		{
			configFile.Reload();
			sprintCancelEnabled = (bool)configFile["Base Settings", "Sprint to Reload Cancel"].BoxedValue;
			aimCancelEnabled = (bool)configFile["Base Settings", "Aim to Reload Cancel"].BoxedValue;
			shootCancelEnabled = (bool)configFile["Base Settings", "Shoot to Reload Cancel"].BoxedValue;
			swapBuffer = (bool)configFile["Base Settings", "Reload Cancel Swap Buffer"].BoxedValue;
		}

		private static void BindAll(ConfigFile config)
		{
			sprintCancelEnabled = config.Bind<bool>("Base Settings", "Sprint to Reload Cancel", sprintCancelEnabled, "Sprinting will cancel reloads.").Value;
			aimCancelEnabled = config.Bind<bool>("Base Settings", "Aim to Reload Cancel", aimCancelEnabled, "Aiming will cancel reloads.").Value;
			shootCancelEnabled = config.Bind<bool>("Base Settings", "Shoot to Reload Cancel", shootCancelEnabled, "Shooting will cancel reloads.").Value;
			swapBuffer = config.Bind<bool>("Base Settings", "Reload Cancel Swap Buffer", swapBuffer, "After a reload cancel, buffers swap inputs until the next possible time.\nThis can mitigate missed inputs when you attempt to swap weapons right after reload canceling.").Value;
		}
	}
	[BepInPlugin("Dinorush.SprintReloadCancel", "SprintReloadCancel", "1.3.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal sealed class EntryPoint : BasePlugin
	{
		public const string MODNAME = "SprintReloadCancel";

		public override void Load()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			((BasePlugin)this).Log.LogMessage((object)"Loading SprintReloadCancel");
			new Harmony("SprintReloadCancel").PatchAll(typeof(ReloadCancelPatches));
			Configuration.Init();
			((BasePlugin)this).Log.LogMessage((object)"Loaded SprintReloadCancel");
		}
	}
	internal static class ReloadCancelPatches
	{
		private const float SWAP_TIME = 0.2f;

		private static readonly Dictionary<InputAction, InventorySlot> SWAP_ACTIONS = new Dictionary<InputAction, InventorySlot>
		{
			{
				(InputAction)23,
				(InventorySlot)1
			},
			{
				(InputAction)24,
				(InventorySlot)2
			},
			{
				(InputAction)25,
				(InventorySlot)3
			},
			{
				(InputAction)26,
				(InventorySlot)10
			},
			{
				(InputAction)28,
				(InventorySlot)5
			},
			{
				(InputAction)29,
				(InventorySlot)11
			},
			{
				(InputAction)27,
				(InventorySlot)4
			}
		};

		private static float reloadEndTime = 0f;

		[HarmonyPatch(typeof(PLOC_Stand), "Update")]
		[HarmonyWrapSafe]
		[HarmonyPrefix]
		private static void ReloadCancelStand(PLOC_Stand __instance)
		{
			AttemptReloadCancel((PLOC_Base)(object)__instance);
		}

		[HarmonyPatch(typeof(PLOC_Crouch), "Update")]
		[HarmonyWrapSafe]
		[HarmonyPrefix]
		private static void ReloadCancelCrouch(PLOC_Crouch __instance)
		{
			AttemptReloadCancel((PLOC_Base)(object)__instance);
		}

		[HarmonyPatch(typeof(PLOC_Jump), "Update")]
		[HarmonyWrapSafe]
		[HarmonyPrefix]
		private static void ReloadCancelJump(PLOC_Jump __instance)
		{
			AttemptReloadCancel((PLOC_Base)(object)__instance);
		}

		[HarmonyPatch(typeof(ItemEquippable), "TryTriggerReloadAnimationSequence")]
		[HarmonyWrapSafe]
		[HarmonyPostfix]
		public static void TrackReloadTime(ItemEquippable __instance, bool __result)
		{
			if (!__result || (Object)(object)((Item)__instance).Owner == (Object)null || !((Agent)((Item)__instance).Owner).IsLocallyOwned)
			{
				return;
			}
			GearFrontPartDataBlock frontData = __instance.GearPartHolder.FrontData;
			List<WeaponAnimSequenceItem> obj = ((((frontData == null) ? null : frontData.ReloadSequence?.Count).GetValueOrDefault() > 0) ? __instance.GearPartHolder.FrontData.ReloadSequence : __instance.GearPartHolder.StockData.ReloadSequence);
			float triggerTime = obj[obj.Count - 1].TriggerTime;
			float num = __instance.ReloadTime / triggerTime;
			float num2 = 0f;
			Enumerator<WeaponAnimSequenceItem> enumerator = obj.GetEnumerator();
			while (enumerator.MoveNext())
			{
				WeaponAnimSequenceItem current = enumerator.Current;
				if (current.TriggerTime > num2)
				{
					num2 = current.TriggerTime;
				}
			}
			reloadEndTime = Clock.Time + num2 * num;
		}

		private static void AttemptReloadCancel(PLOC_Base ploc)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			PlayerAgent owner = ploc.m_owner;
			if (((Agent)owner).IsLocallyOwned)
			{
				FirstPersonItemHolder fPItemHolder = owner.FPItemHolder;
				bool? obj;
				if (fPItemHolder == null)
				{
					obj = null;
				}
				else
				{
					ItemEquippable wieldedItem = fPItemHolder.WieldedItem;
					obj = ((wieldedItem != null) ? new bool?(!wieldedItem.IsReloading) : null);
				}
				bool? flag = obj;
				if (flag.HasValue && !flag.GetValueOrDefault() && ShouldCancel(owner))
				{
					InventorySlot wieldedSlot = ((PlayerInventoryBase)owner.FPItemHolder.m_inventoryLocal).WieldedSlot;
					owner.FPItemHolder.MeleeAttackShortcut();
					CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(SwapBack(owner, wieldedSlot)), (Action)null);
				}
			}
		}

		private static bool ShouldCancel(PlayerAgent owner)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			if (!Configuration.sprintCancelEnabled || !InputMapper.GetButtonDown.Invoke((InputAction)9, owner.InputFilter) || !owner.Locomotion.InputIsForwardEnoughForRun())
			{
				if (reloadEndTime - 0.2f > Clock.Time)
				{
					if (!Configuration.aimCancelEnabled || !InputMapper.GetButtonDown.Invoke((InputAction)7, owner.InputFilter))
					{
						if (Configuration.shootCancelEnabled)
						{
							return InputMapper.GetButtonDown.Invoke((InputAction)8, owner.InputFilter);
						}
						return false;
					}
					return true;
				}
				return false;
			}
			return true;
		}

		private static IEnumerator SwapBack(PlayerAgent owner, InventorySlot slot)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			yield return null;
			if (owner != null)
			{
				owner.Sync.WantsToWieldSlot(slot, false);
			}
			if (Configuration.swapBuffer)
			{
				CoroutineManager.StartCoroutine(CollectionExtensions.WrapToIl2Cpp(SwapBuffer(owner)), (Action)null);
			}
		}

		private static IEnumerator SwapBuffer(PlayerAgent? owner)
		{
			float endTime = Clock.Time + 0.2f;
			InventorySlot bufferedSlot = (InventorySlot)0;
			bool bufferedPush = false;
			while (Clock.Time < endTime && (Object)(object)owner != (Object)null)
			{
				foreach (KeyValuePair<InputAction, InventorySlot> sWAP_ACTION in SWAP_ACTIONS)
				{
					if (InputMapper.GetButtonDown.Invoke(sWAP_ACTION.Key, owner.InputFilter))
					{
						bufferedSlot = sWAP_ACTION.Value;
						bufferedPush = false;
					}
				}
				if (InputMapper.GetButtonDown.Invoke((InputAction)12, owner.InputFilter))
				{
					bufferedPush = true;
				}
				yield return null;
			}
			if ((Object)(object)owner != (Object)null && (int)((PlayerInventoryBase)owner.FPItemHolder.m_inventoryLocal).WieldedSlot != 8)
			{
				if (bufferedPush)
				{
					owner.FPItemHolder.MeleeAttackShortcut();
				}
				else if ((int)bufferedSlot != 0)
				{
					owner.Sync.WantsToWieldSlot(bufferedSlot, false);
				}
			}
		}
	}
}