Decompiled source of ArcadeReload v1.0.0

Niko666.ArcadeReload.dll

Decompiled 12 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("Niko666")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Sweep your gun/magazine/clip/speedloader over a quickbelt slot that holds magazine/cartridge/clip/speedloader and the gun/magazine/clip/speedloader reloads itself, arcade style.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Niko666.ArcadeReload")]
[assembly: AssemblyTitle("ArcadeReload")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace Niko666
{
	internal static class AmmoTransfer
	{
		public static bool TryArcadeReload(ReloadTarget target, FVRQuickBeltSlot slot, bool replaceSpentCasings, int maxRounds, int roundOffset, out string report)
		{
			report = null;
			if (!target.IsValid || (Object)(object)slot == (Object)null)
			{
				return false;
			}
			FVRPhysicalObject curObject = slot.CurObject;
			if ((Object)(object)curObject == (Object)null)
			{
				return false;
			}
			bool isSpawnLock = curObject.m_isSpawnLock;
			FVRFireArmMagazine val = (FVRFireArmMagazine)(object)((curObject is FVRFireArmMagazine) ? curObject : null);
			FVRFireArmRound beltRounds = (FVRFireArmRound)(object)((curObject is FVRFireArmRound) ? curObject : null);
			FVRFireArmClip val2 = (FVRFireArmClip)(object)((curObject is FVRFireArmClip) ? curObject : null);
			if (target.IsHeldContainer)
			{
				if ((Object)(object)target.HeldSpeedloader != (Object)null)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						return SpeedloaderFromClip(target, val2, isSpawnLock, maxRounds, roundOffset, out report);
					}
					if ((Object)(object)beltRounds != (Object)null)
					{
						return SpeedloaderFromRounds(target, ref beltRounds, slot, isSpawnLock, maxRounds, roundOffset, out report);
					}
					return false;
				}
				if ((Object)(object)val != (Object)null)
				{
					return HeldFromMagazine(target, val, isSpawnLock, out report);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					return HeldFromClip(target, val2, isSpawnLock, maxRounds, roundOffset, out report);
				}
				if ((Object)(object)beltRounds != (Object)null)
				{
					return HeldFromRounds(target, ref beltRounds, slot, isSpawnLock, maxRounds, roundOffset, out report);
				}
				return false;
			}
			Speedloader val3 = (Speedloader)(object)((curObject is Speedloader) ? curObject : null);
			if ((Object)(object)val3 != (Object)null)
			{
				return LoadCylinderFromSpeedloader(target, val3, isSpawnLock, out report);
			}
			if ((Object)(object)val != (Object)null)
			{
				return BeltMagazineIntoGun(target, val, isSpawnLock, out report);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				return BeltClipIntoGun(target, val2, isSpawnLock, maxRounds, roundOffset, out report);
			}
			if ((Object)(object)beltRounds != (Object)null)
			{
				return BeltRoundsIntoGun(target, ref beltRounds, slot, isSpawnLock, replaceSpentCasings, maxRounds, roundOffset, out report);
			}
			return false;
		}

		private static bool HeldFromMagazine(ReloadTarget target, FVRFireArmMagazine beltMagazine, bool spawnLocked, out string report)
		{
			report = null;
			FVRFireArmMagazine heldMagazine = target.HeldMagazine;
			if ((Object)(object)heldMagazine == (Object)null)
			{
				return false;
			}
			return FillMagazineFromMagazine(target, heldMagazine, beltMagazine, spawnLocked, out report);
		}

		private static bool HeldFromClip(ReloadTarget target, FVRFireArmClip beltClip, bool spawnLocked, int maxRounds, int roundOffset, out string report)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			FVRFireArmMagazine heldMagazine = target.HeldMagazine;
			if ((Object)(object)heldMagazine != (Object)null)
			{
				return FillMagazineFromClip(target, heldMagazine, beltClip, spawnLocked, maxRounds, roundOffset, out report);
			}
			FVRFireArmClip heldClip = target.HeldClip;
			if ((Object)(object)heldClip != (Object)null && heldClip.ClipType == beltClip.ClipType)
			{
				return FillClipFromClip(target, heldClip, beltClip, spawnLocked, maxRounds, roundOffset, out report);
			}
			return false;
		}

		private static bool HeldFromRounds(ReloadTarget target, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, int maxRounds, int roundOffset, out string report)
		{
			report = null;
			FVRFireArmMagazine heldMagazine = target.HeldMagazine;
			if ((Object)(object)heldMagazine != (Object)null)
			{
				return FillMagazineFromRounds(target, heldMagazine, ref beltRounds, slot, spawnLocked, maxRounds, roundOffset, out report);
			}
			FVRFireArmClip heldClip = target.HeldClip;
			if ((Object)(object)heldClip != (Object)null)
			{
				return FillClipFromRounds(target, heldClip, ref beltRounds, slot, spawnLocked, maxRounds, roundOffset, out report);
			}
			return false;
		}

		private static bool SpeedloaderFromRounds(ReloadTarget target, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, int maxRounds, int roundOffset, out string report)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			Speedloader heldSpeedloader = target.HeldSpeedloader;
			if ((Object)(object)heldSpeedloader == (Object)null)
			{
				return false;
			}
			if (beltRounds.RoundType != ReloadTarget.SpeedloaderChamberType(heldSpeedloader))
			{
				return false;
			}
			int num = ReloadTarget.FreeSpeedloaderChambers(heldSpeedloader);
			if (num <= 0)
			{
				return false;
			}
			int num2 = Mathf.Min(num, CountRoundsInStack(beltRounds));
			if (maxRounds > 0 && num2 > maxRounds)
			{
				num2 = maxRounds;
			}
			if (num2 <= 0)
			{
				return false;
			}
			int num3 = 0;
			for (int i = 0; i < num2; i++)
			{
				FireArmRoundClass roundClass;
				if (spawnLocked)
				{
					roundClass = PeekRoundClass(beltRounds, roundOffset + i);
				}
				else if (!TryTakeRound(ref beltRounds, slot, out roundClass))
				{
					break;
				}
				if (!LoadSpeedloaderChamber(heldSpeedloader, roundClass))
				{
					break;
				}
				num3++;
			}
			if (num3 <= 0)
			{
				return false;
			}
			report = num3 + " round(s) from the belt into the speedloader";
			return true;
		}

		private static bool SpeedloaderFromClip(ReloadTarget target, FVRFireArmClip beltClip, bool spawnLocked, int maxRounds, int roundOffset, out string report)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			Speedloader heldSpeedloader = target.HeldSpeedloader;
			if ((Object)(object)heldSpeedloader == (Object)null)
			{
				return false;
			}
			if (beltClip.RoundType != ReloadTarget.SpeedloaderChamberType(heldSpeedloader))
			{
				return false;
			}
			int num = ReloadTarget.FreeSpeedloaderChambers(heldSpeedloader);
			int numRounds = beltClip.m_numRounds;
			if (num <= 0 || numRounds <= 0)
			{
				return false;
			}
			int num2 = Mathf.Min(num, numRounds);
			if (maxRounds > 0 && num2 > maxRounds)
			{
				num2 = maxRounds;
			}
			int num3 = 0;
			for (int i = 0; i < num2; i++)
			{
				FireArmRoundClass roundClass;
				if (spawnLocked)
				{
					int num4 = PeekClipIndex(numRounds, roundOffset + i);
					if (num4 < 0 || num4 >= beltClip.LoadedRounds.Length || beltClip.LoadedRounds[num4] == null)
					{
						break;
					}
					roundClass = beltClip.LoadedRounds[num4].LR_Class;
				}
				else
				{
					if (beltClip.m_numRounds <= 0)
					{
						break;
					}
					roundClass = beltClip.RemoveRoundReturnClass();
				}
				if (!LoadSpeedloaderChamber(heldSpeedloader, roundClass))
				{
					break;
				}
				num3++;
			}
			if (num3 <= 0)
			{
				return false;
			}
			report = num3 + " round(s) from a clip into the speedloader";
			return true;
		}

		private static bool LoadSpeedloaderChamber(Speedloader loader, FireArmRoundClass roundClass)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			List<SpeedloaderChamber> list = (((Object)(object)loader == (Object)null) ? null : loader.Chambers);
			if (list == null)
			{
				return false;
			}
			for (int i = 0; i < list.Count; i++)
			{
				SpeedloaderChamber val = list[i];
				if (!((Object)(object)val == (Object)null) && !val.IsLoaded)
				{
					val.Load(roundClass, true);
					return true;
				}
			}
			return false;
		}

		private static bool BeltMagazineIntoGun(ReloadTarget target, FVRFireArmMagazine beltMagazine, bool spawnLocked, out string report)
		{
			//IL_0031: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			if (target.FireArm is RevolvingShotgun || target.FireArm is GrappleGun)
			{
				return false;
			}
			FVRFireArmMagazine gunMagazine = target.GunMagazine;
			if ((Object)(object)gunMagazine != (Object)null && gunMagazine.MagazineType == beltMagazine.MagazineType && !gunMagazine.IsFull())
			{
				return FillMagazineFromMagazine(target, gunMagazine, beltMagazine, spawnLocked, out report);
			}
			if ((Object)(object)gunMagazine == (Object)null && (int)target.MagazineType != 0 && beltMagazine.MagazineType == target.MagazineType && (Object)(object)target.GetMagMountPos(beltMagazine.IsBeltBox) != (Object)null)
			{
				return InsertMagazine(target, beltMagazine, spawnLocked, out report);
			}
			SecondaryMagazineSlot[] secondarySlots = target.SecondarySlots;
			if (secondarySlots == null)
			{
				return false;
			}
			FVRFireArmMagazine val = FindSecondaryMagazine(secondarySlots, beltMagazine.MagazineType, beltMagazine.RoundType);
			if ((Object)(object)val != (Object)null)
			{
				return FillMagazineFromMagazine(target, val, beltMagazine, spawnLocked, out report);
			}
			if (beltMagazine.MagazineType != target.MagazineType)
			{
				return false;
			}
			int num = FindEmptySecondarySlot(secondarySlots);
			if (num >= 0)
			{
				return InsertMagazineIntoSecondary(target, beltMagazine, num, spawnLocked, out report);
			}
			return false;
		}

		private static bool InsertMagazineIntoSecondary(ReloadTarget target, FVRFireArmMagazine beltMagazine, int slotIndex, bool spawnLocked, out string report)
		{
			report = null;
			if ((Object)(object)target.FireArm == (Object)null)
			{
				return false;
			}
			FVRFireArmMagazine val = beltMagazine;
			if (spawnLocked)
			{
				GameObject val2 = ((FVRPhysicalObject)beltMagazine).DuplicateFromSpawnLock((FVRViveHand)null);
				if ((Object)(object)val2 == (Object)null)
				{
					return false;
				}
				val = val2.GetComponent<FVRFireArmMagazine>();
				if ((Object)(object)val == (Object)null)
				{
					Object.Destroy((Object)(object)val2);
					return false;
				}
			}
			else
			{
				((FVRPhysicalObject)val).ClearQuickbeltState();
			}
			((FVRPhysicalObject)val).m_isSpawnLock = false;
			val.LoadIntoSecondary(target.FireArm, slotIndex);
			SecondaryMagazineSlot[] secondarySlots = target.SecondarySlots;
			if (secondarySlots == null || slotIndex < 0 || slotIndex >= secondarySlots.Length || secondarySlots[slotIndex] == null || (Object)(object)secondarySlots[slotIndex].Magazine != (Object)(object)val)
			{
				return false;
			}
			report = (spawnLocked ? "spawn locked magazine copied into the secondary slot" : "magazine parked in the secondary slot");
			return true;
		}

		private static FVRFireArmMagazine FindSecondaryMagazine(SecondaryMagazineSlot[] secondaries, FireArmMagazineType magazineType, FireArmRoundType roundType)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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)
			for (int i = 0; i < secondaries.Length; i++)
			{
				FVRFireArmMagazine val = ((secondaries[i] == null) ? null : secondaries[i].Magazine);
				if (!((Object)(object)val == (Object)null) && !val.IsFull() && val.MagazineType == magazineType && val.RoundType == roundType)
				{
					return val;
				}
			}
			return null;
		}

		private static int FindEmptySecondarySlot(SecondaryMagazineSlot[] secondaries)
		{
			for (int i = 0; i < secondaries.Length; i++)
			{
				if (secondaries[i] != null && (Object)(object)secondaries[i].Magazine == (Object)null)
				{
					return i;
				}
			}
			return -1;
		}

		private static FVRFireArmMagazine FindMagazineWithSpace(ReloadTarget target, FireArmRoundType roundType)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			FVRFireArmMagazine gunMagazine = target.GunMagazine;
			if ((Object)(object)gunMagazine != (Object)null && gunMagazine.RoundType == roundType && !gunMagazine.IsFull())
			{
				return gunMagazine;
			}
			SecondaryMagazineSlot[] secondarySlots = target.SecondarySlots;
			if (secondarySlots == null)
			{
				return null;
			}
			for (int i = 0; i < secondarySlots.Length; i++)
			{
				FVRFireArmMagazine val = ((secondarySlots[i] == null) ? null : secondarySlots[i].Magazine);
				if ((Object)(object)val != (Object)null && val.RoundType == roundType && !val.IsFull())
				{
					return val;
				}
			}
			return null;
		}

		private static bool BeltClipIntoGun(ReloadTarget target, FVRFireArmClip beltClip, bool spawnLocked, int maxRounds, int roundOffset, out string report)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			FVRFireArmMagazine val = FindMagazineWithSpace(target, beltClip.RoundType);
			if ((Object)(object)val != (Object)null)
			{
				return FillMagazineFromClip(target, val, beltClip, spawnLocked, maxRounds, roundOffset, out report);
			}
			FVRFireArmClip gunClip = target.GunClip;
			if ((Object)(object)gunClip != (Object)null && gunClip.ClipType == beltClip.ClipType)
			{
				return FillClipFromClip(target, gunClip, beltClip, spawnLocked, maxRounds, roundOffset, out report);
			}
			if ((Object)(object)target.GunMagazine == (Object)null && (int)target.ClipType != 0 && !target.IsAttachable && beltClip.ClipType == target.ClipType && (Object)(object)target.ClipMountPos != (Object)null)
			{
				return InsertClip(target, beltClip, spawnLocked, out report);
			}
			return false;
		}

		private static bool BeltRoundsIntoGun(ReloadTarget target, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, bool replaceSpentCasings, int maxRounds, int roundOffset, out string report)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			FVRFireArmMagazine val = FindMagazineWithSpace(target, beltRounds.RoundType);
			if ((Object)(object)val != (Object)null)
			{
				return FillMagazineFromRounds(target, val, ref beltRounds, slot, spawnLocked, maxRounds, roundOffset, out report);
			}
			FVRFireArmClip gunClip = target.GunClip;
			if ((Object)(object)gunClip != (Object)null && gunClip.RoundType == beltRounds.RoundType)
			{
				return FillClipFromRounds(target, gunClip, ref beltRounds, slot, spawnLocked, maxRounds, roundOffset, out report);
			}
			return FillChambers(target, ref beltRounds, slot, spawnLocked, replaceSpentCasings, maxRounds, roundOffset, out report);
		}

		private static bool FillMagazineFromMagazine(ReloadTarget target, FVRFireArmMagazine gunMagazine, FVRFireArmMagazine beltMagazine, bool spawnLocked, out string report)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			if (beltMagazine.RoundType != gunMagazine.RoundType)
			{
				return false;
			}
			int num = gunMagazine.m_capacity - gunMagazine.m_numRounds;
			int numRounds = beltMagazine.m_numRounds;
			if (num <= 0 || numRounds <= 0)
			{
				return false;
			}
			int num2 = Mathf.Min(num, numRounds);
			int num3 = 0;
			for (int i = 0; i < num2; i++)
			{
				FireArmRoundClass lR_Class;
				if (spawnLocked)
				{
					int num4 = beltMagazine.m_numRounds - 1 - i;
					if (num4 < 0 || beltMagazine.LoadedRounds[num4] == null)
					{
						break;
					}
					lR_Class = beltMagazine.LoadedRounds[num4].LR_Class;
				}
				else
				{
					if (beltMagazine.m_numRounds <= 0)
					{
						break;
					}
					FVRLoadedRound val = beltMagazine.RemoveRound(beltMagazine.m_numRounds - 1);
					if (val == null)
					{
						break;
					}
					lR_Class = val.LR_Class;
				}
				gunMagazine.AddRound(lR_Class, false, false);
				num3++;
			}
			if (num3 <= 0)
			{
				return false;
			}
			gunMagazine.UpdateBulletDisplay();
			target.PlayReloadSound();
			report = num3 + " round(s) from a magazine into the magazine";
			return true;
		}

		private static bool FillMagazineFromClip(ReloadTarget target, FVRFireArmMagazine gunMagazine, FVRFireArmClip beltClip, bool spawnLocked, int maxRounds, int roundOffset, out string report)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			if (beltClip.RoundType != gunMagazine.RoundType)
			{
				return false;
			}
			if ((int)target.ClipType != 0 && beltClip.ClipType != target.ClipType)
			{
				return false;
			}
			int num = gunMagazine.m_capacity - gunMagazine.m_numRounds;
			int numRounds = beltClip.m_numRounds;
			if (num <= 0 || numRounds <= 0)
			{
				return false;
			}
			int num2 = Mathf.Min(num, numRounds);
			if (maxRounds > 0 && num2 > maxRounds)
			{
				num2 = maxRounds;
			}
			int num3 = 0;
			for (int i = 0; i < num2; i++)
			{
				FireArmRoundClass val;
				if (spawnLocked)
				{
					int num4 = PeekClipIndex(numRounds, roundOffset + i);
					if (num4 < 0 || num4 >= beltClip.LoadedRounds.Length || beltClip.LoadedRounds[num4] == null)
					{
						break;
					}
					val = beltClip.LoadedRounds[num4].LR_Class;
				}
				else
				{
					if (beltClip.m_numRounds <= 0)
					{
						break;
					}
					val = beltClip.RemoveRoundReturnClass();
				}
				gunMagazine.AddRound(val, false, false);
				num3++;
			}
			if (num3 <= 0)
			{
				return false;
			}
			gunMagazine.UpdateBulletDisplay();
			target.PlayReloadSound();
			report = num3 + " round(s) from a clip into the magazine";
			return true;
		}

		private static bool FillMagazineFromRounds(ReloadTarget target, FVRFireArmMagazine gunMagazine, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, int maxRounds, int roundOffset, out string report)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			if (beltRounds.RoundType != gunMagazine.RoundType)
			{
				return false;
			}
			int num = Mathf.Min(gunMagazine.m_capacity - gunMagazine.m_numRounds, CountRoundsInStack(beltRounds));
			if (maxRounds > 0 && num > maxRounds)
			{
				num = maxRounds;
			}
			if (num <= 0)
			{
				return false;
			}
			int num2 = 0;
			for (int i = 0; i < num; i++)
			{
				FireArmRoundClass roundClass;
				if (spawnLocked)
				{
					roundClass = PeekRoundClass(beltRounds, roundOffset + i);
				}
				else if (!TryTakeRound(ref beltRounds, slot, out roundClass))
				{
					break;
				}
				gunMagazine.AddRound(roundClass, false, false);
				num2++;
			}
			if (num2 <= 0)
			{
				return false;
			}
			gunMagazine.UpdateBulletDisplay();
			target.PlayReloadSound();
			report = num2 + " round(s) from the belt into the magazine";
			return true;
		}

		private static bool FillClipFromClip(ReloadTarget target, FVRFireArmClip gunClip, FVRFireArmClip beltClip, bool spawnLocked, int maxRounds, int roundOffset, out string report)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			if (beltClip.RoundType != gunClip.RoundType)
			{
				return false;
			}
			int num = gunClip.m_capacity - gunClip.m_numRounds;
			int numRounds = beltClip.m_numRounds;
			if (num <= 0 || numRounds <= 0)
			{
				return false;
			}
			int num2 = Mathf.Min(num, numRounds);
			if (maxRounds > 0 && num2 > maxRounds)
			{
				num2 = maxRounds;
			}
			int num3 = 0;
			for (int i = 0; i < num2; i++)
			{
				FireArmRoundClass val;
				if (spawnLocked)
				{
					int num4 = PeekClipIndex(numRounds, roundOffset + i);
					if (num4 < 0 || num4 >= beltClip.LoadedRounds.Length || beltClip.LoadedRounds[num4] == null)
					{
						break;
					}
					val = beltClip.LoadedRounds[num4].LR_Class;
				}
				else
				{
					if (beltClip.m_numRounds <= 0)
					{
						break;
					}
					val = beltClip.RemoveRoundReturnClass();
				}
				gunClip.AddRound(val, false, false);
				num3++;
			}
			if (num3 <= 0)
			{
				return false;
			}
			gunClip.UpdateBulletDisplay();
			report = num3 + " round(s) from a clip into the clip";
			return true;
		}

		private static bool FillClipFromRounds(ReloadTarget target, FVRFireArmClip gunClip, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, int maxRounds, int roundOffset, out string report)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			if (beltRounds.RoundType != gunClip.RoundType)
			{
				return false;
			}
			int num = Mathf.Min(gunClip.m_capacity - gunClip.m_numRounds, CountRoundsInStack(beltRounds));
			if (maxRounds > 0 && num > maxRounds)
			{
				num = maxRounds;
			}
			if (num <= 0)
			{
				return false;
			}
			int num2 = 0;
			for (int i = 0; i < num; i++)
			{
				FireArmRoundClass roundClass;
				if (spawnLocked)
				{
					roundClass = PeekRoundClass(beltRounds, roundOffset + i);
				}
				else if (!TryTakeRound(ref beltRounds, slot, out roundClass))
				{
					break;
				}
				gunClip.AddRound(roundClass, false, false);
				num2++;
			}
			if (num2 <= 0)
			{
				return false;
			}
			gunClip.UpdateBulletDisplay();
			report = num2 + " round(s) from the belt into the clip";
			return true;
		}

		private static int PeekClipIndex(int available, int position)
		{
			if (available <= 0)
			{
				return -1;
			}
			int num = position % available;
			if (num < 0)
			{
				num += available;
			}
			return available - 1 - num;
		}

		private static bool InsertMagazine(ReloadTarget target, FVRFireArmMagazine beltMagazine, bool spawnLocked, out string report)
		{
			report = null;
			FVRFireArmMagazine val = beltMagazine;
			if (spawnLocked)
			{
				GameObject val2 = ((FVRPhysicalObject)beltMagazine).DuplicateFromSpawnLock((FVRViveHand)null);
				if ((Object)(object)val2 == (Object)null)
				{
					return false;
				}
				val = val2.GetComponent<FVRFireArmMagazine>();
				if ((Object)(object)val == (Object)null)
				{
					Object.Destroy((Object)(object)val2);
					return false;
				}
			}
			else
			{
				((FVRPhysicalObject)val).ClearQuickbeltState();
			}
			((FVRPhysicalObject)val).m_isSpawnLock = false;
			target.InsertMagazine(val);
			if (!target.MagazineIsPresent(val))
			{
				return false;
			}
			report = (spawnLocked ? "spawn locked magazine copied into the gun" : "magazine from the belt inserted");
			return true;
		}

		private static bool InsertClip(ReloadTarget target, FVRFireArmClip beltClip, bool spawnLocked, out string report)
		{
			report = null;
			FVRFireArmClip val = beltClip;
			if (spawnLocked)
			{
				GameObject val2 = ((FVRPhysicalObject)beltClip).DuplicateFromSpawnLock((FVRViveHand)null);
				if ((Object)(object)val2 == (Object)null)
				{
					return false;
				}
				val = val2.GetComponent<FVRFireArmClip>();
				if ((Object)(object)val == (Object)null)
				{
					Object.Destroy((Object)(object)val2);
					return false;
				}
			}
			else
			{
				((FVRPhysicalObject)val).ClearQuickbeltState();
			}
			((FVRPhysicalObject)val).m_isSpawnLock = false;
			val.Load(target.FireArm);
			if ((Object)(object)target.GunClip != (Object)(object)val)
			{
				return false;
			}
			report = (spawnLocked ? "spawn locked clip copied into the gun" : "clip from the belt inserted");
			return true;
		}

		private static bool LoadCylinderFromSpeedloader(ReloadTarget target, Speedloader beltSpeedloader, bool spawnLocked, out string report)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			List<SpeedloaderChamber> chambers = beltSpeedloader.Chambers;
			if (chambers == null || chambers.Count == 0)
			{
				return false;
			}
			FVRFireArm fireArm = target.FireArm;
			RevolvingShotgun val = (RevolvingShotgun)(object)((fireArm is RevolvingShotgun) ? fireArm : null);
			if ((Object)(object)val != (Object)null)
			{
				return InsertCylinderIntoRevolvingShotgun(val, beltSpeedloader, spawnLocked, out report);
			}
			FVRFireArm fireArm2 = target.FireArm;
			GrappleGun val2 = (GrappleGun)(object)((fireArm2 is GrappleGun) ? fireArm2 : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return InsertCylinderIntoGrappleGun(val2, beltSpeedloader, spawnLocked, out report);
			}
			if (target.ChamberCount == 0)
			{
				return false;
			}
			if (!HasSpareChamber(target))
			{
				return false;
			}
			if (!HasLiveRound(chambers))
			{
				return false;
			}
			FVRFireArm fireArm3 = target.FireArm;
			Revolver val3 = (Revolver)(object)((fireArm3 is Revolver) ? fireArm3 : null);
			if ((Object)(object)val3 != (Object)null && (Object)(object)val3.Cylinder != (Object)null)
			{
				if ((Object)(object)chambers[0] == (Object)null || chambers[0].Type != target.RoundType)
				{
					return false;
				}
				if (!((FVRInteractiveObject)val3.Cylinder).IsInteractable() || !val3.Cylinder.CanAccept())
				{
					return false;
				}
				Speedloader val4 = beltSpeedloader;
				if (spawnLocked)
				{
					val4 = DuplicateSpeedloader(beltSpeedloader);
					if ((Object)(object)val4 == (Object)null)
					{
						return false;
					}
				}
				else
				{
					((FVRPhysicalObject)val4).ClearQuickbeltState();
				}
				val3.Cylinder.LoadFromSpeedLoader(val4);
				if (val4.InjectsOnInsertion)
				{
					Object.Destroy((Object)(object)((Component)val4).gameObject);
				}
				report = "cylinder loaded from a speedloader";
				return true;
			}
			return FillChambersFromSpeedloader(target, chambers, spawnLocked, out report);
		}

		private static bool InsertCylinderIntoRevolvingShotgun(RevolvingShotgun gun, Speedloader beltCylinder, bool spawnLocked, out string report)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			if (gun.CylinderLoaded)
			{
				return false;
			}
			if (!CylinderFitsGun(beltCylinder, ((FVRFireArm)gun).RoundType, gun.SLType, (gun.Chambers != null) ? gun.Chambers.Length : 0))
			{
				return false;
			}
			Speedloader val = beltCylinder;
			if (spawnLocked)
			{
				val = DuplicateSpeedloader(beltCylinder);
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
			}
			else
			{
				((FVRPhysicalObject)val).ClearQuickbeltState();
			}
			gun.LoadCylinder(val);
			if (!gun.CylinderLoaded)
			{
				return false;
			}
			Object.Destroy((Object)(object)((Component)val).gameObject);
			report = (spawnLocked ? "spawn locked cylinder copied into the gun" : "cylinder from the belt inserted");
			return true;
		}

		private static bool InsertCylinderIntoGrappleGun(GrappleGun gun, Speedloader beltCylinder, bool spawnLocked, out string report)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			if (gun.IsMagLoaded)
			{
				return false;
			}
			if (!CylinderFitsGun(beltCylinder, ((FVRFireArm)gun).RoundType, gun.SLType, 0))
			{
				return false;
			}
			Speedloader val = beltCylinder;
			if (spawnLocked)
			{
				val = DuplicateSpeedloader(beltCylinder);
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
			}
			else
			{
				((FVRPhysicalObject)val).ClearQuickbeltState();
			}
			gun.LoadCylinder(val);
			if (!gun.IsMagLoaded)
			{
				return false;
			}
			Object.Destroy((Object)(object)((Component)val).gameObject);
			report = (spawnLocked ? "spawn locked grapple cylinder copied into the gun" : "grapple cylinder from the belt inserted");
			return true;
		}

		private static bool CylinderFitsGun(Speedloader cylinder, FireArmRoundType roundType, SpeedLoaderType slType, int chamberCount)
		{
			//IL_000a: 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)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)cylinder == (Object)null || cylinder.SLType != slType)
			{
				return false;
			}
			List<SpeedloaderChamber> chambers = cylinder.Chambers;
			if (chambers == null || chambers.Count == 0 || (Object)(object)chambers[0] == (Object)null || chambers[0].Type != roundType)
			{
				return false;
			}
			if (chamberCount > 0 && chambers.Count < chamberCount)
			{
				return false;
			}
			return HasLiveRound(chambers);
		}

		private static bool FillChambersFromSpeedloader(ReloadTarget target, List<SpeedloaderChamber> loaderChambers, bool spawnLocked, out string report)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < target.ChamberCount; i++)
			{
				FVRFireArmChamber val = target.ChamberAt(i);
				if ((Object)(object)val == (Object)null || !ChamberAcceptsRound(target, val, val.RoundType, replaceSpentCasings: false))
				{
					continue;
				}
				SpeedloaderChamber val2 = null;
				while (num < loaderChambers.Count)
				{
					SpeedloaderChamber val3 = loaderChambers[num];
					num++;
					if ((Object)(object)val3 != (Object)null && val3.IsLoaded && !val3.IsSpent && val3.Type == val.RoundType)
					{
						val2 = val3;
						break;
					}
				}
				if ((Object)(object)val2 == (Object)null)
				{
					break;
				}
				FireArmRoundClass loadedClass = val2.LoadedClass;
				if (!spawnLocked)
				{
					val2.Unload();
				}
				LoadRoundIntoChamber(val, loadedClass, replaceSpentCasing: false);
				num2++;
			}
			if (num2 <= 0)
			{
				return false;
			}
			PlayChamberingSound(target);
			report = num2 + " round(s) from a speedloader";
			return true;
		}

		private static Speedloader DuplicateSpeedloader(Speedloader template)
		{
			GameObject val = ((FVRPhysicalObject)template).DuplicateFromSpawnLock((FVRViveHand)null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Speedloader component = val.GetComponent<Speedloader>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			((FVRPhysicalObject)component).m_isSpawnLock = false;
			return component;
		}

		private static bool FillChambers(ReloadTarget target, ref FVRFireArmRound beltRounds, FVRQuickBeltSlot slot, bool spawnLocked, bool replaceSpentCasings, int maxRounds, int roundOffset, out string report)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			report = null;
			if (target.ChamberCount == 0)
			{
				return false;
			}
			int num = CountRoundsInStack(beltRounds);
			if (maxRounds > 0 && num > maxRounds)
			{
				num = maxRounds;
			}
			if (num <= 0)
			{
				return false;
			}
			int num2 = 0;
			int num3 = 0;
			for (int i = 0; i < target.ChamberCount; i++)
			{
				FVRFireArmChamber chamber = target.ChamberAt(i);
				if (ChamberAcceptsRound(target, chamber, beltRounds.RoundType, replaceSpentCasings))
				{
					if (num3 >= num)
					{
						break;
					}
					FireArmRoundClass roundClass;
					if (spawnLocked)
					{
						roundClass = PeekRoundClass(beltRounds, roundOffset + num3);
					}
					else if (!TryTakeRound(ref beltRounds, slot, out roundClass))
					{
						break;
					}
					num3++;
					LoadRoundIntoChamber(chamber, roundClass, replaceSpentCasings);
					num2++;
				}
			}
			if (num2 <= 0)
			{
				return false;
			}
			PlayChamberingSound(target);
			report = num2 + " round(s) from the belt into the chamber(s)";
			return true;
		}

		private static bool ChamberAcceptsRound(ReloadTarget target, FVRFireArmChamber chamber, FireArmRoundType roundType, bool replaceSpentCasings)
		{
			//IL_000a: 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)
			if ((Object)(object)chamber == (Object)null || chamber.RoundType != roundType)
			{
				return false;
			}
			if (chamber.IsFull && (!replaceSpentCasings || !chamber.IsSpent))
			{
				return false;
			}
			if (IsCylinderStyle(target))
			{
				if (CylinderTracksOpenState(target))
				{
					return chamber.IsAccessible;
				}
				FVRFireArm fireArm = target.FireArm;
				RevolvingShotgun val = (RevolvingShotgun)(object)((fireArm is RevolvingShotgun) ? fireArm : null);
				if ((Object)(object)val != (Object)null)
				{
					return val.CylinderLoaded;
				}
				return true;
			}
			if (chamber.IsManuallyChamberable)
			{
				return chamber.IsAccessible;
			}
			return false;
		}

		private static bool CylinderTracksOpenState(ReloadTarget target)
		{
			FVRFireArm fireArm = target.FireArm;
			if (!(fireArm is Revolver))
			{
				return fireArm is SingleActionRevolver;
			}
			return true;
		}

		private static void LoadRoundIntoChamber(FVRFireArmChamber chamber, FireArmRoundClass roundClass, bool replaceSpentCasing)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)chamber == (Object)null)
			{
				return;
			}
			try
			{
				if (chamber.IsFull)
				{
					if (!replaceSpentCasing)
					{
						return;
					}
					chamber.Unload();
				}
				if (AM.DoesClassExistForType(roundClass, chamber.RoundType))
				{
					chamber.SetRound(roundClass, ((Component)chamber).transform.position, ((Component)chamber).transform.rotation);
				}
			}
			catch (Exception)
			{
			}
		}

		private static bool IsCylinderStyle(ReloadTarget target)
		{
			if (target.IsAttachable)
			{
				return false;
			}
			FVRFireArm fireArm = target.FireArm;
			if (!(fireArm is Revolver) && !(fireArm is SingleActionRevolver))
			{
				return fireArm is RevolvingShotgun;
			}
			return true;
		}

		private static bool HasSpareChamber(ReloadTarget target)
		{
			for (int i = 0; i < target.ChamberCount; i++)
			{
				FVRFireArmChamber val = target.ChamberAt(i);
				if ((Object)(object)val != (Object)null && !val.IsFull)
				{
					return true;
				}
			}
			return false;
		}

		private static bool HasLiveRound(List<SpeedloaderChamber> chambers)
		{
			for (int i = 0; i < chambers.Count; i++)
			{
				SpeedloaderChamber val = chambers[i];
				if ((Object)(object)val != (Object)null && val.IsLoaded && !val.IsSpent)
				{
					return true;
				}
			}
			return false;
		}

		public static int CountRoundsInStack(FVRFireArmRound stack)
		{
			if ((Object)(object)stack == (Object)null)
			{
				return 0;
			}
			return 1 + (stack.ProxyRounds?.Count ?? 0);
		}

		private static FireArmRoundClass PeekRoundClass(FVRFireArmRound stack, int index)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)stack == (Object)null)
			{
				return (FireArmRoundClass)0;
			}
			List<ProxyRound> proxyRounds = stack.ProxyRounds;
			int num = 1 + (proxyRounds?.Count ?? 0);
			int num2 = index % num;
			if (num2 < 0)
			{
				num2 += num;
			}
			if (num2 <= 0)
			{
				return stack.RoundClass;
			}
			int num3 = num2 - 1;
			if (proxyRounds == null || num3 >= proxyRounds.Count || proxyRounds[num3] == null)
			{
				return stack.RoundClass;
			}
			return proxyRounds[num3].Class;
		}

		private static bool TryTakeRound(ref FVRFireArmRound stack, FVRQuickBeltSlot slot, out FireArmRoundClass roundClass)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected I4, but got Unknown
			if ((Object)(object)stack == (Object)null)
			{
				roundClass = (FireArmRoundClass)0;
				return false;
			}
			roundClass = (FireArmRoundClass)(int)stack.RoundClass;
			List<ProxyRound> proxyRounds = stack.ProxyRounds;
			int num = proxyRounds?.Count ?? 0;
			if (num == 0)
			{
				((FVRPhysicalObject)stack).ClearQuickbeltState();
				Object.Destroy((Object)(object)((Component)stack).gameObject);
				return true;
			}
			if (IsStackUniform(stack))
			{
				int index = num - 1;
				ProxyRound val = proxyRounds[index];
				if ((Object)(object)val.GO != (Object)null)
				{
					Object.Destroy((Object)(object)val.GO);
				}
				proxyRounds.RemoveAt(index);
				RefreshStackDisplay(stack);
				return true;
			}
			if (PromoteFirstProxy(stack, slot, out var promoted))
			{
				stack = promoted;
				return true;
			}
			return false;
		}

		private static bool IsStackUniform(FVRFireArmRound stack)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			FireArmRoundClass roundClass = stack.RoundClass;
			List<ProxyRound> proxyRounds = stack.ProxyRounds;
			if (proxyRounds == null)
			{
				return true;
			}
			for (int i = 0; i < proxyRounds.Count; i++)
			{
				if (proxyRounds[i] == null || proxyRounds[i].Class != roundClass)
				{
					return false;
				}
			}
			return true;
		}

		private static bool PromoteFirstProxy(FVRFireArmRound stack, FVRQuickBeltSlot slot, out FVRFireArmRound promoted)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			promoted = null;
			List<ProxyRound> proxyRounds = stack.ProxyRounds;
			if (proxyRounds == null || proxyRounds.Count == 0)
			{
				return false;
			}
			ProxyRound val = proxyRounds[0];
			if (val == null || (Object)(object)val.ObjectWrapper == (Object)null)
			{
				return false;
			}
			GameObject val2 = null;
			try
			{
				val2 = Object.Instantiate<GameObject>(((AnvilAsset)val.ObjectWrapper).GetGameObject(), ((Component)stack).transform.position, ((Component)stack).transform.rotation);
				FVRFireArmRound component = val2.GetComponent<FVRFireArmRound>();
				if ((Object)(object)component == (Object)null)
				{
					Object.Destroy((Object)(object)val2);
					return false;
				}
				for (int i = 1; i < proxyRounds.Count; i++)
				{
					ProxyRound val3 = proxyRounds[i];
					if (val3 != null && !((Object)(object)val3.GO == (Object)null))
					{
						val3.GO.transform.SetParent(((Component)component).transform, true);
						component.ProxyRounds.Add(val3);
					}
				}
				if ((Object)(object)val.GO != (Object)null)
				{
					Object.Destroy((Object)(object)val.GO);
				}
				proxyRounds.Clear();
				((FVRPhysicalObject)stack).ClearQuickbeltState();
				Object.Destroy((Object)(object)((Component)stack).gameObject);
				component.UpdateProxyDisplay();
				if ((Object)(object)slot != (Object)null)
				{
					((FVRPhysicalObject)component).SetQuickBeltSlot(slot);
				}
				promoted = component;
				return true;
			}
			catch (Exception)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					try
					{
						Object.Destroy((Object)(object)val2);
					}
					catch (Exception)
					{
					}
				}
				return false;
			}
		}

		private static void RefreshStackDisplay(FVRFireArmRound stack)
		{
			try
			{
				stack.UpdateProxyDisplay();
			}
			catch (Exception)
			{
			}
		}

		private static void PlayChamberingSound(ReloadTarget target)
		{
			for (int i = 0; i < target.ChamberCount; i++)
			{
				FVRFireArmChamber val = target.ChamberAt(i);
				if (!((Object)(object)val == (Object)null))
				{
					try
					{
						val.PlayChamberingAudio();
						break;
					}
					catch (Exception)
					{
						break;
					}
				}
			}
		}
	}
	internal static class FireArmProbe
	{
		public static Vector3 GetFireArmProbePoint(FVRFireArm gun)
		{
			//IL_0009: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)gun == (Object)null)
			{
				return Vector3.zero;
			}
			Revolver val = (Revolver)(object)((gun is Revolver) ? gun : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.Cylinder != (Object)null)
			{
				return ((Component)val.Cylinder).transform.position;
			}
			SingleActionRevolver val2 = (SingleActionRevolver)(object)((gun is SingleActionRevolver) ? gun : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.Cylinder != (Object)null)
			{
				return ((Component)val2.Cylinder).transform.position;
			}
			RevolvingShotgun val3 = (RevolvingShotgun)(object)((gun is RevolvingShotgun) ? gun : null);
			if ((Object)(object)val3 != (Object)null && (Object)(object)val3.ProxyCylinder != (Object)null)
			{
				return val3.ProxyCylinder.position;
			}
			Transform reloadTriggerWell = GetReloadTriggerWell(gun);
			if ((Object)(object)reloadTriggerWell != (Object)null)
			{
				return reloadTriggerWell.position;
			}
			if ((Object)(object)gun.MagazineMountPos != (Object)null)
			{
				return gun.MagazineMountPos.position;
			}
			List<FVRFireArmChamber> chambers = gun.GetChambers();
			if (chambers != null)
			{
				for (int i = 0; i < chambers.Count; i++)
				{
					if ((Object)(object)chambers[i] != (Object)null)
					{
						return ((Component)chambers[i]).transform.position;
					}
				}
			}
			return ((Component)gun).transform.position;
		}

		public static Vector3 GetHeldObjectProbePoint(FVRPhysicalObject held)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)held == (Object)null)
			{
				return Vector3.zero;
			}
			try
			{
				Rigidbody rootRigidbody = held.RootRigidbody;
				if ((Object)(object)rootRigidbody != (Object)null)
				{
					return rootRigidbody.worldCenterOfMass;
				}
			}
			catch (Exception)
			{
			}
			return ((Component)held).transform.position;
		}

		public static void CollectAttachedFireArms(FVRFireArm gun, List<AttachableFirearm> results)
		{
			if ((Object)(object)gun == (Object)null || results == null)
			{
				return;
			}
			try
			{
				List<FVRFireArmAttachment> attachments = ((FVRPhysicalObject)gun).Attachments;
				if (attachments == null)
				{
					return;
				}
				for (int i = 0; i < attachments.Count; i++)
				{
					FVRFireArmAttachment obj = attachments[i];
					AttachableFirearmPhysicalObject val = (AttachableFirearmPhysicalObject)(object)((obj is AttachableFirearmPhysicalObject) ? obj : null);
					if ((Object)(object)val != (Object)null && (Object)(object)val.FA != (Object)null)
					{
						results.Add(val.FA);
					}
				}
			}
			catch (Exception)
			{
			}
		}

		public static Vector3 GetAttachableProbePoint(AttachableFirearm attachable)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)attachable == (Object)null)
			{
				return Vector3.zero;
			}
			AttachableTubeFed val = (AttachableTubeFed)(object)((attachable is AttachableTubeFed) ? attachable : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.ReloadTriggerWell != (Object)null)
			{
				return val.ReloadTriggerWell.transform.position;
			}
			if ((Object)(object)attachable.MagazineMountPos != (Object)null)
			{
				return attachable.MagazineMountPos.position;
			}
			FVRFireArmChamber val2 = ReloadTarget.AttachableChamber(attachable);
			if ((Object)(object)val2 != (Object)null)
			{
				return ((Component)val2).transform.position;
			}
			if ((Object)(object)attachable.Attachment != (Object)null)
			{
				return ((Component)attachable.Attachment).transform.position;
			}
			return ((Component)attachable).transform.position;
		}

		private static Transform GetReloadTriggerWell(FVRFireArm gun)
		{
			Handgun val = (Handgun)(object)((gun is Handgun) ? gun : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.ReloadTriggerWell != (Object)null)
			{
				return val.ReloadTriggerWell.transform;
			}
			OpenBoltReceiver val2 = (OpenBoltReceiver)(object)((gun is OpenBoltReceiver) ? gun : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.ReloadTriggerWell != (Object)null)
			{
				return val2.ReloadTriggerWell.transform;
			}
			BoltActionRifle val3 = (BoltActionRifle)(object)((gun is BoltActionRifle) ? gun : null);
			if ((Object)(object)val3 != (Object)null && (Object)(object)val3.ReloadTriggerWell != (Object)null)
			{
				return val3.ReloadTriggerWell.transform;
			}
			BAP val4 = (BAP)(object)((gun is BAP) ? gun : null);
			if ((Object)(object)val4 != (Object)null && (Object)(object)val4.ReloadTriggerWell != (Object)null)
			{
				return val4.ReloadTriggerWell.transform;
			}
			TubeFedShotgun val5 = (TubeFedShotgun)(object)((gun is TubeFedShotgun) ? gun : null);
			if ((Object)(object)val5 != (Object)null && (Object)(object)val5.ReloadTriggerWell != (Object)null)
			{
				return val5.ReloadTriggerWell.transform;
			}
			RailTater val6 = (RailTater)(object)((gun is RailTater) ? gun : null);
			if ((Object)(object)val6 != (Object)null && (Object)(object)val6.ReloadTriggerWell != (Object)null)
			{
				return val6.ReloadTriggerWell.transform;
			}
			GrappleGun val7 = (GrappleGun)(object)((gun is GrappleGun) ? gun : null);
			if ((Object)(object)val7 != (Object)null && (Object)(object)val7.ReloadTriggerWell != (Object)null)
			{
				return val7.ReloadTriggerWell.transform;
			}
			return null;
		}

		public static bool SlotContains(FVRQuickBeltSlot slot, Vector3 point, float radiusMultiplier)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)slot == (Object)null)
			{
				return false;
			}
			try
			{
				if (slot.IsPointInsideMe(point))
				{
					return true;
				}
				if (radiusMultiplier <= 1f)
				{
					return false;
				}
				float num = 0.5f * radiusMultiplier;
				if ((int)slot.Shape == 0)
				{
					Transform val = (((Object)(object)slot.HoverGeo != (Object)null) ? slot.HoverGeo.transform : null);
					if ((Object)(object)val != (Object)null)
					{
						Vector3 val2 = val.InverseTransformPoint(point);
						if (((Vector3)(ref val2)).magnitude < num)
						{
							return true;
						}
					}
				}
				else if ((Object)(object)slot.RectBounds != (Object)null)
				{
					Vector3 val3 = slot.RectBounds.InverseTransformPoint(point);
					if (Mathf.Abs(val3.x) < num && Mathf.Abs(val3.y) < num && Mathf.Abs(val3.z) < num)
					{
						return true;
					}
				}
				return false;
			}
			catch (Exception)
			{
				return false;
			}
		}
	}
	[BepInProcess("h3vr.exe")]
	[BepInPlugin("Niko666.ArcadeReload", "ArcadeReload", "1.0.0")]
	public class ArcadeReload : BaseUnityPlugin
	{
		private struct ConfigSnapshot
		{
			public bool Enabled;

			public float Cooldown;

			public float RoundInterval;

			public float Radius;

			public bool AddedSlots;

			public bool SpentCasings;

			public bool Verbose;
		}

		private sealed class FeedState
		{
			public Object Owner;

			public FVRQuickBeltSlot LastSlot;

			public float LastReloadTime;

			public bool Feeding;

			public float NextRoundTime;

			public int RoundsFed;

			public int LastFrame = -1;

			public int LastTakeFrame = -1;

			public int LastContainerRounds = -1;

			public float ContainerQuietUntil;

			public bool ContactDisqualified;

			public bool ContainerArmed;

			public float AwayFromBeltSince = -1f;
		}

		public static ConfigEntry<bool> ModEnabled;

		public static ConfigEntry<float> ReloadCooldown;

		public static ConfigEntry<float> RoundFeedInterval;

		public static ConfigEntry<float> BeltTriggerRadius;

		public static ConfigEntry<bool> IncludeAddedBeltSlots;

		public static ConfigEntry<bool> ReplaceSpentCasings;

		public static ConfigEntry<bool> VerboseLogging;

		private static ConfigSnapshot _cfg;

		private static string _configFilePath;

		private static long _configFileStamp = -1L;

		private static readonly Dictionary<int, FeedState> _feedStates = new Dictionary<int, FeedState>();

		private static readonly List<ReloadTarget> _targetScratch = new List<ReloadTarget>();

		private static readonly List<AttachableFirearm> _attachableScratch = new List<AttachableFirearm>();

		private static float _lastStatePrune;

		private int _updateErrors;

		private static float _lastConfigCheck;

		private const float EmptySlotPenalty = 1000f;

		private const float ContainerQuietTime = 1.2f;

		private const float HeldContainerArmDelay = 0.25f;

		public const string Id = "Niko666.ArcadeReload";

		public static ArcadeReload Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		public static string Name => "ArcadeReload";

		public static string Version => "1.0.0";

		private void BindConfig()
		{
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch for the arcade reload.");
			ReloadCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ReloadCooldown", 0.2f, "Seconds before the same gun can be arcade reloaded again. A sweep that enters a belt slot reloads once; leaving the slot and coming back reloads again. (0-2)");
			RoundFeedInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RoundFeedInterval", 0.15f, "Seconds between rounds when rounds are loaded one at a time, the way you would push them in by hand: loose rounds in the belt, and clips. The gun keeps taking one round at this pace for as long as it stays over the slot, so a short stack - or a spawn locked one - fills the gun completely, and a spawn locked stack cycles through its round types. Whole magazines and speedloaders always load in one go. (0.05-2)");
			BeltTriggerRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BeltTriggerRadius", 1.5f, "How big the quickbelt slots are for this mod, as a multiplier of their real pickup volume. 1.0 = exactly the vanilla slot volume, which is small and easy to sweep past in one frame. (1-3)");
			IncludeAddedBeltSlots = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IncludeAddedBeltSlots", true, "Also accept ammo from extra slots that are not part of the base belt (chest rigs, backpacks and other added slots).");
			ReplaceSpentCasings = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ReplaceSpentCasings", false, "Off: a chamber or cylinder position that still holds a fired casing is left alone and only genuinely empty ones get a new round. On: the spent casing is thrown away and replaced.");
			VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLogging", false, "Log every arcade reload to the BepInEx console. Useful when a gun does not reload the way you expect.");
			AddSettingChangedListener<bool>(ModEnabled);
			AddSettingChangedListener<float>(ReloadCooldown);
			AddSettingChangedListener<float>(RoundFeedInterval);
			AddSettingChangedListener<float>(BeltTriggerRadius);
			AddSettingChangedListener<bool>(IncludeAddedBeltSlots);
			AddSettingChangedListener<bool>(ReplaceSpentCasings);
			AddSettingChangedListener<bool>(VerboseLogging);
		}

		private static void AddSettingChangedListener<T>(ConfigEntry<T> entry)
		{
			entry.SettingChanged += delegate
			{
				ReloadConfigSnapshot();
			};
		}

		private static void ReloadConfigSnapshot()
		{
			_cfg = new ConfigSnapshot
			{
				Enabled = ModEnabled.Value,
				Cooldown = Mathf.Clamp(ReloadCooldown.Value, 0f, 2f),
				RoundInterval = Mathf.Clamp(RoundFeedInterval.Value, 0.05f, 2f),
				Radius = Mathf.Clamp(BeltTriggerRadius.Value, 1f, 3f),
				AddedSlots = IncludeAddedBeltSlots.Value,
				SpentCasings = ReplaceSpentCasings.Value,
				Verbose = VerboseLogging.Value
			};
		}

		private static void ReloadConfigFromDisk()
		{
			try
			{
				if ((Object)(object)Instance != (Object)null && ((BaseUnityPlugin)Instance).Config != null)
				{
					((BaseUnityPlugin)Instance).Config.Reload();
				}
			}
			catch (Exception ex)
			{
				if (Logger != null)
				{
					Logger.LogWarning((object)("Config reload failed: " + ex.Message));
				}
			}
			ReloadConfigSnapshot();
			RememberConfigFileStamp();
		}

		private static void RememberConfigFileStamp()
		{
			if (string.IsNullOrEmpty(_configFilePath))
			{
				return;
			}
			try
			{
				_configFileStamp = (File.Exists(_configFilePath) ? File.GetLastWriteTimeUtc(_configFilePath).Ticks : (-1));
			}
			catch (Exception)
			{
				_configFileStamp = -1L;
			}
		}

		private static void CheckConfigFileChanged()
		{
			if (string.IsNullOrEmpty(_configFilePath))
			{
				return;
			}
			try
			{
				if (File.Exists(_configFilePath) && File.GetLastWriteTimeUtc(_configFilePath).Ticks != _configFileStamp)
				{
					Logger.LogMessage((object)"Config file changed on disk, reloading it.");
					ReloadConfigFromDisk();
				}
			}
			catch (Exception)
			{
			}
		}

		private static bool TryGetState(ReloadTarget target, float now, out FeedState state)
		{
			state = null;
			Object identity = target.Identity;
			if (identity == (Object)null)
			{
				return false;
			}
			int instanceID = identity.GetInstanceID();
			if (!_feedStates.TryGetValue(instanceID, out state) || state == null)
			{
				state = new FeedState();
				state.Owner = identity;
				_feedStates[instanceID] = state;
			}
			PruneStates(now);
			return true;
		}

		private static void PruneStates(float now)
		{
			if (now - _lastStatePrune < 5f || _feedStates.Count < 24)
			{
				return;
			}
			_lastStatePrune = now;
			List<int> list = null;
			foreach (KeyValuePair<int, FeedState> feedState in _feedStates)
			{
				if (feedState.Value == null || feedState.Value.Owner == (Object)null)
				{
					if (list == null)
					{
						list = new List<int>();
					}
					list.Add(feedState.Key);
				}
			}
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					_feedStates.Remove(list[i]);
				}
			}
		}

		private static void ResetAllFeedStates()
		{
			foreach (KeyValuePair<int, FeedState> feedState in _feedStates)
			{
				if (feedState.Value != null)
				{
					feedState.Value.LastSlot = null;
					FeedStop(feedState.Value);
				}
			}
		}

		private static void FeedStop(FeedState state)
		{
			state.Feeding = false;
			state.NextRoundTime = 0f;
			state.RoundsFed = 0;
		}

		private static ReloadTarget ResolveTarget(FVRViveHand hand)
		{
			FVRInteractiveObject currentInteractable = hand.CurrentInteractable;
			if ((Object)(object)currentInteractable == (Object)null)
			{
				return default(ReloadTarget);
			}
			FVRFireArm val = (FVRFireArm)(object)((currentInteractable is FVRFireArm) ? currentInteractable : null);
			if ((Object)(object)val != (Object)null)
			{
				return ReloadTarget.ForFireArm(val);
			}
			AttachableFirearmPhysicalObject val2 = (AttachableFirearmPhysicalObject)(object)((currentInteractable is AttachableFirearmPhysicalObject) ? currentInteractable : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.FA != (Object)null)
			{
				return ReloadTarget.ForAttachable(val2.FA);
			}
			AttachableFirearmInterface val3 = (AttachableFirearmInterface)(object)((currentInteractable is AttachableFirearmInterface) ? currentInteractable : null);
			if ((Object)(object)val3 != (Object)null && (Object)(object)val3.FA != (Object)null)
			{
				return ReloadTarget.ForAttachable(val3.FA);
			}
			FVRAlternateGrip val4 = (FVRAlternateGrip)(object)((currentInteractable is FVRAlternateGrip) ? currentInteractable : null);
			if ((Object)(object)val4 != (Object)null)
			{
				AttachableForegrip lastGrabbedInGrip = val4.LastGrabbedInGrip;
				AttachableFirearmInterface val5 = (AttachableFirearmInterface)(object)((lastGrabbedInGrip is AttachableFirearmInterface) ? lastGrabbedInGrip : null);
				if ((Object)(object)val5 != (Object)null && (Object)(object)val5.FA != (Object)null)
				{
					return ReloadTarget.ForAttachable(val5.FA);
				}
				return default(ReloadTarget);
			}
			FVRFireArmMagazine val6 = (FVRFireArmMagazine)(object)((currentInteractable is FVRFireArmMagazine) ? currentInteractable : null);
			if ((Object)(object)val6 != (Object)null)
			{
				return ReloadTarget.ForHeldMagazine(val6);
			}
			FVRFireArmClip val7 = (FVRFireArmClip)(object)((currentInteractable is FVRFireArmClip) ? currentInteractable : null);
			if ((Object)(object)val7 != (Object)null)
			{
				return ReloadTarget.ForHeldClip(val7);
			}
			Speedloader val8 = (Speedloader)(object)((currentInteractable is Speedloader) ? currentInteractable : null);
			if ((Object)(object)val8 != (Object)null)
			{
				return ReloadTarget.ForHeldSpeedloader(val8);
			}
			return default(ReloadTarget);
		}

		private static void CollectTargets(FVRViveHand hand)
		{
			_targetScratch.Clear();
			ReloadTarget reloadTarget = ResolveTarget(hand);
			if (!reloadTarget.IsValid)
			{
				return;
			}
			_targetScratch.Add(reloadTarget);
			if ((Object)(object)reloadTarget.FireArm == (Object)null)
			{
				return;
			}
			_attachableScratch.Clear();
			FireArmProbe.CollectAttachedFireArms(reloadTarget.FireArm, _attachableScratch);
			for (int i = 0; i < _attachableScratch.Count; i++)
			{
				ReloadTarget item = ReloadTarget.ForAttachable(_attachableScratch[i]);
				if (!item.SameAs(reloadTarget))
				{
					_targetScratch.Add(item);
				}
			}
		}

		private static void UpdateSweep(FeedState state, ReloadTarget target, FVRPlayerBody body, float now, FeedState primaryState)
		{
			FVRQuickBeltSlot val = FindBeltSlot(target, body);
			bool flag = (Object)(object)val != (Object)(object)state.LastSlot;
			if (flag)
			{
				state.LastSlot = val;
				FeedStop(state);
			}
			if (target.IsHeldContainer)
			{
				int containerRoundCount = target.ContainerRoundCount;
				if (state.LastContainerRounds >= 0 && containerRoundCount >= 0 && containerRoundCount < state.LastContainerRounds)
				{
					state.ContainerQuietUntil = now + 1.2f;
					state.ContactDisqualified = true;
					FeedStop(state);
				}
				state.LastContainerRounds = containerRoundCount;
			}
			if ((Object)(object)val == (Object)null)
			{
				state.ContactDisqualified = false;
				if (target.IsHeldContainer)
				{
					if (state.AwayFromBeltSince < 0f)
					{
						state.AwayFromBeltSince = now;
					}
					else if (now - state.AwayFromBeltSince >= 0.25f)
					{
						state.ContainerArmed = true;
					}
				}
				return;
			}
			state.AwayFromBeltSince = -1f;
			if ((Object)(object)val.CurObject == (Object)null)
			{
				FeedStop(state);
				return;
			}
			if (target.IsHeldContainer)
			{
				if (!state.ContainerArmed)
				{
					FeedStop(state);
					return;
				}
				if (state.ContactDisqualified || now < state.ContainerQuietUntil)
				{
					FeedStop(state);
					return;
				}
			}
			if (primaryState != null && (Object)(object)primaryState.LastSlot == (Object)(object)val && (primaryState.Feeding || primaryState.LastTakeFrame == Time.frameCount))
			{
				FeedStop(state);
				return;
			}
			bool flag2 = IsSlowFeedSource(val);
			if (flag)
			{
				if (now - state.LastReloadTime < _cfg.Cooldown)
				{
					return;
				}
			}
			else if (!state.Feeding || !flag2 || now < state.NextRoundTime)
			{
				return;
			}
			bool flag3;
			string report;
			try
			{
				flag3 = AmmoTransfer.TryArcadeReload(target, val, _cfg.SpentCasings, flag2 ? 1 : 0, state.RoundsFed, out report);
			}
			catch (Exception ex)
			{
				FeedStop(state);
				if (_cfg.Verbose)
				{
					Logger.LogWarning((object)("Arcade reload attempt failed: " + ex));
				}
				return;
			}
			if (!flag3)
			{
				if (flag && _cfg.Verbose)
				{
					Logger.LogMessage((object)("Arcade reload: swept into a slot holding " + DescribeSlotItem(val) + " but nothing could be loaded [" + target.Name + "]"));
				}
				if (flag2 && !state.ContactDisqualified)
				{
					state.Feeding = true;
					state.NextRoundTime = now + _cfg.RoundInterval;
				}
				else
				{
					FeedStop(state);
				}
				return;
			}
			state.LastReloadTime = now;
			state.LastTakeFrame = Time.frameCount;
			if (flag2)
			{
				state.Feeding = true;
				state.RoundsFed++;
				state.NextRoundTime = now + _cfg.RoundInterval;
			}
			else
			{
				FeedStop(state);
			}
			if (_cfg.Verbose)
			{
				Logger.LogMessage((object)("Arcade reload: " + report + " [" + target.Name + "]"));
			}
		}

		private static bool IsSlowFeedSource(FVRQuickBeltSlot slot)
		{
			FVRPhysicalObject val = (((Object)(object)slot == (Object)null) ? null : slot.CurObject);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (!(val is FVRFireArmRound))
			{
				return val is FVRFireArmClip;
			}
			return true;
		}

		public void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			ReloadConfigSnapshot();
			try
			{
				if ((Object)(object)Instance != (Object)null && ((BaseUnityPlugin)Instance).Config != null)
				{
					_configFilePath = ((BaseUnityPlugin)Instance).Config.ConfigFilePath;
				}
			}
			catch (Exception)
			{
			}
			RememberConfigFileStamp();
			Logger.LogMessage((object)("Hello, world! Sent from Niko666.ArcadeReload " + Version));
		}

		public void Update()
		{
			try
			{
				float unscaledTime = Time.unscaledTime;
				if (unscaledTime - _lastConfigCheck >= 1f)
				{
					_lastConfigCheck = unscaledTime;
					CheckConfigFileChanged();
				}
				if (!_cfg.Enabled)
				{
					return;
				}
				FVRMovementManager val = null;
				try
				{
					val = GM.CurrentMovementManager;
				}
				catch (Exception)
				{
				}
				FVRPlayerBody val2 = null;
				try
				{
					val2 = GM.CurrentPlayerBody;
				}
				catch (Exception)
				{
				}
				FVRViveHand[] array = (((Object)(object)val == (Object)null) ? null : val.Hands);
				if (array == null || (Object)(object)val2 == (Object)null)
				{
					ResetAllFeedStates();
					return;
				}
				foreach (FVRViveHand val3 in array)
				{
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					CollectTargets(val3);
					FeedState feedState = null;
					for (int j = 0; j < _targetScratch.Count; j++)
					{
						ReloadTarget target = _targetScratch[j];
						if (!TryGetState(target, unscaledTime, out var state))
						{
							continue;
						}
						if (j == 0)
						{
							feedState = state;
						}
						if (state.LastFrame < 0)
						{
							state.LastSlot = FindBeltSlot(target, val2);
							if (target.IsHeldContainer)
							{
								state.LastContainerRounds = target.ContainerRoundCount;
							}
						}
						if (state.LastFrame != Time.frameCount)
						{
							state.LastFrame = Time.frameCount;
							UpdateSweep(state, target, val2, unscaledTime, (j == 0) ? null : feedState);
						}
					}
				}
			}
			catch (Exception ex3)
			{
				if (_updateErrors < 3)
				{
					_updateErrors++;
					Logger.LogError((object)("Arcade Reload update failed: " + ex3));
				}
			}
		}

		private static string DescribeSlotItem(FVRQuickBeltSlot slot)
		{
			FVRPhysicalObject val = (((Object)(object)slot == (Object)null) ? null : slot.CurObject);
			if ((Object)(object)val == (Object)null)
			{
				return "nothing";
			}
			FVRFireArmMagazine val2 = (FVRFireArmMagazine)(object)((val is FVRFireArmMagazine) ? val : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return ((object)Unsafe.As<FireArmMagazineType, FireArmMagazineType>(ref val2.MagazineType)/*cast due to .constrained prefix*/).ToString() + " magazine (" + val2.m_numRounds + "/" + val2.m_capacity + ")";
			}
			FVRFireArmClip val3 = (FVRFireArmClip)(object)((val is FVRFireArmClip) ? val : null);
			if ((Object)(object)val3 != (Object)null)
			{
				return ((object)Unsafe.As<FireArmClipType, FireArmClipType>(ref val3.ClipType)/*cast due to .constrained prefix*/).ToString() + " clip (" + val3.m_numRounds + "/" + val3.m_capacity + ")";
			}
			FVRFireArmRound val4 = (FVRFireArmRound)(object)((val is FVRFireArmRound) ? val : null);
			if ((Object)(object)val4 != (Object)null)
			{
				return ((object)Unsafe.As<FireArmRoundType, FireArmRoundType>(ref val4.RoundType)/*cast due to .constrained prefix*/).ToString() + " round(s), stack of " + (1 + ((val4.ProxyRounds != null) ? val4.ProxyRounds.Count : 0));
			}
			if ((Object)(object)((val is Speedloader) ? val : null) != (Object)null)
			{
				return "speedloader";
			}
			return ((Object)val).name;
		}

		private static FVRQuickBeltSlot FindBeltSlot(ReloadTarget target, FVRPlayerBody body)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			Vector3 probePoint;
			try
			{
				probePoint = target.GetProbePoint();
			}
			catch (Exception)
			{
				return null;
			}
			FVRQuickBeltSlot best = null;
			float bestScore = float.MaxValue;
			best = ConsiderSlots(body.QBSlots_Internal, probePoint, best, ref bestScore);
			if (_cfg.AddedSlots)
			{
				best = ConsiderSlots(body.QBSlots_Added, probePoint, best, ref bestScore);
			}
			return best;
		}

		private static FVRQuickBeltSlot ConsiderSlots(List<FVRQuickBeltSlot> slots, Vector3 probe, FVRQuickBeltSlot best, ref float bestScore)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (slots == null)
			{
				return best;
			}
			for (int i = 0; i < slots.Count; i++)
			{
				FVRQuickBeltSlot val = slots[i];
				if (!((Object)(object)val == (Object)null) && val.IsSelectable && FireArmProbe.SlotContains(val, probe, _cfg.Radius))
				{
					Vector3 val2 = (((Object)(object)val.PoseOverride != (Object)null) ? val.PoseOverride : ((Component)val).transform).position - probe;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					float num = (((Object)(object)val.CurObject != (Object)null) ? sqrMagnitude : (sqrMagnitude + 1000f));
					if (num < bestScore)
					{
						bestScore = num;
						best = val;
					}
				}
			}
			return best;
		}
	}
	internal struct ReloadTarget
	{
		public readonly FVRFireArm FireArm;

		public readonly AttachableFirearm Attachable;

		public readonly FVRFireArmMagazine HeldMagazine;

		public readonly FVRFireArmClip HeldClip;

		public readonly Speedloader HeldSpeedloader;

		public bool IsValid
		{
			get
			{
				if (!IsGun)
				{
					return IsHeldContainer;
				}
				return true;
			}
		}

		public bool IsGun
		{
			get
			{
				if (!((Object)(object)FireArm != (Object)null))
				{
					return (Object)(object)Attachable != (Object)null;
				}
				return true;
			}
		}

		public bool IsAttachable => (Object)(object)Attachable != (Object)null;

		public bool IsHeldContainer
		{
			get
			{
				if (!((Object)(object)HeldMagazine != (Object)null) && !((Object)(object)HeldClip != (Object)null))
				{
					return (Object)(object)HeldSpeedloader != (Object)null;
				}
				return true;
			}
		}

		public Object Identity
		{
			get
			{
				if ((Object)(object)FireArm != (Object)null)
				{
					return (Object)(object)FireArm;
				}
				if ((Object)(object)Attachable != (Object)null)
				{
					return (Object)(object)Attachable;
				}
				if ((Object)(object)HeldMagazine != (Object)null)
				{
					return (Object)(object)HeldMagazine;
				}
				if ((Object)(object)HeldClip != (Object)null)
				{
					return (Object)(object)HeldClip;
				}
				return (Object)(object)HeldSpeedloader;
			}
		}

		public string Name
		{
			get
			{
				Object identity = Identity;
				if (!(identity == (Object)null))
				{
					return identity.name;
				}
				return "(none)";
			}
		}

		public FireArmRoundType RoundType
		{
			get
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: 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_006e: 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 ((Object)(object)FireArm != (Object)null)
				{
					return FireArm.RoundType;
				}
				if ((Object)(object)Attachable != (Object)null)
				{
					return Attachable.RoundType;
				}
				if ((Object)(object)HeldMagazine != (Object)null)
				{
					return HeldMagazine.RoundType;
				}
				if ((Object)(object)HeldClip != (Object)null)
				{
					return HeldClip.RoundType;
				}
				return SpeedloaderChamberType(HeldSpeedloader);
			}
		}

		public FireArmMagazineType MagazineType
		{
			get
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: 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)
				if ((Object)(object)FireArm != (Object)null)
				{
					return FireArm.MagazineType;
				}
				if ((Object)(object)Attachable != (Object)null)
				{
					return Attachable.MagazineType;
				}
				if ((Object)(object)HeldMagazine != (Object)null)
				{
					return HeldMagazine.MagazineType;
				}
				return (FireArmMagazineType)0;
			}
		}

		public int ContainerRoundCount
		{
			get
			{
				if ((Object)(object)HeldMagazine != (Object)null)
				{
					return HeldMagazine.m_numRounds;
				}
				if ((Object)(object)HeldClip != (Object)null)
				{
					return HeldClip.m_numRounds;
				}
				if ((Object)(object)HeldSpeedloader != (Object)null)
				{
					return LoadedSpeedloaderChambers(HeldSpeedloader);
				}
				return -1;
			}
		}

		public FVRFireArmMagazine GunMagazine
		{
			get
			{
				if ((Object)(object)FireArm != (Object)null)
				{
					return FireArm.Magazine;
				}
				if ((Object)(object)Attachable != (Object)null)
				{
					return Attachable.Magazine;
				}
				return null;
			}
		}

		public FVRFireArmClip GunClip
		{
			get
			{
				if ((Object)(object)FireArm != (Object)null)
				{
					return FireArm.Clip;
				}
				if ((Object)(object)Attachable != (Object)null)
				{
					return Attachable.Clip;
				}
				return null;
			}
		}

		public FireArmClipType ClipType
		{
			get
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)FireArm != (Object)null))
				{
					return (FireArmClipType)0;
				}
				return FireArm.ClipType;
			}
		}

		public Transform ClipMountPos
		{
			get
			{
				if ((Object)(object)FireArm != (Object)null)
				{
					return FireArm.ClipMountPos;
				}
				if ((Object)(object)Attachable != (Object)null)
				{
					return Attachable.ClipMountPos;
				}
				return null;
			}
		}

		public SecondaryMagazineSlot[] SecondarySlots
		{
			get
			{
				if (!((Object)(object)FireArm != (Object)null))
				{
					return null;
				}
				return FireArm.SecondaryMagazineSlots;
			}
		}

		public int ChamberCount
		{
			get
			{
				if ((Object)(object)FireArm != (Object)null)
				{
					return FireArm.GetChambers()?.Count ?? 0;
				}
				return ((Object)(object)AttachableChamber(Attachable) != (Object)null) ? 1 : 0;
			}
		}

		private ReloadTarget(FVRFireArm fireArm, AttachableFirearm attachable, FVRFireArmMagazine heldMagazine, FVRFireArmClip heldClip, Speedloader heldSpeedloader)
		{
			FireArm = fireArm;
			Attachable = attachable;
			HeldMagazine = heldMagazine;
			HeldClip = heldClip;
			HeldSpeedloader = heldSpeedloader;
		}

		public static ReloadTarget ForFireArm(FVRFireArm gun)
		{
			return new ReloadTarget(gun, null, null, null, null);
		}

		public static ReloadTarget ForAttachable(AttachableFirearm attachable)
		{
			return new ReloadTarget(null, attachable, null, null, null);
		}

		public static ReloadTarget ForHeldMagazine(FVRFireArmMagazine magazine)
		{
			return new ReloadTarget(null, null, magazine, null, null);
		}

		public static ReloadTarget ForHeldClip(FVRFireArmClip clip)
		{
			return new ReloadTarget(null, null, null, clip, null);
		}

		public static ReloadTarget ForHeldSpeedloader(Speedloader speedloader)
		{
			return new ReloadTarget(null, null, null, null, speedloader);
		}

		public bool SameAs(ReloadTarget other)
		{
			if ((Object)(object)FireArm == (Object)(object)other.FireArm && (Object)(object)Attachable == (Object)(object)other.Attachable && (Object)(object)HeldMagazine == (Object)(object)other.HeldMagazine && (Object)(object)HeldClip == (Object)(object)other.HeldClip)
			{
				return (Object)(object)HeldSpeedloader == (Object)(object)other.HeldSpeedloader;
			}
			return false;
		}

		public static FireArmRoundType SpeedloaderChamberType(Speedloader loader)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			List<SpeedloaderChamber> list = (((Object)(object)loader == (Object)null) ? null : loader.Chambers);
			if (list == null || list.Count == 0 || (Object)(object)list[0] == (Object)null)
			{
				return (FireArmRoundType)0;
			}
			return list[0].Type;
		}

		public static int FreeSpeedloaderChambers(Speedloader loader)
		{
			List<SpeedloaderChamber> list = (((Object)(object)loader == (Object)null) ? null : loader.Chambers);
			if (list == null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				if ((Object)(object)list[i] != (Object)null && !list[i].IsLoaded)
				{
					num++;
				}
			}
			return num;
		}

		public static int LoadedSpeedloaderChambers(Speedloader loader)
		{
			List<SpeedloaderChamber> list = (((Object)(object)loader == (Object)null) ? null : loader.Chambers);
			if (list == null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				if ((Object)(object)list[i] != (Object)null && list[i].IsLoaded)
				{
					num++;
				}
			}
			return num;
		}

		public Transform GetMagMountPos(bool isBeltBox)
		{
			if ((Object)(object)FireArm != (Object)null)
			{
				return FireArm.GetMagMountPos(isBeltBox);
			}
			if (!((Object)(object)Attachable != (Object)null))
			{
				return null;
			}
			return Attachable.MagazineMountPos;
		}

		public FVRFireArmChamber ChamberAt(int index)
		{
			if ((Object)(object)FireArm != (Object)null)
			{
				List<FVRFireArmChamber> chambers = FireArm.GetChambers();
				if (chambers == null || index < 0 || index >= chambers.Count)
				{
					return null;
				}
				return chambers[index];
			}
			if (index != 0)
			{
				return null;
			}
			return AttachableChamber(Attachable);
		}

		public static FVRFireArmChamber AttachableChamber(AttachableFirearm attachable)
		{
			if ((Object)(object)attachable == (Object)null)
			{
				return null;
			}
			AttachableClosedBoltWeapon val = (AttachableClosedBoltWeapon)(object)((attachable is AttachableClosedBoltWeapon) ? attachable : null);
			if ((Object)(object)val != (Object)null)
			{
				return val.Chamber;
			}
			AttachableTubeFed val2 = (AttachableTubeFed)(object)((attachable is AttachableTubeFed) ? attachable : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2.Chamber;
			}
			AttachableBreakActions val3 = (AttachableBreakActions)(object)((attachable is AttachableBreakActions) ? attachable : null);
			if ((Object)(object)val3 != (Object)null)
			{
				return val3.Chamber;
			}
			GP25 val4 = (GP25)(object)((attachable is GP25) ? attachable : null);
			if ((Object)(object)val4 != (Object)null)
			{
				return val4.Chamber;
			}
			M203 val5 = (M203)(object)((attachable is M203) ? attachable : null);
			if ((Object)(object)val5 != (Object)null)
			{
				return val5.Chamber;
			}
			return null;
		}

		public void InsertMagazine(FVRFireArmMagazine magazine)
		{
			if (!((Object)(object)magazine == (Object)null))
			{
				if ((Object)(object)FireArm != (Object)null)
				{
					magazine.Load(FireArm);
				}
				else if ((Object)(object)Attachable != (Object)null)
				{
					magazine.Load(Attachable);
				}
			}
		}

		public bool MagazineIsPresent(FVRFireArmMagazine magazine)
		{
			return (Object)(object)GunMagazine == (Object)(object)magazine;
		}

		public Vector3 GetProbePoint()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)FireArm != (Object)null)
			{
				return FireArmProbe.GetFireArmProbePoint(FireArm);
			}
			if ((Object)(object)Attachable != (Object)null)
			{
				return FireArmProbe.GetAttachableProbePoint(Attachable);
			}
			return FireArmProbe.GetHeldObjectProbePoint((FVRPhysicalObject)(((Object)(object)HeldMagazine != (Object)null) ? HeldMagazine : (((object)HeldClip) ?? ((object)HeldSpeedloader))));
		}

		public void PlayReloadSound()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)FireArm != (Object)null)
				{
					FireArm.PlayAudioEvent((FirearmAudioEventType)28, 1f);
					return;
				}
				if ((Object)(object)Attachable != (Object)null)
				{
					Attachable.PlayAudioEvent((FirearmAudioEventType)28, 1f);
					return;
				}
				FVRFireArmMagazine heldMagazine = HeldMagazine;
				if ((Object)(object)heldMagazine != (Object)null)
				{
					SM.PlayGenericSound(heldMagazine.Profile.MagazineInsertRound, ((Component)heldMagazine).transform.position);
				}
			}
			catch (Exception)
			{
			}
		}
	}
}