Decompiled source of ClipSlapAkimbo v1.0.0

BitWizrd.ClipSlapAkimbo.dll

Decompiled 5 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ClipSlap")]
[assembly: AssemblyDescription("Allows players to slap away empty clips from firearms")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BitWizrd")]
[assembly: AssemblyProduct("ClipSlap")]
[assembly: AssemblyCopyright("Copyright © BitWizrd 2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("B1C2D3E4-F5A6-4B5C-8D7E-9F0A1B2C3D4E")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BitWizrd.ClipSlapAkimbo;

[BepInPlugin("BitWizrd.ClipSlapAkimbo", "ClipSlapAkimbo", "1.0.0")]
[BepInProcess("h3vr.exe")]
public class ClipSlap : BaseUnityPlugin
{
	public class FirearmClipSlapDetector : MonoBehaviour
	{
		private FVRFireArm firearm;

		public void Awake()
		{
			firearm = ((Component)this).GetComponent<FVRFireArm>();
		}

		public void OnCollisionEnter(Collision collision)
		{
			if (!((Object)(object)firearm != (Object)null) || !((FVRInteractiveObject)firearm).IsHeld || IsControllerObject(collision.collider) || collision.transform.IsChildOf(((Component)firearm).transform))
			{
				return;
			}
			if (validClipTriggers.TryGetValue(collision.collider, out var _))
			{
				if (configEnableDebugLogging.Value)
				{
					Logger.LogInfo((object)("Found registered clip trigger " + ((Object)collision.collider).name + " through direct collision"));
				}
				CheckForFirearmClipSlap(firearm, collision.collider);
				return;
			}
			foreach (KeyValuePair<Collider, FVRFireArmClip> validClipTrigger in validClipTriggers)
			{
				if (((Component)validClipTrigger.Key).transform.IsChildOf(collision.transform))
				{
					if (configEnableDebugLogging.Value)
					{
						Logger.LogInfo((object)("Found registered clip trigger " + ((Object)validClipTrigger.Key).name + " through physical collision with " + ((Object)collision.collider).name));
					}
					CheckForFirearmClipSlap(firearm, validClipTrigger.Key);
					break;
				}
			}
		}

		private bool IsControllerObject(Collider collider)
		{
			if ((Object)(object)collider == (Object)null)
			{
				return false;
			}
			string name = ((Object)collider).name;
			if (!name.Contains("Controller") && !name.Equals("Controller (right)") && !name.Equals("Controller (left)") && !name.Contains("Hand"))
			{
				return name.Contains("Tracker");
			}
			return true;
		}
	}

	public class InteractiveObjectClipSlapDetector : MonoBehaviour
	{
		private FVRInteractiveObject interactiveObject;

		public void Awake()
		{
			interactiveObject = ((Component)this).GetComponent<FVRInteractiveObject>();
		}

		public void OnCollisionEnter(Collision collision)
		{
			if (!((Object)(object)interactiveObject != (Object)null) || !interactiveObject.IsHeld || IsControllerObject(collision.collider) || collision.transform.IsChildOf(((Component)interactiveObject).transform))
			{
				return;
			}
			if (validClipTriggers.TryGetValue(collision.collider, out var _))
			{
				if (configEnableDebugLogging.Value)
				{
					Logger.LogInfo((object)("InteractiveObject " + ((Object)interactiveObject).name + " found registered clip trigger " + ((Object)collision.collider).name + " through direct collision"));
				}
				CheckForInteractiveObjectClipSlap(interactiveObject, collision.collider);
				return;
			}
			foreach (KeyValuePair<Collider, FVRFireArmClip> validClipTrigger in validClipTriggers)
			{
				if (((Component)validClipTrigger.Key).transform.IsChildOf(collision.transform))
				{
					if (configEnableDebugLogging.Value)
					{
						Logger.LogInfo((object)("InteractiveObject " + ((Object)interactiveObject).name + " found registered clip trigger " + ((Object)validClipTrigger.Key).name + " through physical collision with " + ((Object)collision.collider).name));
					}
					CheckForInteractiveObjectClipSlap(interactiveObject, validClipTrigger.Key);
					break;
				}
			}
		}

		private bool IsControllerObject(Collider collider)
		{
			if ((Object)(object)collider == (Object)null)
			{
				return false;
			}
			string name = ((Object)collider).name;
			if (!name.Contains("Controller") && !name.Equals("Controller (right)") && !name.Equals("Controller (left)") && !name.Contains("Hand"))
			{
				return name.Contains("Tracker");
			}
			return true;
		}
	}

	private class HandStates
	{
		public FVRViveHand LeftHand;

		public FVRViveHand RightHand;

		public FVRFireArm LeftFirearm;

		public FVRFireArm RightFirearm;
	}

	private class ColliderPair
	{
		public BoxCollider SolidCollider;

		public BoxCollider TriggerCollider;
	}

	internal static ManualLogSource Logger;

	public static ConfigEntry<float> configSlapForce;

	public static ConfigEntry<float> configSlapForceFullClip;

	public static ConfigEntry<float> configSlapThreshold;

	public static ConfigEntry<bool> configEnableDebugLogging;

	public static ConfigEntry<bool> configRequireEmptyClip;

	private const float CLIP_REATTACHMENT_COOLDOWN = 1f;

	public static ConfigEntry<bool> configAutoBoltRelease;

	public static ConfigEntry<bool> configAllowFirearmsToSlap;

	public static ConfigEntry<bool> configAutoLoadClipsFromQuickbelt;

	public static ConfigEntry<bool> configRequireSpawnlockedQuickbelt;

	public static ConfigEntry<bool> configAllowLoadingWithOneFirearm;

	public static ConfigEntry<bool> configFirearmsCanPushDownClipRounds;

	public static ConfigEntry<bool> configClipsCanPressOtherClips;

	public static ConfigEntry<bool> configAllowInteractiveObjectsToSlap;

	public static ConfigEntry<bool> configInteractiveObjectsCanPushDownClipRounds;

	private Harmony harmony;

	private static readonly string HarmonyID = "BitWizrd.ClipSlapAkimbo";

	private static Dictionary<FVRFireArmClip, float> recentlySlappedClips = new Dictionary<FVRFireArmClip, float>();

	private static Dictionary<FVRFireArmClip, float> activeBulletPushOperations = new Dictionary<FVRFireArmClip, float>();

	private static float bulletPushOperationDuration = 0.2f;

	private static List<FVRFireArmClip> updateClipsToRemove = new List<FVRFireArmClip>();

	private static List<int> idsToRemoveFromRegistration = new List<int>();

	private static List<Collider> collidersToUnregister = new List<Collider>();

	private static List<Collider> invalidCollidersToClean = new List<Collider>();

	private static List<Transform> invalidTransformsToClean = new List<Transform>();

	private static List<Rigidbody> invalidRigidbodiesToClean = new List<Rigidbody>();

	private static List<Collider> collidersToStoreForDualWield = new List<Collider>();

	private static StringBuilder stringBuilder = new StringBuilder(32);

	private static Dictionary<Transform, FVRFireArmClip> transformToClipCache = new Dictionary<Transform, FVRFireArmClip>();

	private static Dictionary<Rigidbody, FVRFireArmClip> rigidbodyToClipCache = new Dictionary<Rigidbody, FVRFireArmClip>();

	private static Dictionary<int, FVRFireArmClip> validClipIDs = new Dictionary<int, FVRFireArmClip>();

	private static Dictionary<FVRFireArmClip, int> clipToIdCache = new Dictionary<FVRFireArmClip, int>();

	private static int nextClipID = 1000;

	private static bool isDualWielding = false;

	private static Dictionary<Collider, int> originalColliderLayers = new Dictionary<Collider, int>();

	private static Dictionary<FVRFireArmClip, List<Collider>> trackedClipColliders = new Dictionary<FVRFireArmClip, List<Collider>>();

	private static Dictionary<Collider, FVRFireArmClip> colliderToClipCache = new Dictionary<Collider, FVRFireArmClip>();

	private static HashSet<FVRFireArmClip> activeInteractionClips = new HashSet<FVRFireArmClip>();

	private static Dictionary<FVRFireArm, HashSet<FVRFireArmClip>> firearmActiveClips = new Dictionary<FVRFireArm, HashSet<FVRFireArmClip>>();

	private static bool hasLoggedInitialState = false;

	private static Dictionary<Collider, FVRFireArmClip> validClipTriggers = new Dictionary<Collider, FVRFireArmClip>();

	public static int GetClipID(FVRFireArmClip clip)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return 0;
		}
		if (clipToIdCache.TryGetValue(clip, out var value))
		{
			return value;
		}
		return 0;
	}

	public static int RegisterClipForSlapping(FVRFireArmClip clip)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return 0;
		}
		if (clipToIdCache.TryGetValue(clip, out var value))
		{
			return value;
		}
		int num = nextClipID++;
		validClipIDs[num] = clip;
		clipToIdCache[clip] = num;
		if (configEnableDebugLogging.Value)
		{
			Logger.LogInfo((object)$"Registered clip {((Object)clip).name} with ID {num} for slapping authorization");
		}
		return num;
	}

	public static void UnregisterClipForSlapping(int clipID)
	{
		if (validClipIDs.TryGetValue(clipID, out var value))
		{
			if ((Object)(object)value != (Object)null)
			{
				clipToIdCache.Remove(value);
			}
			validClipIDs.Remove(clipID);
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)string.Format("Unregistered clip {0} with ID {1} from slapping authorization", ((value != null) ? ((Object)value).name : null) ?? "null", clipID));
			}
		}
	}

	public static void UnregisterClipForSlapping(FVRFireArmClip clip)
	{
		if (!((Object)(object)clip == (Object)null) && clipToIdCache.TryGetValue(clip, out var value))
		{
			validClipIDs.Remove(value);
			clipToIdCache.Remove(clip);
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)$"Unregistered clip {((Object)clip).name} with ID {value} from slapping authorization");
			}
		}
	}

	public static bool IsDualWielding()
	{
		return isDualWielding;
	}

	private static void CleanupColliderCache()
	{
		invalidCollidersToClean.Clear();
		invalidTransformsToClean.Clear();
		invalidRigidbodiesToClean.Clear();
		int num = 0;
		int num2 = 0;
		foreach (KeyValuePair<Collider, FVRFireArmClip> item in colliderToClipCache)
		{
			Collider key = item.Key;
			FVRFireArmClip value = item.Value;
			if ((Object)(object)key == (Object)null || (Object)(object)value == (Object)null || (Object)(object)((Component)value).gameObject == (Object)null)
			{
				invalidCollidersToClean.Add(key);
			}
			else
			{
				num++;
			}
		}
		foreach (KeyValuePair<Transform, FVRFireArmClip> item2 in transformToClipCache)
		{
			Transform key2 = item2.Key;
			FVRFireArmClip value2 = item2.Value;
			if ((Object)(object)key2 == (Object)null || (Object)(object)value2 == (Object)null || (Object)(object)((Component)value2).gameObject == (Object)null)
			{
				invalidTransformsToClean.Add(key2);
			}
		}
		foreach (KeyValuePair<Rigidbody, FVRFireArmClip> item3 in rigidbodyToClipCache)
		{
			Rigidbody key3 = item3.Key;
			FVRFireArmClip value3 = item3.Value;
			if ((Object)(object)key3 == (Object)null || (Object)(object)value3 == (Object)null || (Object)(object)((Component)value3).gameObject == (Object)null)
			{
				invalidRigidbodiesToClean.Add(key3);
			}
		}
		foreach (Collider item4 in invalidCollidersToClean)
		{
			colliderToClipCache.Remove(item4);
			num2++;
		}
		foreach (Transform item5 in invalidTransformsToClean)
		{
			transformToClipCache.Remove(item5);
			num2++;
		}
		foreach (Rigidbody item6 in invalidRigidbodiesToClean)
		{
			rigidbodyToClipCache.Remove(item6);
			num2++;
		}
		if (configEnableDebugLogging.Value && num2 > 0)
		{
			Logger.LogInfo((object)$"Cleaned up {num2} invalid cache entries, kept {num} valid collider entries");
		}
	}

	public static void RemoveClipFromCache(FVRFireArmClip clip)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return;
		}
		if ((Object)(object)((Component)clip).gameObject == (Object)null)
		{
			List<Collider> list = new List<Collider>();
			foreach (KeyValuePair<Collider, FVRFireArmClip> item in colliderToClipCache)
			{
				if ((Object)(object)item.Value == (Object)(object)clip)
				{
					list.Add(item.Key);
				}
			}
			foreach (Collider item2 in list)
			{
				colliderToClipCache.Remove(item2);
			}
			if (configEnableDebugLogging.Value && list.Count > 0)
			{
				Logger.LogInfo((object)$"Removed {list.Count} cache entries for destroyed clip {((Object)clip).name}");
			}
		}
		else if (configEnableDebugLogging.Value)
		{
			Logger.LogInfo((object)("Skipped cache removal for active clip " + ((Object)clip).name + " - keeping cache entries for future use"));
		}
	}

	private void Awake()
	{
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Expected O, but got Unknown
		Logger = ((BaseUnityPlugin)this).Logger;
		configSlapForce = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "Slap Force Multiplier", 1.75f, "Multiplier for the force applied to the clip when slapped (for empty clips)");
		configSlapForceFullClip = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "Full Clip Slap Force", 0.75f, "Multiplier for the force applied to the clip when slapped (for full clips)");
		configSlapThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Settings", "Slap Velocity Threshold", 1.75f, "Minimum velocity required to slap a clip");
		configRequireEmptyClip = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Require Empty Clip", false, "If true, clips can only be slapped out when empty. If false, any clip can be slapped out with force based on how full it is.");
		configEnableDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Enable Debug Logging", false, "If true, enables debug logging");
		configAutoBoltRelease = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Auto Bolt Release", false, "If true, automatically releases the bolt/slide when a clip is slapped out (if the firearm supports it)");
		configAllowFirearmsToSlap = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Allow Firearms To Slap", true, "If true, firearms can slap clips out of other guns");
		configAutoLoadClipsFromQuickbelt = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Auto Load Clips From Quickbelt", true, "If true, automatically loads compatible clips from quickbelt slots when a handgun is hovering over them");
		configRequireSpawnlockedQuickbelt = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Only Load From Spawnlocked Slots", false, "If true, clips will only auto-load from quickbelt slots that are spawnlocked");
		configAllowLoadingWithOneFirearm = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Allow Loading When Wielding One Handgun", false, "If true, clips can be auto-loaded when only one hand has a handgun. If false (default), both hands must be holding firearms for auto-loading to work.");
		configFirearmsCanPushDownClipRounds = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Firearms Can Push Down Clip Rounds", true, "If true, allows a firearm in one hand to push rounds from a clip in the other hand (as if dual wielding)");
		configClipsCanPressOtherClips = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Clips Can Press Other Clips", true, "If true, clips inserted in firearms can press into each other to load rounds when both hands are holding firearms with clips");
		configAllowInteractiveObjectsToSlap = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Allow Interactive Objects To Slap", true, "If true, any held FVRInteractiveObject can slap clips out of firearms");
		configInteractiveObjectsCanPushDownClipRounds = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "Interactive Objects Can Push Down Clip Rounds", true, "If true, allows any held FVRInteractiveObject to push rounds from clips when dual wielding");
		harmony = new Harmony(HarmonyID);
		harmony.PatchAll();
		Logger.LogInfo((object)"ClipSlapAkimbo plugin loaded!");
	}

	private void Update()
	{
		updateClipsToRemove.Clear();
		CleanupTimedDictionary(recentlySlappedClips, 1f, updateClipsToRemove);
		CleanupCooldownDictionary(activeBulletPushOperations, updateClipsToRemove);
	}

	public static bool WasRecentlySlapped(FVRFireArmClip clip)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return false;
		}
		bool num = recentlySlappedClips.ContainsKey(clip);
		if (num && configEnableDebugLogging.Value)
		{
			Logger.LogInfo((object)$"Clip {((Object)clip).name} was recently slapped, remaining cooldown: {recentlySlappedClips[clip]}s");
		}
		return num;
	}

	public static void RegisterBulletPushOperation(FVRFireArmClip clip)
	{
		if (!((Object)(object)clip == (Object)null))
		{
			activeBulletPushOperations[clip] = Time.time + bulletPushOperationDuration;
		}
	}

	public static bool IsClipInBulletPushOperation(FVRFireArmClip clip)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return false;
		}
		if (activeBulletPushOperations.ContainsKey(clip))
		{
			return Time.time < activeBulletPushOperations[clip];
		}
		return false;
	}

	public static void CheckForClipSlap(FVRViveHand hand, Collider collider)
	{
		if ((Object)(object)hand == (Object)null || hand.PhysTracker == null)
		{
			return;
		}
		FVRFireArmClip val = null;
		if (validClipTriggers.TryGetValue(collider, out var value))
		{
			val = value;
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)$"[Direct Hit] Hand {((Object)hand).name} hit registered clip trigger {((Object)collider).name}");
			}
		}
		else
		{
			foreach (KeyValuePair<Collider, FVRFireArmClip> validClipTrigger in validClipTriggers)
			{
				if (((Component)validClipTrigger.Key).transform.IsChildOf(((Component)collider).transform))
				{
					val = validClipTrigger.Value;
					if (configEnableDebugLogging.Value)
					{
						Logger.LogInfo((object)$"[Child Hit] Hand {((Object)hand).name} hit {((Object)collider).name}, found child clip trigger {((Object)validClipTrigger.Key).name}");
					}
					break;
				}
			}
		}
		if ((Object)(object)val != (Object)null)
		{
			ProcessClipSlap(hand, val);
		}
	}

	private static void ProcessClipSlap(FVRViveHand hand, FVRFireArmClip clip)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		//IL_009d: 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_014e: Unknown result type (might be due to invalid IL or missing references)
		if ((int)clip.State != 1 || (Object)(object)clip.FireArm == (Object)null)
		{
			return;
		}
		bool flag = false;
		int num = 0;
		foreach (KeyValuePair<int, FVRFireArmClip> validClipID in validClipIDs)
		{
			if ((Object)(object)validClipID.Value == (Object)(object)clip)
			{
				flag = true;
				num = validClipID.Key;
				break;
			}
		}
		if (!flag)
		{
			return;
		}
		if (configEnableDebugLogging.Value)
		{
			Logger.LogInfo((object)$"CheckForClipSlap: Target clip {((Object)clip).name} has valid ID {num} for slapping");
		}
		Vector3 velocity = hand.PhysTracker.Velocity;
		float num2 = Mathf.Max(((Vector3)(ref velocity)).magnitude, ((Vector3)(ref hand.Input.VelLinearLocal)).magnitude);
		if (num2 < configSlapThreshold.Value)
		{
			return;
		}
		FVRInteractiveObject currentInteractable = hand.CurrentInteractable;
		FVRFireArm val = (FVRFireArm)(object)((currentInteractable is FVRFireArm) ? currentInteractable : null);
		if ((Object)(object)val != (Object)null)
		{
			TrackClipForInteraction(clip, val);
		}
		FVRInteractiveObject currentInteractable2 = hand.CurrentInteractable;
		FVRFireArm val2 = (FVRFireArm)(object)((currentInteractable2 is FVRFireArm) ? currentInteractable2 : null);
		if (!ValidateClipSlapConditions(clip, val2))
		{
			if ((Object)(object)val2 != (Object)null && (Object)(object)clip.FireArm == (Object)(object)val2)
			{
				LogDebug("Prevented self-slap: Hand is holding the gun that contains this clip");
			}
		}
		else
		{
			LogDebug($"SUCCESS: Hand slapping clip {((Object)clip).name} with velocity: {num2}");
			ProcessSlap(clip, num2, ((Vector3)(ref hand.Input.VelLinearWorld)).normalized);
		}
	}

	public static bool IsClipCompatibleWithFirearm(FVRFireArmClip clip, FVRFireArm firearm)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)clip == (Object)null || (Object)(object)firearm == (Object)null)
		{
			return false;
		}
		if (firearm.ClipType != clip.ClipType)
		{
			return false;
		}
		if ((Object)(object)firearm.Clip != (Object)null)
		{
			return false;
		}
		return true;
	}

	public static bool BothHandsHaveFirearmsWithClips()
	{
		if ((Object)(object)GM.CurrentMovementManager == (Object)null || GM.CurrentMovementManager.Hands == null || GM.CurrentMovementManager.Hands.Length < 2)
		{
			return false;
		}
		FVRViveHand val = GM.CurrentMovementManager.Hands[0];
		FVRViveHand val2 = GM.CurrentMovementManager.Hands[1];
		if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
		{
			return false;
		}
		FVRInteractiveObject currentInteractable = val.CurrentInteractable;
		FVRFireArm val3 = (FVRFireArm)(object)((currentInteractable is FVRFireArm) ? currentInteractable : null);
		FVRInteractiveObject currentInteractable2 = val2.CurrentInteractable;
		FVRFireArm val4 = (FVRFireArm)(object)((currentInteractable2 is FVRFireArm) ? currentInteractable2 : null);
		if ((Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null)
		{
			return false;
		}
		if ((Object)(object)val3.Clip != (Object)null)
		{
			return (Object)(object)val4.Clip != (Object)null;
		}
		return false;
	}

	public static bool BothHandsHaveFirearms()
	{
		FVRMovementManager currentMovementManager = GM.CurrentMovementManager;
		if (currentMovementManager?.Hands == null || currentMovementManager.Hands.Length < 2)
		{
			UpdateDualWieldState(newState: false);
			return false;
		}
		FVRViveHand val = currentMovementManager.Hands[0];
		FVRViveHand val2 = currentMovementManager.Hands[1];
		if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
		{
			UpdateDualWieldState(newState: false);
			return false;
		}
		FVRInteractiveObject currentInteractable = val.CurrentInteractable;
		FVRInteractiveObject obj = ((currentInteractable is FVRFireArm) ? currentInteractable : null);
		FVRInteractiveObject currentInteractable2 = val2.CurrentInteractable;
		FVRFireArm val3 = (FVRFireArm)(object)((currentInteractable2 is FVRFireArm) ? currentInteractable2 : null);
		if ((Object)(object)obj != (Object)null)
		{
			return (Object)(object)val3 != (Object)null;
		}
		return false;
	}

	public static bool BothHandsHaveInteractableObjects()
	{
		FVRMovementManager currentMovementManager = GM.CurrentMovementManager;
		if (currentMovementManager?.Hands == null || currentMovementManager.Hands.Length < 2)
		{
			return false;
		}
		FVRViveHand val = currentMovementManager.Hands[0];
		FVRViveHand val2 = currentMovementManager.Hands[1];
		if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
		{
			return false;
		}
		FVRInteractiveObject currentInteractable = val.CurrentInteractable;
		FVRInteractiveObject currentInteractable2 = val2.CurrentInteractable;
		if ((Object)(object)currentInteractable != (Object)null)
		{
			return (Object)(object)currentInteractable2 != (Object)null;
		}
		return false;
	}

	public static bool HandsHaveMixedInteractables()
	{
		FVRMovementManager currentMovementManager = GM.CurrentMovementManager;
		if (currentMovementManager?.Hands == null || currentMovementManager.Hands.Length < 2)
		{
			return false;
		}
		FVRViveHand val = currentMovementManager.Hands[0];
		FVRViveHand val2 = currentMovementManager.Hands[1];
		if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
		{
			return false;
		}
		FVRInteractiveObject currentInteractable = val.CurrentInteractable;
		FVRFireArm val3 = (FVRFireArm)(object)((currentInteractable is FVRFireArm) ? currentInteractable : null);
		FVRInteractiveObject currentInteractable2 = val2.CurrentInteractable;
		FVRFireArm val4 = (FVRFireArm)(object)((currentInteractable2 is FVRFireArm) ? currentInteractable2 : null);
		FVRInteractiveObject currentInteractable3 = val.CurrentInteractable;
		FVRInteractiveObject currentInteractable4 = val2.CurrentInteractable;
		bool flag = (Object)(object)val3 != (Object)null;
		bool flag2 = (Object)(object)val4 != (Object)null;
		bool flag3 = (Object)(object)currentInteractable3 != (Object)null;
		bool flag4 = (Object)(object)currentInteractable4 != (Object)null;
		if (!(flag && flag4))
		{
			return flag2 && flag3;
		}
		return true;
	}

	public static void CreateTemporaryBulletCollider(FVRFireArmClip clip)
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)clip == (Object)null || !clip.HasARound())
		{
			return;
		}
		GameObject val = FindTopActiveBulletDisplay(clip);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		MeshFilter component = val.GetComponent<MeshFilter>();
		MeshRenderer component2 = val.GetComponent<MeshRenderer>();
		if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component.mesh == (Object)null)
		{
			return;
		}
		ColliderPair colliderPair = FindExistingColliders(val);
		BoxCollider val2 = colliderPair.SolidCollider;
		BoxCollider val3 = colliderPair.TriggerCollider;
		bool flag = false;
		bool flag2 = false;
		Bounds bounds = component.mesh.bounds;
		if ((Object)(object)val2 == (Object)null)
		{
			val2 = CreateConfiguredBoxCollider(val, bounds, isTrigger: false);
			flag = true;
		}
		else
		{
			val2.size = ((Bounds)(ref bounds)).size;
			val2.center = ((Bounds)(ref bounds)).center;
		}
		if ((Object)(object)val3 == (Object)null)
		{
			val3 = CreateConfiguredBoxCollider(val, bounds, isTrigger: true, 1.4f);
			flag2 = true;
		}
		else
		{
			val3.size = ((Bounds)(ref bounds)).size * 1.4f;
			val3.center = ((Bounds)(ref bounds)).center;
		}
		BulletTriggerDetector bulletTriggerDetector = val.GetComponent<BulletTriggerDetector>();
		bool flag3 = false;
		if ((Object)(object)bulletTriggerDetector == (Object)null)
		{
			bulletTriggerDetector = val.AddComponent<BulletTriggerDetector>();
			flag3 = true;
		}
		bulletTriggerDetector.parentClip = clip;
		((Behaviour)bulletTriggerDetector).enabled = true;
		val.layer = LayerMask.NameToLayer("Default");
		FVRFireArmClipFixedUpdatePatch.temporaryBulletColliders[clip] = val2;
		FVRFireArmClipFixedUpdatePatch.temporaryBulletTriggers[clip] = val3;
		if (!configEnableDebugLogging.Value)
		{
			return;
		}
		string text = "";
		if (flag || flag2 || flag3)
		{
			text = "Created";
			if (flag)
			{
				text += " solid-collider";
			}
			if (flag2)
			{
				text += " trigger-collider";
			}
			if (flag3)
			{
				text += " detector";
			}
		}
		else
		{
			text = "Reused existing";
		}
		Logger.LogInfo((object)(text + " bullet colliders for " + ((Object)clip).name));
	}

	public static void RemoveTemporaryBulletCollider(FVRFireArmClip clip)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return;
		}
		if (configEnableDebugLogging.Value)
		{
			Logger.LogInfo((object)("Disabling all bullet colliders for " + ((Object)clip).name));
		}
		int layerID = LayerMask.NameToLayer("NoCol");
		int num = SetGameObjectArrayToLayer(clip.DisplayBullets, layerID);
		if (clip.DisplayBullets != null)
		{
			GameObject[] displayBullets = clip.DisplayBullets;
			foreach (GameObject val in displayBullets)
			{
				if ((Object)(object)val != (Object)null)
				{
					BulletTriggerDetector component = val.GetComponent<BulletTriggerDetector>();
					if ((Object)(object)component != (Object)null)
					{
						((Behaviour)component).enabled = false;
					}
				}
			}
		}
		LogDebug($"Disabled {num} colliders by setting to NoCol layer");
		if (FVRFireArmClipFixedUpdatePatch.temporaryBulletColliders.ContainsKey(clip))
		{
			FVRFireArmClipFixedUpdatePatch.temporaryBulletColliders.Remove(clip);
		}
		if (FVRFireArmClipFixedUpdatePatch.temporaryBulletTriggers.ContainsKey(clip))
		{
			FVRFireArmClipFixedUpdatePatch.temporaryBulletTriggers.Remove(clip);
		}
	}

	public static void HandleBulletTriggerFirearmInteraction(FVRFireArmClip clip, FVRFireArm firearm, Collider firearmCollider)
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: 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)
		if ((Object)(object)clip == (Object)null || (Object)(object)firearm == (Object)null)
		{
			return;
		}
		RegisterBulletPushOperation(clip);
		if (!configFirearmsCanPushDownClipRounds.Value)
		{
			return;
		}
		string key = $"{((Object)firearm).GetInstanceID()}_{((Object)clip).GetInstanceID()}";
		if (FVRFireArmClipFixedUpdatePatch.processedClipPairsThisFrame.TryGetValue(key, out var _))
		{
			return;
		}
		FVRFireArmClipFixedUpdatePatch.processedClipPairsThisFrame[key] = Time.time;
		Vector3 velLinearWorld = ((FVRInteractiveObject)firearm).m_hand.Input.VelLinearWorld;
		if (((Vector3)(ref velLinearWorld)).magnitude > 0.1f && Vector3.Angle(velLinearWorld, -((Component)clip).transform.up) < 45f)
		{
			if (!TryPushRoundFromClipToMag(clip, $"Trigger-based firearm {((Object)firearm).name}"))
			{
				LogDebug($"Firearm {((Object)firearm).name} could not push from clip {((Object)clip).name}: {GetClipPushFailureReason(clip)}");
			}
			else
			{
				LogDebug($"Firearm {((Object)firearm).name} pushed round from clip {((Object)clip).name}");
			}
		}
	}

	public static void HandleBulletTriggerInteractiveObjectInteraction(FVRFireArmClip clip, FVRInteractiveObject interactiveObject, Collider objectCollider)
	{
		//IL_007b: 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)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: 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)
		if ((Object)(object)clip == (Object)null || (Object)(object)interactiveObject == (Object)null || interactiveObject is FVRFireArm)
		{
			return;
		}
		RegisterBulletPushOperation(clip);
		if (!configInteractiveObjectsCanPushDownClipRounds.Value)
		{
			return;
		}
		string key = $"{((Object)interactiveObject).GetInstanceID()}_{((Object)clip).GetInstanceID()}";
		if (FVRFireArmClipFixedUpdatePatch.processedClipPairsThisFrame.TryGetValue(key, out var _))
		{
			return;
		}
		FVRFireArmClipFixedUpdatePatch.processedClipPairsThisFrame[key] = Time.time;
		Vector3 velLinearWorld = interactiveObject.m_hand.Input.VelLinearWorld;
		if (((Vector3)(ref velLinearWorld)).magnitude > 0.1f && Vector3.Angle(velLinearWorld, -((Component)clip).transform.up) < 45f)
		{
			if (!TryPushRoundFromClipToMag(clip, $"Trigger-based interactive object {((Object)interactiveObject).name}"))
			{
				LogDebug($"Interactive object {((Object)interactiveObject).name} could not push from clip {((Object)clip).name}: {GetClipPushFailureReason(clip)}");
			}
			else
			{
				LogDebug($"Interactive object {((Object)interactiveObject).name} pushed round from clip {((Object)clip).name}");
			}
		}
	}

	public static void HandleBulletTriggerClipInteraction(FVRFireArmClip sourceClip, FVRFireArmClip targetClip)
	{
		if ((Object)(object)sourceClip == (Object)null || (Object)(object)targetClip == (Object)null)
		{
			return;
		}
		RegisterBulletPushOperation(sourceClip);
		RegisterBulletPushOperation(targetClip);
		if (!configClipsCanPressOtherClips.Value)
		{
			return;
		}
		bool num = BothHandsHaveFirearmsWithClips();
		bool flag = HandsHaveMixedInteractables();
		if (!num && !flag)
		{
			if (configEnableDebugLogging.Value)
			{
				LogDebug("Clip-to-clip interaction skipped: No valid dual-wield state for clip interaction");
				HandStates handStates = GetHandStates();
				LogDebug("Left hand: " + (((Object)(object)handStates.LeftFirearm != (Object)null) ? ((Object)handStates.LeftFirearm).name : "no firearm") + ", clip: " + (((Object)(object)handStates.LeftFirearm != (Object)null && (Object)(object)handStates.LeftFirearm.Clip != (Object)null) ? ((Object)handStates.LeftFirearm.Clip).name : "none"));
				LogDebug("Right hand: " + (((Object)(object)handStates.RightFirearm != (Object)null) ? ((Object)handStates.RightFirearm).name : "no firearm") + ", clip: " + (((Object)(object)handStates.RightFirearm != (Object)null && (Object)(object)handStates.RightFirearm.Clip != (Object)null) ? ((Object)handStates.RightFirearm.Clip).name : "none"));
			}
			return;
		}
		string key = GenerateClipPairKey(sourceClip, targetClip);
		if (!FVRFireArmClipFixedUpdatePatch.processedClipPairsThisFrame.TryGetValue(key, out var _))
		{
			FVRFireArmClipFixedUpdatePatch.processedClipPairsThisFrame[key] = Time.time;
			LogDebug("Clip trigger overlap detected: " + ((Object)sourceClip).name + " <-> " + ((Object)targetClip).name);
			bool flag2 = false;
			bool flag3 = false;
			flag2 = TryPushRoundFromClipToMag(sourceClip, "Source clip " + ((Object)sourceClip).name);
			if (!flag2)
			{
				LogDebug("Source clip " + ((Object)sourceClip).name + " could not push: " + GetClipPushFailureReason(sourceClip));
			}
			flag3 = TryPushRoundFromClipToMag(targetClip, "Target clip " + ((Object)targetClip).name);
			if (!flag3)
			{
				LogDebug("Target clip " + ((Object)targetClip).name + " could not push: " + GetClipPushFailureReason(targetClip));
			}
			LogDebug($"Trigger overlap result: {((Object)sourceClip).name} pushed={flag2}, {((Object)targetClip).name} pushed={flag3}");
		}
	}

	private static FVRFireArmClip FindClipFromCollider(Collider collider)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Invalid comparison between Unknown and I4
		if ((Object)(object)collider == (Object)null)
		{
			return null;
		}
		if (colliderToClipCache.TryGetValue(collider, out var value))
		{
			if (IsCacheEntryValid(value) && (int)value.State == 1 && (Object)(object)value.FireArm != (Object)null)
			{
				return value;
			}
			colliderToClipCache.Remove(collider);
		}
		FVRFireArmClip value2 = null;
		Transform transform = ((Component)collider).transform;
		if (transformToClipCache.TryGetValue(transform, out value2) && !IsCacheEntryValid(value2))
		{
			transformToClipCache.Remove(transform);
			value2 = null;
		}
		if ((Object)(object)value2 == (Object)null)
		{
			value2 = ((Component)collider).GetComponent<FVRFireArmClip>();
			if ((Object)(object)value2 != (Object)null)
			{
				transformToClipCache[transform] = value2;
			}
		}
		if ((Object)(object)value2 == (Object)null)
		{
			FVRFireArmClipInterface component = ((Component)collider).GetComponent<FVRFireArmClipInterface>();
			if ((Object)(object)component != (Object)null && ((Behaviour)component).isActiveAndEnabled)
			{
				value2 = component.Clip;
			}
		}
		if ((Object)(object)value2 == (Object)null && (Object)(object)collider.attachedRigidbody != (Object)null)
		{
			Rigidbody attachedRigidbody = collider.attachedRigidbody;
			if (rigidbodyToClipCache.TryGetValue(attachedRigidbody, out value2) && !IsCacheEntryValid(value2))
			{
				rigidbodyToClipCache.Remove(attachedRigidbody);
				value2 = null;
			}
			if ((Object)(object)value2 == (Object)null)
			{
				value2 = ((Component)attachedRigidbody).GetComponent<FVRFireArmClip>();
				if ((Object)(object)value2 != (Object)null)
				{
					rigidbodyToClipCache[attachedRigidbody] = value2;
				}
			}
		}
		if ((Object)(object)value2 != (Object)null)
		{
			colliderToClipCache[collider] = value2;
		}
		return value2;
	}

	private static void ProcessSlap(FVRFireArmClip clip, float velocityMagnitude, Vector3 slapDirection)
	{
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		FVRFireArm fireArm = clip.FireArm;
		float num = 0f;
		if (clip.m_capacity > 0)
		{
			num = (float)clip.m_numRounds / (float)clip.m_capacity;
		}
		float num2 = Mathf.Lerp(configSlapForce.Value, configSlapForceFullClip.Value, num);
		float num3 = velocityMagnitude * num2;
		if (configEnableDebugLogging.Value)
		{
			Logger.LogInfo((object)$"Processing slap for clip {((Object)clip).name}: force={num3}, direction={slapDirection}");
		}
		RestoreClipCollidersFromDualWield(clip);
		if ((Object)(object)fireArm != (Object)null)
		{
			fireArm.EjectClip();
			if (configAutoBoltRelease.Value)
			{
				TryReleaseBoltOrSlide(fireArm);
			}
		}
		recentlySlappedClips[clip] = 1f;
		if ((Object)(object)((FVRPhysicalObject)clip).RootRigidbody != (Object)null)
		{
			Vector3 velocity = ((FVRPhysicalObject)clip).RootRigidbody.velocity;
			Vector3 val = slapDirection * num3;
			((FVRPhysicalObject)clip).RootRigidbody.velocity = velocity + val;
			Rigidbody rootRigidbody = ((FVRPhysicalObject)clip).RootRigidbody;
			rootRigidbody.angularVelocity += new Vector3(Random.Range(-5f, 5f), Random.Range(-5f, 5f), Random.Range(-5f, 5f));
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)$"Applied additional slap velocity {((Vector3)(ref val)).magnitude:F2} to clip {((Object)clip).name}");
			}
		}
	}

	private static void TryReleaseBoltOrSlide(FVRFireArm fireArm)
	{
		if ((Object)(object)fireArm == (Object)null)
		{
			return;
		}
		ClosedBoltWeapon val = (ClosedBoltWeapon)(object)((fireArm is ClosedBoltWeapon) ? fireArm : null);
		if ((Object)(object)val != (Object)null && (Object)(object)val.Bolt != (Object)null && val.HasBoltReleaseButton)
		{
			if (val.Bolt.IsBoltLocked())
			{
				val.Bolt.ReleaseBolt();
				LogDebug("Released bolt on ClosedBoltWeapon: " + ((Object)fireArm).name);
			}
			return;
		}
		Handgun val2 = (Handgun)(object)((fireArm is Handgun) ? fireArm : null);
		if ((Object)(object)val2 != (Object)null && val2.HasSlideReleaseControl)
		{
			if (val2.IsSlideCatchEngaged())
			{
				val2.DropSlideRelease();
				LogDebug("Released slide on Handgun: " + ((Object)fireArm).name);
			}
			return;
		}
		OpenBoltReceiver val3 = (OpenBoltReceiver)(object)((fireArm is OpenBoltReceiver) ? fireArm : null);
		if ((Object)(object)val3 != (Object)null)
		{
			if (val3.IsBoltCatchEngaged())
			{
				LogDebug("Attempting to release bolt on OpenBoltReceiver: " + ((Object)fireArm).name);
				TryInvokeMethod(val3, "DisEngageBoltCatch");
			}
			return;
		}
		LogDebug("Attempting to use reflection to release bolt on: " + ((object)fireArm).GetType().Name);
		Component val4 = null;
		Component[] componentsInChildren = ((Component)fireArm).GetComponentsInChildren<Component>();
		foreach (Component val5 in componentsInChildren)
		{
			if (((object)val5).GetType().Name.Contains("Bolt") || ((object)val5).GetType().Name.Contains("Slide"))
			{
				val4 = val5;
				break;
			}
		}
		if ((Object)(object)val4 != (Object)null && !TryInvokeMethod(val4, "ReleaseBolt"))
		{
			TryInvokeMethod(val4, "DropSlideRelease");
		}
	}

	public static void UpdateDualWieldState(bool newState)
	{
		if (!hasLoggedInitialState && configEnableDebugLogging.Value)
		{
			FVRMovementManager currentMovementManager = GM.CurrentMovementManager;
			if (currentMovementManager?.Hands != null && currentMovementManager.Hands.Length >= 2)
			{
				FVRViveHand obj = currentMovementManager.Hands[0];
				FVRViveHand val = currentMovementManager.Hands[1];
				FVRInteractiveObject obj2 = ((obj != null) ? obj.CurrentInteractable : null);
				FVRFireArm val2 = (FVRFireArm)(object)((obj2 is FVRFireArm) ? obj2 : null);
				FVRInteractiveObject obj3 = ((val != null) ? val.CurrentInteractable : null);
				FVRFireArm val3 = (FVRFireArm)(object)((obj3 is FVRFireArm) ? obj3 : null);
				Logger.LogInfo((object)string.Format("Initial dual-wield state: Left={0}, Right={1}, Result={2}", ((val2 != null) ? ((Object)val2).name : null) ?? "null", ((val3 != null) ? ((Object)val3).name : null) ?? "null", newState));
			}
			hasLoggedInitialState = true;
		}
		if (isDualWielding == newState)
		{
			return;
		}
		if (configEnableDebugLogging.Value)
		{
			FVRMovementManager currentMovementManager2 = GM.CurrentMovementManager;
			if (currentMovementManager2?.Hands != null && currentMovementManager2.Hands.Length >= 2)
			{
				FVRViveHand obj4 = currentMovementManager2.Hands[0];
				FVRViveHand val4 = currentMovementManager2.Hands[1];
				FVRInteractiveObject obj5 = ((obj4 != null) ? obj4.CurrentInteractable : null);
				FVRFireArm val5 = (FVRFireArm)(object)((obj5 is FVRFireArm) ? obj5 : null);
				FVRInteractiveObject obj6 = ((val4 != null) ? val4.CurrentInteractable : null);
				FVRFireArm val6 = (FVRFireArm)(object)((obj6 is FVRFireArm) ? obj6 : null);
				Logger.LogInfo((object)string.Format("Dual-wield state changed: Left={0}, Right={1}, {2} -> {3}", ((val5 != null) ? ((Object)val5).name : null) ?? "null", ((val6 != null) ? ((Object)val6).name : null) ?? "null", isDualWielding, newState));
			}
		}
		isDualWielding = newState;
		if (!newState)
		{
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)$"Restoring {activeInteractionClips.Count} active clips from dual-wield state");
			}
			foreach (FVRFireArmClip item in new HashSet<FVRFireArmClip>(activeInteractionClips))
			{
				if ((Object)(object)item != (Object)null && (Object)(object)((Component)item).gameObject != (Object)null)
				{
					RestoreClipCollidersFromDualWield(item);
					if (configEnableDebugLogging.Value)
					{
						Logger.LogInfo((object)$"Restored clip {((Object)item).name} to normal state");
					}
				}
			}
			activeInteractionClips.Clear();
			firearmActiveClips.Clear();
		}
		else
		{
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)"Entered dual-wield mode - configuring all clips in held firearms");
			}
			ConfigureExistingClipsForDualWield();
		}
	}

	private static void ConfigureExistingClipsForDualWield()
	{
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Invalid comparison between Unknown and I4
		FVRMovementManager currentMovementManager = GM.CurrentMovementManager;
		if (currentMovementManager?.Hands == null || currentMovementManager.Hands.Length < 2)
		{
			return;
		}
		FVRViveHand val = currentMovementManager.Hands[0];
		FVRViveHand val2 = currentMovementManager.Hands[1];
		if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
		{
			return;
		}
		FVRFireArm[] obj = new FVRFireArm[2]
		{
			(FVRFireArm)/*isinst with value type is only supported in some contexts*/,
			(FVRFireArm)/*isinst with value type is only supported in some contexts*/
		};
		int num = 0;
		FVRFireArm[] array = (FVRFireArm[])(object)obj;
		foreach (FVRFireArm val3 in array)
		{
			if ((Object)(object)val3 != (Object)null && (Object)(object)val3.Clip != (Object)null && (int)val3.Clip.State == 1)
			{
				FVRFireArmClip clip = val3.Clip;
				RemoveTemporaryBulletCollider(clip);
				if (clip.HasARound())
				{
					CreateTemporaryBulletCollider(clip);
				}
				TrackClipForInteraction(clip, val3);
				num++;
				if (configEnableDebugLogging.Value)
				{
					Logger.LogInfo((object)$"Configured existing clip {((Object)clip).name} in firearm {((Object)val3).name} for dual-wield mode (bullets: {clip.m_numRounds})");
				}
			}
		}
		if (configEnableDebugLogging.Value && num > 0)
		{
			Logger.LogInfo((object)$"Configured {num} existing clips for dual-wield mode");
		}
	}

	public static void TrackClipForInteraction(FVRFireArmClip clip, FVRFireArm firearm)
	{
		if ((Object)(object)clip == (Object)null || (Object)(object)firearm == (Object)null)
		{
			return;
		}
		bool flag = activeInteractionClips.Contains(clip);
		activeInteractionClips.Add(clip);
		if (!firearmActiveClips.ContainsKey(firearm))
		{
			firearmActiveClips[firearm] = new HashSet<FVRFireArmClip>();
		}
		firearmActiveClips[firearm].Add(clip);
		if (isDualWielding)
		{
			StoreAndSetClipCollidersForDualWield(clip, flag);
			if (configEnableDebugLogging.Value && flag)
			{
				Logger.LogInfo((object)$"Reconfigured already tracked clip {((Object)clip).name} for dual-wield mode");
			}
		}
	}

	public static void UntrackClipFromInteraction(FVRFireArmClip clip, FVRFireArm firearm)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return;
		}
		activeInteractionClips.Remove(clip);
		if ((Object)(object)firearm != (Object)null && firearmActiveClips.ContainsKey(firearm))
		{
			firearmActiveClips[firearm].Remove(clip);
			if (firearmActiveClips[firearm].Count == 0)
			{
				firearmActiveClips.Remove(firearm);
			}
		}
		RestoreClipCollidersFromDualWield(clip);
	}

	public static void StoreAndSetClipCollidersForDualWield(FVRFireArmClip clip, bool forceReconfigure = false)
	{
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_0265: Unknown result type (might be due to invalid IL or missing references)
		//IL_030a: Unknown result type (might be due to invalid IL or missing references)
		//IL_030f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0322: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)clip == (Object)null)
		{
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)"StoreAndSetClipCollidersForDualWield: Clip is null, returning");
			}
			return;
		}
		if (trackedClipColliders.ContainsKey(clip) && !forceReconfigure)
		{
			LogDebug("StoreAndSetClipCollidersForDualWield: Clip " + ((Object)clip).name + " already configured, skipping");
			return;
		}
		if (forceReconfigure && trackedClipColliders.ContainsKey(clip))
		{
			LogDebug($"StoreAndSetClipCollidersForDualWield: Force reconfiguring clip {((Object)clip).name} (current bullets: {clip.m_numRounds})");
			RestoreClipCollidersFromDualWield(clip);
			RemoveTemporaryBulletCollider(clip);
			if (clip.HasARound())
			{
				CreateTemporaryBulletCollider(clip);
				LogDebug($"Created bullet colliders for current state: {clip.m_numRounds} bullets");
			}
			else
			{
				LogDebug("No bullets remaining, no bullet colliders created");
			}
		}
		LogDebug("StoreAndSetClipCollidersForDualWield: Processing clip " + ((Object)clip).name);
		List<Collider> list = new List<Collider>();
		if ((Object)(object)clip.Interface != (Object)null)
		{
			Collider component = ((Component)clip.Interface).GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				StoreAndSetColliderLayer(component, "NoCol", list);
			}
		}
		Collider[] componentsInChildren = ((Component)clip).GetComponentsInChildren<Collider>(true);
		HashSet<Collider> hashSet = new HashSet<Collider>();
		Collider[] componentsInChildren2;
		if (clip.DisplayBullets != null && clip.DisplayBullets.Length != 0)
		{
			int numRounds = clip.m_numRounds;
			for (int i = 0; i < clip.DisplayBullets.Length && i < numRounds; i++)
			{
				GameObject val = clip.DisplayBullets[i];
				if (!((Object)(object)val != (Object)null) || !val.activeInHierarchy)
				{
					continue;
				}
				componentsInChildren2 = val.GetComponentsInChildren<Collider>(true);
				foreach (Collider val2 in componentsInChildren2)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						hashSet.Add(val2);
						LogDebug($"Including bullet collider {((Object)val2).name} from active bullet {i}");
					}
				}
			}
			if (clip.DisplayBullets.Length > numRounds)
			{
				LogDebug($"Ignoring {clip.DisplayBullets.Length - numRounds} inactive bullet displays for clip {((Object)clip).name}");
			}
		}
		Collider val3 = null;
		float num = 0f;
		componentsInChildren2 = componentsInChildren;
		foreach (Collider val4 in componentsInChildren2)
		{
			if ((Object)(object)val4 != (Object)null && val4.isTrigger)
			{
				float num2 = 0f;
				if (val4 is BoxCollider)
				{
					BoxCollider val5 = (BoxCollider)(object)((val4 is BoxCollider) ? val4 : null);
					num2 = val5.size.x * val5.size.y * val5.size.z;
				}
				else if (val4 is SphereCollider)
				{
					SphereCollider val6 = (SphereCollider)(object)((val4 is SphereCollider) ? val4 : null);
					num2 = 4.1887903f * Mathf.Pow(val6.radius, 3f);
				}
				else if (val4 is CapsuleCollider)
				{
					CapsuleCollider val7 = (CapsuleCollider)(object)((val4 is CapsuleCollider) ? val4 : null);
					float num3 = val7.height - 2f * val7.radius;
					float num4 = (float)Math.PI * val7.radius * val7.radius * num3;
					float num5 = 4.1887903f * Mathf.Pow(val7.radius, 3f);
					num2 = num4 + num5;
				}
				Vector3 lossyScale = ((Component)val4).transform.lossyScale;
				num2 *= lossyScale.x * lossyScale.y * lossyScale.z;
				if (num2 > num)
				{
					num = num2;
					val3 = val4;
				}
			}
		}
		componentsInChildren2 = componentsInChildren;
		foreach (Collider val8 in componentsInChildren2)
		{
			if ((Object)(object)val8 == (Object)null)
			{
				continue;
			}
			bool flag = hashSet.Contains(val8);
			if (!flag)
			{
				if (FVRFireArmClipFixedUpdatePatch.temporaryBulletColliders.ContainsKey(clip) && (Object)(object)val8 == (Object)(object)FVRFireArmClipFixedUpdatePatch.temporaryBulletColliders[clip])
				{
					flag = true;
				}
				else if (FVRFireArmClipFixedUpdatePatch.temporaryBulletTriggers.ContainsKey(clip) && (Object)(object)val8 == (Object)(object)FVRFireArmClipFixedUpdatePatch.temporaryBulletTriggers[clip])
				{
					flag = true;
				}
			}
			bool flag2 = false;
			if ((Object)(object)clip.Interface != (Object)null && ((Component)val8).transform.IsChildOf(((Component)clip.Interface).transform))
			{
				flag2 = true;
			}
			bool flag3 = (Object)(object)val8 == (Object)(object)val3;
			if (!flag && !flag2 && !flag3)
			{
				StoreAndSetColliderLayer(val8, "NoCol", list);
			}
		}
		trackedClipColliders[clip] = list;
	}

	public static void RestoreClipCollidersFromDualWield(FVRFireArmClip clip)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return;
		}
		RemoveTemporaryBulletCollider(clip);
		if (!trackedClipColliders.ContainsKey(clip))
		{
			return;
		}
		List<Collider> list = trackedClipColliders[clip];
		int num = 0;
		foreach (Collider item in list)
		{
			if ((Object)(object)item != (Object)null && originalColliderLayers.ContainsKey(item))
			{
				int num2 = originalColliderLayers[item];
				((Component)item).gameObject.layer = num2;
				num++;
				LogDebug($"Restored collider: {((Object)item).name} on {((Object)((Component)item).gameObject).name} to layer {LayerMask.LayerToName(num2)}");
				originalColliderLayers.Remove(item);
			}
		}
		trackedClipColliders.Remove(clip);
		LogDebug($"Restored {num} colliders for {((Object)clip).name}");
	}

	public static void RegisterClipTriggers(FVRFireArmClip clip)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return;
		}
		Collider component = ((Component)clip).GetComponent<Collider>();
		if ((Object)(object)component != (Object)null && component.isTrigger)
		{
			validClipTriggers[component] = clip;
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)("Registered trigger collider " + ((Object)component).name + " for clip " + ((Object)clip).name));
			}
		}
		else if (configEnableDebugLogging.Value)
		{
			Logger.LogInfo((object)("WARNING: Could not find trigger collider directly on clip " + ((Object)clip).name));
		}
	}

	public static void UnregisterClipTriggers(FVRFireArmClip clip)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return;
		}
		List<Collider> list = new List<Collider>();
		foreach (KeyValuePair<Collider, FVRFireArmClip> validClipTrigger in validClipTriggers)
		{
			if ((Object)(object)validClipTrigger.Value == (Object)(object)clip)
			{
				list.Add(validClipTrigger.Key);
			}
		}
		foreach (Collider item in list)
		{
			validClipTriggers.Remove(item);
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)("Unregistered trigger collider " + ((Object)item).name + " for clip " + ((Object)clip).name));
			}
		}
	}

	public static void CheckForFirearmClipSlap(FVRFireArm firearm, Collider collider)
	{
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Invalid comparison between Unknown and I4
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0253: Unknown result type (might be due to invalid IL or missing references)
		if (!configAllowFirearmsToSlap.Value)
		{
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)"CheckForFirearmClipSlap: Firearms not allowed to slap");
			}
			return;
		}
		if ((Object)(object)firearm == (Object)null || !((FVRInteractiveObject)firearm).IsHeld)
		{
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)string.Format("CheckForFirearmClipSlap: Invalid firearm or not held - firearm: {0}, held: {1}", ((firearm != null) ? ((Object)firearm).name : null) ?? "null", firearm != null && ((FVRInteractiveObject)firearm).IsHeld));
			}
			return;
		}
		FVRFireArmClip val = FindClipFromCollider(collider);
		if ((Object)(object)val == (Object)null || IsClipInBulletPushOperation(val))
		{
			return;
		}
		if ((Object)(object)val.FireArm == (Object)(object)firearm)
		{
			_ = configEnableDebugLogging.Value;
			return;
		}
		if ((int)val.State != 1 || (Object)(object)val.FireArm == (Object)null)
		{
			if (colliderToClipCache.ContainsKey(collider))
			{
				colliderToClipCache.Remove(collider);
			}
			return;
		}
		bool flag = false;
		int num = 0;
		foreach (KeyValuePair<int, FVRFireArmClip> validClipID in validClipIDs)
		{
			if ((Object)(object)validClipID.Value == (Object)(object)val)
			{
				flag = true;
				num = validClipID.Key;
				break;
			}
		}
		if (!flag)
		{
			return;
		}
		if (configEnableDebugLogging.Value)
		{
			Logger.LogInfo((object)$"CheckForFirearmClipSlap: Target clip {((Object)val).name} has valid ID {num} for slapping");
		}
		Vector3 velLinearWorld = ((FVRInteractiveObject)firearm).m_hand.Input.VelLinearWorld;
		Vector3 val2 = (((Object)(object)((FVRPhysicalObject)firearm).RootRigidbody != (Object)null) ? ((FVRPhysicalObject)firearm).RootRigidbody.velocity : Vector3.zero);
		Vector3 val3 = ((Vector3.Magnitude(velLinearWorld) > Vector3.Magnitude(val2)) ? velLinearWorld : val2);
		float magnitude = ((Vector3)(ref val3)).magnitude;
		if (configEnableDebugLogging.Value && magnitude > 0.5f)
		{
			Logger.LogInfo((object)$"CheckForFirearmClipSlap: {((Object)firearm).name} velocity {magnitude}, threshold {configSlapThreshold.Value}");
		}
		if (magnitude < configSlapThreshold.Value)
		{
			if (configEnableDebugLogging.Value && magnitude > 0.5f)
			{
				Logger.LogInfo((object)"CheckForFirearmClipSlap: Velocity below threshold");
			}
			return;
		}
		if ((Object)(object)firearm != (Object)null)
		{
			TrackClipForInteraction(val, firearm);
		}
		if (!ValidateClipSlapConditions(val, firearm))
		{
			LogDebug($"CheckForFirearmClipSlap: Clip {((Object)val).name} failed validation (state: {val.State}, firearm match: {(Object)(object)val.FireArm == (Object)(object)firearm})");
			return;
		}
		LogDebug($"SUCCESS: Firearm slapping clip {((Object)val).name} with velocity: {magnitude}");
		ProcessSlap(val, magnitude, ((Vector3)(ref val3)).normalized);
	}

	public static void CheckForFirearmClipSlap(FVRFireArm firearm, Collision collision)
	{
		CheckForFirearmClipSlap(firearm, collision.collider);
	}

	public static void CheckForInteractiveObjectClipSlap(FVRInteractiveObject interactiveObject, Collider collider)
	{
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Invalid comparison between Unknown and I4
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0288: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		if (!configAllowInteractiveObjectsToSlap.Value)
		{
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)"CheckForInteractiveObjectClipSlap: Interactive objects not allowed to slap");
			}
		}
		else if ((Object)(object)interactiveObject == (Object)null || !interactiveObject.IsHeld)
		{
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)string.Format("CheckForInteractiveObjectClipSlap: Invalid object or not held - object: {0}, held: {1}", ((interactiveObject != null) ? ((Object)interactiveObject).name : null) ?? "null", interactiveObject != null && interactiveObject.IsHeld));
			}
		}
		else
		{
			if (interactiveObject is FVRFireArm)
			{
				return;
			}
			FVRFireArmClip val = FindClipFromCollider(collider);
			if ((Object)(object)val == (Object)null || IsClipInBulletPushOperation(val))
			{
				return;
			}
			if ((int)val.State != 1 || (Object)(object)val.FireArm == (Object)null)
			{
				if (colliderToClipCache.ContainsKey(collider))
				{
					colliderToClipCache.Remove(collider);
				}
				return;
			}
			bool flag = false;
			int num = 0;
			foreach (KeyValuePair<int, FVRFireArmClip> validClipID in validClipIDs)
			{
				if ((Object)(object)validClipID.Value == (Object)(object)val)
				{
					flag = true;
					num = validClipID.Key;
					break;
				}
			}
			if (!flag)
			{
				return;
			}
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)$"CheckForInteractiveObjectClipSlap: Target clip {((Object)val).name} has valid ID {num} for slapping");
			}
			Vector3 velLinearWorld = interactiveObject.m_hand.Input.VelLinearWorld;
			Vector3 val2 = Vector3.zero;
			Rigidbody component = ((Component)interactiveObject).GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null)
			{
				val2 = component.velocity;
			}
			Vector3 val3 = ((Vector3.Magnitude(velLinearWorld) > Vector3.Magnitude(val2)) ? velLinearWorld : val2);
			float magnitude = ((Vector3)(ref val3)).magnitude;
			if (configEnableDebugLogging.Value && magnitude > 0.5f)
			{
				Logger.LogInfo((object)$"CheckForInteractiveObjectClipSlap: {((Object)interactiveObject).name} velocity {magnitude}, threshold {configSlapThreshold.Value}");
			}
			if (magnitude < configSlapThreshold.Value)
			{
				if (configEnableDebugLogging.Value && magnitude > 0.5f)
				{
					Logger.LogInfo((object)"CheckForInteractiveObjectClipSlap: Velocity below threshold");
				}
				return;
			}
			if ((Object)(object)val.FireArm != (Object)null)
			{
				TrackClipForInteraction(val, val.FireArm);
			}
			if (!ValidateClipSlapConditions(val))
			{
				LogDebug($"CheckForInteractiveObjectClipSlap: Clip {((Object)val).name} failed validation (state: {val.State})");
				return;
			}
			LogDebug($"SUCCESS: Interactive object {((Object)interactiveObject).name} slapping clip {((Object)val).name} with velocity: {magnitude}");
			ProcessSlap(val, magnitude, ((Vector3)(ref val3)).normalized);
		}
	}

	public static void LogDebug(string message)
	{
		if (configEnableDebugLogging.Value)
		{
			Logger.LogInfo((object)message);
		}
	}

	private static FVRFireArmClip TryGetClipFromSingleCollider(Collider collider, bool requireLocked = false)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Invalid comparison between Unknown and I4
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Invalid comparison between Unknown and I4
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Invalid comparison between Unknown and I4
		if ((Object)(object)collider == (Object)null)
		{
			return null;
		}
		FVRFireArmClip component = ((Component)collider).GetComponent<FVRFireArmClip>();
		if ((Object)(object)component != (Object)null && (!requireLocked || (int)component.State == 1))
		{
			return component;
		}
		if ((Object)(object)collider.attachedRigidbody != (Object)null)
		{
			component = ((Component)collider.attachedRigidbody).GetComponent<FVRFireArmClip>();
			if ((Object)(object)component != (Object)null && (!requireLocked || (int)component.State == 1))
			{
				return component;
			}
		}
		FVRFireArmClipInterface component2 = ((Component)collider).GetComponent<FVRFireArmClipInterface>();
		if ((Object)(object)component2 != (Object)null && ((Behaviour)component2).isActiveAndEnabled)
		{
			component = component2.Clip;
			if ((Object)(object)component != (Object)null && (!requireLocked || (int)component.State == 1))
			{
				return component;
			}
		}
		return null;
	}

	private static bool ValidateClipSlapConditions(FVRFireArmClip clip, FVRFireArm excludeFirearm = null)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Invalid comparison between Unknown and I4
		if ((Object)(object)clip == (Object)null)
		{
			return false;
		}
		if ((int)clip.State != 1)
		{
			return false;
		}
		if ((Object)(object)excludeFirearm != (Object)null && (Object)(object)clip.FireArm == (Object)(object)excludeFirearm)
		{
			return false;
		}
		if (configRequireEmptyClip.Value && clip.m_numRounds > 0)
		{
			return false;
		}
		if (WasRecentlySlapped(clip))
		{
			return false;
		}
		return true;
	}

	private static void StoreAndSetColliderLayer(Collider collider, string newLayerName, List<Collider> trackingList)
	{
		if (!((Object)(object)collider == (Object)null))
		{
			if (!originalColliderLayers.ContainsKey(collider))
			{
				originalColliderLayers[collider] = ((Component)collider).gameObject.layer;
			}
			trackingList.Add(collider);
			((Component)collider).gameObject.layer = LayerMask.NameToLayer(newLayerName);
			LogDebug("Stored and set collider to " + newLayerName + ": " + ((Object)collider).name + " on " + ((Object)((Component)collider).gameObject).name + " (was: " + LayerMask.LayerToName(originalColliderLayers[collider]) + ")");
		}
	}

	private static bool TryPushRoundFromClipToMag(FVRFireArmClip clip, string actionSource)
	{
		if ((Object)(object)clip == (Object)null || !clip.HasARound())
		{
			return false;
		}
		if ((Object)(object)clip.FireArm == (Object)null || (Object)(object)clip.FireArm.Magazine == (Object)null)
		{
			return false;
		}
		if (clip.FireArm.Magazine.IsFull())
		{
			return false;
		}
		clip.LoadOneRoundFromClipToMag();
		LogDebug(actionSource + " pushed round from clip " + ((Object)clip).name);
		return true;
	}

	private static string GenerateClipPairKey(FVRFireArmClip clipA, FVRFireArmClip clipB)
	{
		int instanceID = ((Object)clipA).GetInstanceID();
		int instanceID2 = ((Object)clipB).GetInstanceID();
		stringBuilder.Length = 0;
		if (instanceID < instanceID2)
		{
			stringBuilder.Append(instanceID).Append('_').Append(instanceID2);
		}
		else
		{
			stringBuilder.Append(instanceID2).Append('_').Append(instanceID);
		}
		return stringBuilder.ToString();
	}

	private static BoxCollider CreateConfiguredBoxCollider(GameObject target, Bounds bounds, bool isTrigger, float sizeMultiplier = 1f)
	{
		//IL_0010: 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_0023: Unknown result type (might be due to invalid IL or missing references)
		BoxCollider obj = target.AddComponent<BoxCollider>();
		((Collider)obj).isTrigger = isTrigger;
		obj.size = ((Bounds)(ref bounds)).size * sizeMultiplier;
		obj.center = ((Bounds)(ref bounds)).center;
		return obj;
	}

	private static HandStates GetHandStates()
	{
		HandStates handStates = new HandStates();
		if ((Object)(object)GM.CurrentMovementManager != (Object)null && GM.CurrentMovementManager.Hands != null && GM.CurrentMovementManager.Hands.Length >= 2)
		{
			handStates.LeftHand = GM.CurrentMovementManager.Hands[0];
			handStates.RightHand = GM.CurrentMovementManager.Hands[1];
			handStates.LeftFirearm = (FVRFireArm)(((Object)(object)handStates.LeftHand != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			handStates.RightFirearm = (FVRFireArm)(((Object)(object)handStates.RightHand != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
		}
		return handStates;
	}

	private static bool TryInvokeMethod(object target, string methodName, object[] parameters = null)
	{
		if (target == null)
		{
			return false;
		}
		try
		{
			Type type = target.GetType();
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public);
			if ((object)method != null)
			{
				method.Invoke(target, parameters);
				LogDebug("Successfully invoked " + methodName + " on " + type.Name);
				return true;
			}
		}
		catch (Exception ex)
		{
			LogDebug("Error invoking " + methodName + ": " + ex.Message);
		}
		return false;
	}

	private static bool IsCacheEntryValid(FVRFireArmClip clip)
	{
		if ((Object)(object)clip != (Object)null)
		{
			return (Object)(object)((Component)clip).gameObject != (Object)null;
		}
		return false;
	}

	private static string GetClipPushFailureReason(FVRFireArmClip clip)
	{
		if (!clip.HasARound())
		{
			return "no rounds";
		}
		if ((Object)(object)clip.FireArm == (Object)null)
		{
			return "no firearm";
		}
		if ((Object)(object)clip.FireArm.Magazine == (Object)null)
		{
			return "no magazine";
		}
		if (clip.FireArm.Magazine.IsFull())
		{
			return "magazine full";
		}
		return "unknown";
	}

	private static GameObject FindTopActiveBulletDisplay(FVRFireArmClip clip)
	{
		if (clip?.DisplayBullets == null || clip.DisplayBullets.Length == 0)
		{
			return null;
		}
		for (int num = clip.DisplayBullets.Length - 1; num >= 0; num--)
		{
			if ((Object)(object)clip.DisplayBullets[num] != (Object)null && clip.DisplayBullets[num].activeInHierarchy)
			{
				return clip.DisplayBullets[num];
			}
		}
		return null;
	}

	private static ColliderPair FindExistingColliders(GameObject target)
	{
		ColliderPair colliderPair = new ColliderPair();
		BoxCollider[] components = target.GetComponents<BoxCollider>();
		foreach (BoxCollider val in components)
		{
			if ((Object)(object)val != (Object)null)
			{
				if (!((Collider)val).isTrigger && (Object)(object)colliderPair.SolidCollider == (Object)null)
				{
					colliderPair.SolidCollider = val;
				}
				else if (((Collider)val).isTrigger && (Object)(object)colliderPair.TriggerCollider == (Object)null)
				{
					colliderPair.TriggerCollider = val;
				}
			}
		}
		return colliderPair;
	}

	private static int SetGameObjectArrayToLayer(GameObject[] gameObjects, int layerID)
	{
		int num = 0;
		if (gameObjects == null)
		{
			return num;
		}
		foreach (GameObject val in gameObjects)
		{
			if (!((Object)(object)val != (Object)null))
			{
				continue;
			}
			BoxCollider[] components = val.GetComponents<BoxCollider>();
			foreach (BoxCollider val2 in components)
			{
				if ((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.layer != layerID)
				{
					((Component)val2).gameObject.layer = layerID;
					num++;
				}
			}
			val.layer = layerID;
		}
		return num;
	}

	public static bool IsFirearmValidForClipAutoLoading(FVRFireArm firearm)
	{
		if ((Object)(object)firearm != (Object)null && firearm.UsesClips && (Object)(object)firearm.Clip == (Object)null)
		{
			return (Object)(object)firearm.ClipMountPos != (Object)null;
		}
		return false;
	}

	public static bool IsClipValidForAutoLoading(FVRFireArmClip clip, FVRFireArm firearm)
	{
		if ((Object)(object)clip == (Object)null)
		{
			return false;
		}
		if (!IsClipCompatibleWithFirearm(clip, firearm))
		{
			return false;
		}
		if (WasRecentlySlapped(clip))
		{
			return false;
		}
		if (configRequireSpawnlockedQuickbelt.Value && !((FVRPhysicalObject)clip).m_isSpawnLock)
		{
			return false;
		}
		return true;
	}

	public static void CopyLoadedRounds(FVRFireArmClip sourceClip, FVRFireArmClip targetClip)
	{
		//IL_0069: 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)
		if (sourceClip?.LoadedRounds == null || targetClip?.LoadedRounds == null)
		{
			return;
		}
		int num = Mathf.Min(sourceClip.LoadedRounds.Length, targetClip.LoadedRounds.Length);
		for (int i = 0; i < num; i++)
		{
			if (sourceClip.LoadedRounds[i] != null && (Object)(object)sourceClip.LoadedRounds[i].LR_Mesh != (Object)null)
			{
				targetClip.LoadedRounds[i].LR_Class = sourceClip.LoadedRounds[i].LR_Class;
				targetClip.LoadedRounds[i].LR_Mesh = sourceClip.LoadedRounds[i].LR_Mesh;
				targetClip.LoadedRounds[i].LR_Material = sourceClip.LoadedRounds[i].LR_Material;
				targetClip.LoadedRounds[i].LR_ObjectWrapper = sourceClip.LoadedRounds[i].LR_ObjectWrapper;
			}
		}
	}

	public static FVRFireArmClip CreateSpawnlockedClipDuplicate(FVRFireArmClip originalClip)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)((FVRPhysicalObject)(originalClip?)).ObjectWrapper == (Object)null)
		{
			return null;
		}
		FVRFireArmClip component = Object.Instantiate<GameObject>(((AnvilAsset)((FVRPhysicalObject)originalClip).ObjectWrapper).GetGameObject(), ((Component)originalClip).transform.position, ((Component)originalClip).transform.rotation).GetComponent<FVRFireArmClip>();
		if ((Object)(object)component != (Object)null)
		{
			CopyLoadedRounds(originalClip, component);
			component.m_numRounds = originalClip.m_numRounds;
			component.UpdateBulletDisplay();
			LogDebug("Created duplicate of spawnlocked clip for loading");
		}
		return component;
	}

	public static bool OtherHandHasFirearm(FVRViveHand hand)
	{
		object obj;
		if (hand == null)
		{
			obj = null;
		}
		else
		{
			FVRViveHand otherHand = hand.OtherHand;
			obj = ((otherHand != null) ? otherHand.CurrentInteractable : null);
		}
		if ((Object)obj != (Object)null)
		{
			return hand.OtherHand.CurrentInteractable is FVRFireArm;
		}
		return false;
	}

	public static bool IsClipValidForBulletTrigger(FVRFireArmClip clip)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Invalid comparison between Unknown and I4
		if ((Object)(object)clip != (Object)null)
		{
			return (int)clip.State == 1;
		}
		return false;
	}

	public static FVRFireArm FindFirearmInHierarchy(Collider collider)
	{
		if (collider == null)
		{
			return null;
		}
		return ((Component)collider).GetComponentInParent<FVRFireArm>();
	}

	public static FVRInteractiveObject FindInteractiveObjectInHierarchy(Collider collider)
	{
		if (collider == null)
		{
			return null;
		}
		return ((Component)collider).GetComponentInParent<FVRInteractiveObject>();
	}

	public static bool IsFirearmValidForInteraction(FVRFireArm firearm, FVRFireArm excludeFirearm = null)
	{
		if ((Object)(object)firearm != (Object)null && (Object)(object)firearm != (Object)(object)excludeFirearm)
		{
			return ((FVRInteractiveObject)firearm).IsHeld;
		}
		return false;
	}

	public static bool IsInteractiveObjectValidForInteraction(FVRInteractiveObject interactiveObject)
	{
		if ((Object)(object)interactiveObject != (Object)null && interactiveObject.IsHeld)
		{
			return !(interactiveObject is FVRFireArm);
		}
		return false;
	}

	public static bool IsLayerMatch(GameObject obj, string expectedLayerName)
	{
		if ((Object)(object)obj != (Object)null)
		{
			return obj.layer == LayerMask.NameToLayer(expectedLayerName);
		}
		return false;
	}

	public static void CleanupTimedDictionary<T>(Dictionary<T, float> dictionary, float maxAge, List<T> keysToRemove)
	{
		keysToRemove.Clear();
		float time = Time.time;
		foreach (KeyValuePair<T, float> item in dictionary)
		{
			if (time - item.Value > maxAge)
			{
				keysToRemove.Add(item.Key);
			}
		}
		foreach (T item2 in keysToRemove)
		{
			dictionary.Remove(item2);
		}
	}

	public static void CleanupCooldownDictionary<T>(Dictionary<T, float> dictionary, List<T> keysToRemove)
	{
		keysToRemove.Clear();
		float deltaTime = Time.deltaTime;
		List<T> list = new List<T>();
		List<float> list2 = new List<float>();
		foreach (KeyValuePair<T, float> item in dictionary)
		{
			float num = item.Value - deltaTime;
			if (num <= 0f)
			{
				keysToRemove.Add(item.Key);
				continue;
			}
			list.Add(item.Key);
			list2.Add(num);
		}
		for (int i = 0; i < list.Count; i++)
		{
			dictionary[list[i]] = list2[i];
		}
		foreach (T item2 in keysToRemove)
		{
			dictionary.Remove(item2);
		}
	}

	public static void EnsureClipPhysicsIntegrity(FVRFireArmClip clip)
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)((clip != null) ? ((FVRPhysicalObject)clip).RootRigidbody : null) == (Object)null))
		{
			bool flag = false;
			if (!((FVRPhysicalObject)clip).RootRigidbody.useGravity)
			{
				((FVRPhysicalObject)clip).RootRigidbody.useGravity = true;
				flag = true;
				LogDebug("Fixed disabled gravity on clip " + ((Object)clip).name);
			}
			if (((FVRPhysicalObject)clip).RootRigidbody.isKinematic && !((FVRPhysicalObject)clip).IsKinematicLocked)
			{
				((FVRPhysicalObject)clip).RootRigidbody.isKinematic = false;
				flag = true;
				LogDebug("Fixed kinematic state on clip " + ((Object)clip).name);
			}
			if ((int)((FVRPhysicalObject)clip).RootRigidbody.constraints != 0)
			{
				((FVRPhysicalObject)clip).RootRigidbody.constraints = (RigidbodyConstraints)0;
				flag = true;
				LogDebug("Cleared position constraints on clip " + ((Object)clip).name);
			}
			if (flag && configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)("Fixed physics integrity issues on clip " + ((Object)clip).name));
			}
		}
	}

	public static bool ShouldProcessClipForDualWield(FVRFireArmClip clip)
	{
		if ((Object)(object)clip != (Object)null && (Object)(object)((Component)clip).gameObject != (Object)null)
		{
			return ((Component)clip).gameObject.activeInHierarchy;
		}
		return false;
	}

	public static bool ValidateFirearmClipForSlapping(FVRFireArm firearm)
	{
		if ((Object)(object)firearm == (Object)null)
		{
			return false;
		}
		if ((Object)(object)firearm.Clip == (Object)null)
		{
			if (configEnableDebugLogging.Value)
			{
				Logger.LogInfo((object)("Firearm slap validation failed: Firearm " + ((Object)firearm).name + " has no clip loaded"));
			}
			return false;
		}
		bool flag = false;
		int num = 0;
		foreach (KeyValuePair<int, FVRFireArmClip> validClipID in validClipIDs)
		{
			if ((Object)(object)validClipID.Value == (Object)(object)firearm.Clip)
			{
				flag = true;
				num = validClipID.Key;
				break;
			}
		}
		if (configEnableDebugLogging.Value)
		{
			if (flag)
			{
				Logger.LogInfo((object)$"Firearm slap validation passed: Firearm {((Object)firearm).name} has registered clip {((Object)firearm.Clip).name} with ID {num}");
			}
			else
			{
				Logger.LogInfo((object)("Firearm slap validation failed: Clip " + ((Object)firearm.Clip).name + " is not registered for slapping"));
			}
		}
		return flag;
	}
}
[HarmonyPatch(typeof(FVRFireArmClip), "Load")]
public class FVRFireArmClipLoadPatch
{
	public static bool Prefix(FVRFireArmClip __instance, FVRFireArm fireArm)
	{
		if (ClipSlap.WasRecentlySlapped(__instance))
		{
			if (ClipSlap.configEnableDebugLogging.Value)
			{
				ClipSlap.Logger.LogInfo((object)("Blocked clip " + ((Object)__instance).name + " reattachment - recently slapped"));
			}
			return false;
		}
		return true;
	}

	public static void Postfix(FVRFireArmClip __instance, FVRFireArm fireArm)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		if ((int)__instance.State == 1 && (Object)(object)__instance.FireArm != (Object)null)
		{
			int num = ClipSlap.RegisterClipForSlapping(__instance);
			ClipSlap.RegisterClipTriggers(__instance);
			if (ClipSlap.configEnableDebugLogging.Value)
			{
				ClipSlap.Logger.LogInfo((object)$"Auto-registered clip {((Object)__instance).name} with ID {num} upon loading into {((Object)fireArm).name}");
			}
			if (((FVRInteractiveObject)__instance.FireArm).IsHeld)
			{
				ClipSlap.TrackClipForInteraction(__instance, __instance.FireArm);
			}
			ClipSlap.CreateTemporaryBulletCollider(__instance);
			if (ClipSlap.configEnableDebugLogging.Value)
			{
				ClipSlap.Logger.LogInfo((object)$"Clip {((Object)__instance).name} loaded into {((Object)__instance.FireArm).name} (dual-wield: {ClipSlap.IsDualWielding()})");
			}
		}
	}
}
[HarmonyPatch(typeof(FVRFireArmClip), "Release")]
public class FVRFireArmClipReleasePatch
{
	public static void Prefix(FVRFireArmClip __instance)
	{
		ClipSlap.UnregisterClipForSlapping(__instance);
		ClipSlap.UnregisterClipTriggers(__instance);
		if (ClipSlap.configEnableDebugLogging.Value)
		{
			ClipSlap.Logger.LogInfo((object)("Auto-unregistered clip " + ((Object)__instance).name + " upon release from firearm"));
		}
		ClipSlap.RemoveTemporaryBulletCollider(__instance);
		ClipSlap.RestoreClipCollidersFromDualWield(__instance);
		ClipSlap.EnsureClipPhysicsIntegrity(__instance);
		ClipSlap.RemoveClipFromCache(__instance);
	}
}
[HarmonyPatch(typeof(FVRFireArmClip), "UpdateBulletDisplay")]
public class FVRFireArmClipUpdateBulletDisplayPatch
{
	public static void Postfix(FVRFireArmClip __instance)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Invalid comparison between Unknown and I4
		if ((int)__instance.State != 1 || (Object)(object)__instance.FireArm == (Object)null)
		{
			return;
		}
		if (ClipSlap.configEnableDebugLogging.Value)
		{
			ClipSlap.Logger.LogInfo((object)$"UpdateBulletDisplay patch triggered for {((Object)__instance).name}, rounds: {__instance.m_numRounds}");
		}
		ClipSlap.RemoveTemporaryBulletCollider(__instance);
		if (__instance.HasARound())
		{
			ClipSlap.CreateTemporaryBulletCollider(__instance);
			if (ClipSlap.configEnableDebugLogging.Value)
			{
				ClipSlap.Logger.LogInfo((object)("Created new bullet collider on top bullet for " + ((Object)__instance).name));
			}
		}
		else if (ClipSlap.configEnableDebugLogging.Value)
		{
			ClipSlap.Logger.LogInfo((object)("No bullets left in " + ((Object)__instance).name + ", no collider created"));
		}
	}
}
public class BulletTriggerDetector : MonoBehaviour
{
	public FVRFireArmClip parentClip;

	private Dictionary<Collider, float> _cooldowns;

	private const float CooldownTime = 0.1f;

	private void Awake()
	{
		_cooldowns = new Dictionary<Collider, float>();
	}

	public void OnTriggerEnter(Collider other)
	{
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Invalid comparison between Unknown and I4
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Invalid comparison between Unknown and I4
		if (_cooldowns.ContainsKey(other) && Time.time < _cooldowns[other])
		{
			return;
		}
		_cooldowns[other] = Time.time + 0.1f;
		if (ClipSlap.configEnableDebugLogging.Value)
		{
			ManualLogSource logger = ClipSlap.Logger;
			string[] obj = new string[6] { "BulletTriggerDetector on ", null, null, null, null, null };
			FVRFireArmClip obj2 = parentClip;
			obj[1] = ((obj2 != null) ? ((Object)obj2).name : null) ?? "null";
			obj[2] = ": OnTriggerEnter with ";
			obj[3] = ((Object)other).name;
			obj[4] = " on layer ";
			obj[5] = LayerMask.LayerToName(((Component)other).gameObject.layer);
			logger.LogInfo((object)string.Concat(obj));
		}
		if (!ClipSlap.IsClipValidForBulletTrigger(parentClip))
		{
			ClipSlap.LogDebug("BulletTriggerDetector: Skipping - parentClip null or not locked");
			return;
		}
		if (ClipSlap.IsLayerMatch(((Component)other).gameObject, "Default"))
		{
			FVRFireArm val = ClipSlap.FindFirearmInHierarchy(other);
			if (ClipSlap.IsFirearmValidForInteraction(val, parentClip.FireArm))
			{
				ClipSlap.LogDebug("BulletTriggerDetector: Detected firearm interaction with " + ((Object)val).name);
				ClipSlap.HandleBulletTriggerFirearmInteraction(parentClip, val, other);
			}
			else
			{
				FVRInteractiveObject val2 = ClipSlap.FindInteractiveObjectInHierarchy(other);
				if (ClipSlap.IsInteractiveObjectValidForInteraction(val2))
				{
					ClipSlap.LogDebug("BulletTriggerDetector: Detected interactive object interaction with " + ((Object)val2).name);
					ClipSlap.HandleBulletTriggerInteractiveObjectInteraction(parentClip, val2, other);
				}
			}
		}
		BulletTriggerDetector component = ((Component)other).GetComponent<BulletTriggerDetector>();
		if (ClipSlap.configEnableDebugLogging.Value)
		{
			ClipSlap.Logger.LogInfo((object)$"BulletTriggerDetector: Checking for other BulletTriggerDetector on {((Object)other).name} - found: {(Object)(object)component != (Object)null}");
			if ((Object)(object)component != (Object)null)
			{
				ManualLogSource logger2 = ClipSlap.Logger;
				FVRFireArmClip obj3 = component.parentClip;
				string arg = ((obj3 != null) ? ((Object)obj3).name : null) ?? "null";
				FVRFireArmClip obj4 = component.parentClip;
				logger2.LogInfo((object)$"BulletTriggerDetector: Other detector parent clip: {arg}, locked: {obj4 != null && (int)obj4.State == 1}");
				ClipSlap.Logger.LogInfo((object)$"BulletTriggerDetector: Same clip check - this: {ClipSlap.GetClipID(parentClip)}, other: {ClipSlap.GetClipID(component.parentClip)}");
			}
		}
		if ((Object)(object)component != (Object)null && (Object)(object)component.parentClip != (Object)null && (Object)(object)component.parentClip != (Object)(object)parentClip && (int)component.parentClip.State == 1 && ClipSlap.GetClipID(component.parentClip) != ClipSlap.GetClipID(parentClip))
		{
			if (ClipSlap.configEnableDebugLogging.Value)
			{
				ClipSlap.Logger.LogInfo((object)$"BulletTriggerDetector: Initiating clip-to-clip interaction between {((Object)parentClip).name} and {((Object)component.parentClip).name}");
			}
			ClipSlap.HandleBulletTriggerClipInteraction(parentClip, component.parentClip);
		}
		else if (ClipSlap.configEnableDebugLogging.Value && (Object)(object)component != (Object)null)
		{
			ClipSlap.Logger.LogInfo((object)"BulletTriggerDetector: Skipping interaction - same clip or invalid state");
		}
	}

	private void Update()
	{
		if (_cooldowns.Count <= 0)
		{
			return;
		}
		List<Collider> list = new List<Collider>();
		foreach (KeyValuePair<Collider, float> cooldown in _cooldowns)
		{
			if (Time.time > cooldown.Value)
			{
				list.Add(cooldown.Key);
			}
		}
		foreach (Collider item in list)
		{
			_cooldowns.Remove(item);
		}
	}
}
[HarmonyPatch(typeof(FVRViveHand), "TestQuickBeltDistances")]
public class FVRViveHandQuickBeltPatch
{
	public static void Postfix(FVRViveHand __instance)
	{
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		if (!ClipSlap.configAutoLoadClipsFromQuickbelt.Value || (Object)(object)__instance.CurrentInteractable == (Object)null || !(__instance.CurrentInteractable is FVRFireArm))
		{
			return;
		}
		FVRInteractiveObject currentInteractable = __instance.CurrentInteractable;
		FVRFireArm val = (FVRFireArm)(object)((currentInteractable is FVRFireArm) ? currentInteractable : null);
		if ((Object)(object)val == (Object)null || !val.UsesClips || (Object)(object)val.Clip != (Object)null || (Object)(object)val.ClipMountPos == (Object)null)
		{
			return;
		}
		if (!(val is Handgun))
		{
			if (ClipSlap.configEnableDebugLogging.Value)
			{
				ClipSlap.Logger.LogInfo((object)("Quickbelt auto-loading blocked: " + ((Object)val).name + " is not a Handgun (type: " + ((object)val).GetType().Name + ")"));
			}
			return;
		}
		FVRViveHand otherHand = __instance.OtherHand;
		bool flag = (Object)(object)((otherHand != null) ? otherHand.CurrentInteractable : null) != (Object)null && __instance.OtherHand.CurrentInteractable is FVRFireArm;
		if ((!ClipSlap.configAllowLoadingWithOneFirearm.Value && !flag) || GM.CurrentPlayerBody?.QBSlots_Internal == null)
		{
			return;
		}
		Vector3 position = val.ClipMountPos.position;
		FVRQuickBeltSlot val2 = null;
		foreach (FVRQuickBeltSlot item in GM.CurrentPlayerBody.QBSlots_Internal)
		{
			if ((Object)(object)item != (Object)null && ((Component)item).gameObject.activeInHierarchy && (Object)(object)item.CurObject != (Object)null && item.IsPointInsideMe(position))
			{
				val2 = item;
				break;
			}
		}
		if ((Object)(object)val2 == (Object)null)
		{
			return;
		}
		FVRPhysicalObject curObject = val2.CurObject;
		FVRFireArmClip val3 = (FVRFireArmClip)(object)((curObject is FVRFireArmClip) ? curObject : null);
		if ((Object)(object)val3 == (Object)null || !ClipSlap.IsClipCompatibleWithFirearm(val3, val) || ClipSlap.WasRecentlySlapped(val3) || (ClipSlap.configRequireSpawnlockedQuickbelt.Value && !((FVRPhysicalObject)val3).m_isSpawnLock))
		{
			return;
		}
		if (ClipSlap.configEnableDebugLogging.Value)
		{
			ClipSlap.Logger.LogInfo((object)("Auto-loading clip " + ((Object)val3).name + " from hovered quickbelt slot into firearm " + ((Object)val).name));
		}
		FVRFireArmClip val4;
		if (((FVRPhysicalObject)val3).m_isSpawnLock)
		{
			val4 = ClipSlap.CreateSpawnlockedClipDuplicate(val3);
			if ((Object)(object)val4 == (Object)null)
			{
				return;
			}
		}
		else
		{
			val4 = val3;
			((FVRPhysicalObject)val3).ClearQuickbeltState();
			ClipSlap.LogDebug("Using original clip from quickbelt slot");
		}
		val4.Load(val);
	}
}
[HarmonyPatch(typeof(FVRFireArmClip), "FVRFixedUpdate")]
public class FVRFireArmClipFixedUpdatePatch
{
	public static Dictionary<FVRFireArmClip, BoxCollider> temporaryBulletColliders = new Dictionary<FVRFireArmClip, BoxCollider>();

	public static Dictionary<FVRFireArmClip, BoxCollider> temporaryBulletTriggers = new Dictionary<FVRFireArmClip, BoxCollider>();

	public static Dictionary<string, float> processedClipPairsThisFrame = new Dictionary<string, float>();

	public static Dictionary<string, float> clipPairCooldowns = new Dictionary<string, float>();

	private static float lastFixedUpdateTime = -1f;

	public static void Postfix(FVRFireArmClip __instance)
	{
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Invalid comparison between Unknown and I4
		if (processedClipPairsThisFrame.Count > 0)
		{
			List<string> keysToRemove = new List<string>();
			ClipSlap.CleanupTimedDictionary(processedClipPairsThisFrame, 1f, keysToRemove);
		}
		if (Time.fixedTime != lastFixedUpdateTime)
		{
			processedClipPairsThisFrame.Clear();
			lastFixedUpdateTime = Time.fixedTime;
		}
		if (clipPairCooldowns.Count > 0)
		{
			List<string> keysToRemove2 = new List<string>();
			ClipSlap.CleanupCooldownDictionary(clipPairCooldowns, keysToRemove2);
		}
		if ((ClipSlap.configFirearmsCanPushDownClipRounds.Value || ClipSlap.configClipsCanPressOtherClips.Value) && (int)__instance.State == 1)
		{
			_ = (Object)(object)__instance.FireArm == (Object)null;
		}
	}
}
[HarmonyPatch(typeof(FVRFireArm), "FVRFixedUpdate")]
public class FVRFireArmDualWieldPatch
{
	public static void Postfix(FVRFireArm __instance)
	{
		ClipSlap.UpdateDualWieldState(ClipSlap.BothHandsHaveFirearms() || ClipSlap.HandsHaveMixedInteractables());
	}
}
[HarmonyPatch(typeof(FVRFireArm), "BeginInteraction")]
public class FVRFireArmBeginInteractionDualWieldPatch
{
	public static void Postfix(FVRFireArm __instance, FVRViveHand hand)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Invalid comparison between Unknown and I4
		if ((Object)(object)__instance.Clip != (Object)null && (int)__instance.Clip.State == 1)
		{
			ClipSlap.TrackClipForInteraction(__instance.Clip, __instance);
		}
		ClipSlap.BothHandsHaveFirearms();
	}
}
[HarmonyPatch(typeof(FVRFireArm), "EndInteraction")]
public class FVRFireArmEndInteractionDualWieldPatch
{
	public static void Postfix(FVRFireArm __instance, FVRViveHand hand)
	{
		if ((Object)(object)__instance.Clip != (Object)null)
		{
			ClipSlap.UntrackClipFromInteraction(__instance.Clip, __instance);
		}
		ClipSlap.BothHandsHaveFirearms();
	}
}
[HarmonyPatch(typeof(FVRFireArm), "EndInteractionIntoInventorySlot")]
public class FVRFireArmEndInteractionIntoInventorySlotDualWieldPatch
{
	public static void Postfix(FVRFireArm __instance, FVRViveHand hand, FVRQuickBeltSlot slot)
	{
		if ((Object)(object)__instance.Clip != (Object)null)
		{
			ClipSlap.UntrackClipFromInteraction(__instance.Clip, __instance);
		}
		ClipSlap.BothHandsHaveFirearms();
	}
}
[HarmonyPatch(typeof(FVRFireArm), "Awake")]
public class FVRFireArmAwakeClipSlapPatch
{
	public static void Postfix(FVRFireArm __instance)
	{
		if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<ClipSlap.FirearmClipSlapDetector>()))
		{
			((Component)__instance).gameObject.AddComponent<ClipSlap.FirearmClipSlapDetector>();
			if (ClipSlap.configEnableDebugLogging.Value)
			{
				ClipSlap.Logger.LogInfo((object)$"Added FirearmClipSlapDetector to {((Object)__instance).name}");
			}
		}
	}
}
[HarmonyPatch(typeof(FVRInteractiveObject), "Awake")]
public class FVRInteractiveObjectAwakeClipSlapPatch
{
	public static void Postfix(FVRInteractiveObject __instance)
	{
		if (!(__instance is FVRFireArm) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<ClipSlap.InteractiveObjectClipSlapDetector>()))
		{
			((Component)__instance).gameObject.AddComponent<ClipSlap.InteractiveObjectClipSlapDetector>();
			if (ClipSlap.configEnableDebugLogging.Value)
			{
				ClipSlap.Logger.LogInfo((object)$"Added InteractiveObjectClipSlapDetector to {((Object)__instance).name}");
			}
		}
	}
}
[HarmonyPatch(typeof(FVRInteractiveObject), "BeginInteraction")]
public class FVRInteractiveObjectBeginInteractionDualWieldPatch
{
	public static void Postfix(FVRInteractiveObject __instance, FVRViveHand hand)
	{
		ClipSlap.UpdateDualWieldState(ClipSlap.BothHandsHaveFirearms() || ClipSlap.HandsHaveMixedInteractables());
	}
}
[HarmonyPatch(typeof(FVRInteractiveObject), "EndInteraction")]
public class FVRInteractiveObjectEndInteractionDualWieldPatch
{
	public static void Postfix(FVRInteractiveObject __instance, FVRViveHand hand)
	{
		ClipSlap.UpdateDualWieldState(ClipSlap.BothHandsHaveFirearms() || ClipSlap.HandsHaveMixedInteractables());
	}
}
[HarmonyPatch(typeof(FVRViveHand), "OnTriggerEnter")]
public class FVRViveHandTriggerEnterPatch
{
	public static void Postfix(FVRViveHand __instance, Collider collider)
	{
		if (!IsControllerObject(collider))
		{
			ClipSlap.CheckForClipSlap(__instance, collider);
		}
	}

	private static bool IsControllerObject(Collider collider)
	{
		if ((Object)(object)collider == (Object)null)
		{
			return false;
		}
		string name = ((Object)collider).name;
		if (!name.Contains("Controller") && !name.Equals("Controller (right)") && !name.Equals("Controller (left)") && !name.Contains("Hand"))
		{
			return name.Contains("Tracker");
		}
		return true;
	}
}