Decompiled source of QuickGunFx v2.4.5

Mods/QuickGunFX.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BoneLib;
using BoneLib.BoneMenu;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.AI;
using Il2CppSLZ.Marrow.Data;
using Il2CppSLZ.Marrow.Pool;
using Il2CppSLZ.Marrow.Warehouse;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using QuickGunFX;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(GunFXMod), "QuickGunFX", "2.4.4", "nontendo", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("QuickGunFX")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("QuickGunFX")]
[assembly: AssemblyTitle("QuickGunFX")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace QuickGunFX
{
	public static class AirRack
	{
		public static BarcodeSet Guns = null;

		private static readonly Dictionary<int, float> _cooldown = new Dictionary<int, float>();

		private static readonly Dictionary<int, Vector3> _lastPos = new Dictionary<int, Vector3>();

		private static readonly Dictionary<int, bool> _armed = new Dictionary<int, bool>();

		private static readonly Dictionary<int, bool> _wasBack = new Dictionary<int, bool>();

		private static float _logTimer;

		public static void Update()
		{
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Invalid comparison between Unknown and I4
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Invalid comparison between Unknown and I4
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Invalid comparison between Unknown and I4
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			if (!GunFXSettings.Enabled || !GunFXSettings.AirRackEnabled)
			{
				return;
			}
			RigManager rigManager = Player.RigManager;
			PhysicsRig val = ((rigManager != null) ? rigManager.physicsRig : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			float time = Time.time;
			float deltaTime = Time.deltaTime;
			bool flag = GunFXSettings.DebugLog && (_logTimer -= deltaTime) <= 0f;
			if (flag)
			{
				_logTimer = 0.5f;
			}
			Hand[] array = (Hand[])(object)new Hand[2] { val.rightHand, val.leftHand };
			foreach (Hand val2 in array)
			{
				GameObject val3 = (((Object)(object)val2 != (Object)null) ? val2.m_CurrentAttachedGO : null);
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				Gun componentInParent = val3.GetComponentInParent<Gun>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					continue;
				}
				int instanceID = ((Object)componentInParent).GetInstanceID();
				Vector3 position = ((Component)componentInParent).transform.position;
				Vector3 val4 = Vector3.zero;
				if (_lastPos.TryGetValue(instanceID, out var value) && deltaTime > 0f)
				{
					val4 = (position - value) / deltaTime;
				}
				_lastPos[instanceID] = position;
				SlideStates slideState = componentInParent.slideState;
				bool flag2 = (int)slideState == 4 || (int)slideState == 3 || (int)slideState == 2;
				if (flag)
				{
					MelonLogger.Msg($"[QuickGunFX] airrack watch: slide={slideState} down={0f - val4.y:0.0} speed={((Vector3)(ref val4)).magnitude:0.0} charged={componentInParent.isCharged}");
				}
				if (!GunFXSettings.AirRackAllGuns)
				{
					string text = CartridgeTrails.BarcodeOf(componentInParent);
					if (text == null || !Guns.Contains(text))
					{
						continue;
					}
				}
				bool value2;
				bool flag3 = _wasBack.TryGetValue(instanceID, out value2) && value2;
				_wasBack[instanceID] = flag2;
				if (flag2 && !flag3)
				{
					_armed[instanceID] = true;
				}
				if (!flag2 || !(_armed.TryGetValue(instanceID, out var value3) && value3))
				{
					continue;
				}
				int key = instanceID;
				if ((_cooldown.TryGetValue(key, out var value4) && time < value4) || val4.y > 0f - GunFXSettings.AirRackSwing)
				{
					continue;
				}
				try
				{
					if (GunFXSettings.AirRackUseCharge)
					{
						componentInParent.Charge();
					}
					else
					{
						componentInParent.SlideRelease();
					}
					componentInParent.CompleteSlideReturn();
					componentInParent.SetAnimationState((AnimationStates)4, 1f);
				}
				catch (Exception ex)
				{
					if (GunFXSettings.DebugLog)
					{
						MelonLogger.Warning("[QuickGunFX] air rack: " + ex.Message);
					}
				}
				_cooldown[key] = time + 0.5f;
				_armed[key] = false;
				if (GunFXSettings.DebugLog)
				{
					MelonLogger.Msg($"[QuickGunFX] AIR RACKED via {(GunFXSettings.AirRackUseCharge ? "Charge()" : "SlideRelease()")} (down {0f - val4.y:0.0} m/s)");
				}
			}
		}
	}
	public class BarcodeSet
	{
		private readonly MelonPreferences_Category _cat;

		private readonly MelonPreferences_Entry<string> _data;

		private readonly HashSet<string> _set = new HashSet<string>();

		public int Count => _set.Count;

		public BarcodeSet(string category)
		{
			_cat = MelonPreferences.CreateCategory(category);
			_data = _cat.CreateEntry<string>("Guns", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			string[] array = _data.Value.Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string item in array)
			{
				_set.Add(item);
			}
		}

		public void Reload()
		{
			_set.Clear();
			string[] array = _data.Value.Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string item in array)
			{
				_set.Add(item);
			}
		}

		public bool Contains(string barcode)
		{
			if (!string.IsNullOrEmpty(barcode))
			{
				return _set.Contains(barcode);
			}
			return false;
		}

		public bool Add(string barcode)
		{
			if (string.IsNullOrEmpty(barcode) || !_set.Add(barcode))
			{
				return false;
			}
			Save();
			return true;
		}

		public bool Remove(string barcode)
		{
			if (!_set.Remove(barcode))
			{
				return false;
			}
			Save();
			return true;
		}

		public void Clear()
		{
			_set.Clear();
			Save();
		}

		private void Save()
		{
			_data.Value = string.Join("|", _set);
			_cat.SaveToFile(false);
		}
	}
	[HarmonyPatch(typeof(Gun), "EjectCartridge")]
	public static class Gun_EjectCartridge_Patch
	{
		public static void Prefix(Gun __instance)
		{
			try
			{
				if (GunFXSettings.CasingTrailEnabled)
				{
					string text = CartridgeTrails.BarcodeOf(__instance);
					if (text != null && SavedGuns.Contains(text))
					{
						CartridgeTrails.OnEject(__instance, text);
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[QuickGunFX] eject patch: " + ex.Message);
			}
		}
	}
	public static class CartridgeTrails
	{
		private struct Pending
		{
			public Transform port;

			public Transform gunRoot;

			public string barcode;

			public float expire;
		}

		private class Trail
		{
			public GameObject go;

			public TrailRenderer tr;

			public Transform? casing;

			public int casingId;

			public string barcode = "";

			public Vector3 lastPos;

			public bool detached;

			public float dieTime;

			public bool fading;

			public float fadeStart;

			public float fadeDur;

			public float bright = 1f;
		}

		private static readonly List<Pending> _pending = new List<Pending>();

		private const float SearchRadius = 0.4f;

		private const float MinEjectSpeed = 2f;

		private const int MaxTrails = 40;

		private static readonly List<Trail> _trails = new List<Trail>();

		private static readonly HashSet<int> _trailed = new HashSet<int>();

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

		private const float FadeMin = 0.4f;

		private static Material? _mat;

		private static Texture2D? _tex;

		private static readonly List<FirearmCartridge> _cand = new List<FirearmCartridge>();

		private static readonly List<Vector3> _candPos = new List<Vector3>();

		public static void NotifyFired(Gun gun)
		{
			try
			{
				int instanceID = ((Object)gun).GetInstanceID();
				int value;
				int num = (_pendingSpent.TryGetValue(instanceID, out value) ? value : 0);
				_pendingSpent[instanceID] = Mathf.Min(num + 1, 12);
			}
			catch
			{
			}
		}

		public static void OnEject(Gun gun, string barcode)
		{
			try
			{
				int instanceID = ((Object)gun).GetInstanceID();
				int value;
				int num = (_pendingSpent.TryGetValue(instanceID, out value) ? value : 0);
				if (num <= 0)
				{
					if (GunFXSettings.DebugLog)
					{
						MelonLogger.Msg("[QuickGunFX] eject with no spent case owed -> no trail (live round)");
					}
					return;
				}
				_pendingSpent[instanceID] = num - 1;
				Transform val = gun.shellSpawnTransform;
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)gun).transform;
				}
				Poolee componentInParent = ((Component)gun).GetComponentInParent<Poolee>();
				Transform gunRoot = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).transform : ((Component)gun).transform);
				_pending.Add(new Pending
				{
					port = val,
					gunRoot = gunRoot,
					barcode = barcode,
					expire = Time.time + 0.6f
				});
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[QuickGunFX] casing eject hook failed: " + ex.Message);
			}
		}

		public static void Update()
		{
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//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_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			_cand.Clear();
			_candPos.Clear();
			Vector3 val;
			if (_pending.Count > 0)
			{
				foreach (FirearmCartridge item in Object.FindObjectsOfType<FirearmCartridge>())
				{
					if ((Object)(object)item == (Object)null || _trailed.Contains(((Object)item).GetInstanceID()))
					{
						continue;
					}
					Rigidbody componentInParent = ((Component)item).GetComponentInParent<Rigidbody>();
					if (!((Object)(object)componentInParent == (Object)null) && !componentInParent.isKinematic)
					{
						val = componentInParent.velocity;
						if (!(((Vector3)(ref val)).magnitude < 2f))
						{
							_cand.Add(item);
							_candPos.Add(((Component)item).transform.position);
						}
					}
				}
			}
			for (int num = _pending.Count - 1; num >= 0; num--)
			{
				Pending pending = _pending[num];
				bool flag = false;
				if ((Object)(object)pending.port != (Object)null && _cand.Count > 0)
				{
					FirearmCartridge val2 = null;
					float num2 = float.MaxValue;
					Vector3 position = pending.port.position;
					for (int i = 0; i < _cand.Count; i++)
					{
						FirearmCartridge val3 = _cand[i];
						if (!((Object)(object)val3 == (Object)null))
						{
							val = _candPos[i] - position;
							float magnitude = ((Vector3)(ref val)).magnitude;
							if (!(magnitude > 0.4f) && !(magnitude >= num2) && !_trailed.Contains(((Object)val3).GetInstanceID()) && !IsAttachedToGun(val3, pending.gunRoot))
							{
								num2 = magnitude;
								val2 = val3;
							}
						}
					}
					if ((Object)(object)val2 != (Object)null)
					{
						StartTrail(((Component)val2).transform, ((Object)val2).GetInstanceID(), pending.barcode);
						flag = true;
						if (GunFXSettings.DebugLog)
						{
							MelonLogger.Msg($"[QuickGunFX] casing trail started ({num2:0.00}m from port)");
						}
					}
				}
				if (flag || time >= pending.expire)
				{
					if (!flag && GunFXSettings.DebugLog)
					{
						MelonLogger.Msg("[QuickGunFX] casing: no new casing found in window");
					}
					_pending.RemoveAt(num);
				}
			}
			for (int num3 = _trails.Count - 1; num3 >= 0; num3--)
			{
				Trail trail = _trails[num3];
				if (!trail.detached)
				{
					bool flag2 = (Object)(object)trail.casing != (Object)null && ((Component)trail.casing).gameObject.activeInHierarchy;
					if (flag2 && Vector3.Distance(trail.casing.position, trail.lastPos) > 1f)
					{
						Detach(trail, time);
					}
					else if (flag2)
					{
						trail.go.transform.position = trail.casing.TransformPoint(SavedGuns.GetOffset(trail.barcode));
						trail.lastPos = trail.casing.position;
						if (time >= trail.dieTime)
						{
							Detach(trail, time);
						}
					}
					else
					{
						Detach(trail, time);
					}
				}
				if (trail.detached)
				{
					float num4 = ((trail.fadeDur <= 0f) ? 1f : Mathf.Clamp01((time - trail.fadeStart) / trail.fadeDur));
					SetTrailAlpha(trail.tr, 1f - num4, trail.bright);
					if (num4 >= 1f)
					{
						try
						{
							Object.Destroy((Object)(object)trail.go);
						}
						catch
						{
						}
						_trailed.Remove(trail.casingId);
						_trails.RemoveAt(num3);
					}
				}
			}
		}

		private static void Detach(Trail t, float now)
		{
			if (!t.detached)
			{
				t.detached = true;
				t.tr.emitting = false;
				_trailed.Remove(t.casingId);
				t.fadeStart = now;
				t.fadeDur = Mathf.Max(0.4f, t.tr.time);
			}
		}

		private static void SetTrailAlpha(TrailRenderer tr, float mult, float bright)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			float num = GunFXSettings.Gray * bright;
			Gradient val = new Gradient();
			Il2CppStructArray<GradientColorKey> val2 = new Il2CppStructArray<GradientColorKey>(2L);
			((Il2CppArrayBase<GradientColorKey>)(object)val2)[0] = new GradientColorKey(new Color(num, num, num), 0f);
			((Il2CppArrayBase<GradientColorKey>)(object)val2)[1] = new GradientColorKey(new Color(num, num, num), 1f);
			Il2CppStructArray<GradientAlphaKey> val3 = new Il2CppStructArray<GradientAlphaKey>(3L);
			((Il2CppArrayBase<GradientAlphaKey>)(object)val3)[0] = new GradientAlphaKey(0.55f * mult, 0f);
			((Il2CppArrayBase<GradientAlphaKey>)(object)val3)[1] = new GradientAlphaKey(0.4f * mult, 0.5f);
			((Il2CppArrayBase<GradientAlphaKey>)(object)val3)[2] = new GradientAlphaKey(0f, 1f);
			val.SetKeys(val2, val3);
			tr.colorGradient = val;
		}

		private static bool IsAttachedToGun(FirearmCartridge fc, Transform gunRoot)
		{
			try
			{
				return (Object)(object)gunRoot != (Object)null && ((Component)fc).transform.IsChildOf(gunRoot);
			}
			catch
			{
				return false;
			}
		}

		private static void StartTrail(Transform casing, int casingId, string barcode)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0018: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("QF_CasingTrail");
			Object.DontDestroyOnLoad((Object)(object)val);
			val.transform.position = casing.position;
			TrailRenderer val2 = val.AddComponent<TrailRenderer>();
			((Renderer)val2).material = TrailMaterial();
			float num = (val2.startWidth = Mathf.Max(0.002f, GunFXSettings.CasingTrailWidth));
			val2.endWidth = num * 0.2f;
			val2.time = Mathf.Max(0.2f, GunFXSettings.CasingTrailLife);
			val2.numCapVertices = 2;
			val2.numCornerVertices = 2;
			val2.minVertexDistance = 0.004f;
			val2.alignment = (LineAlignment)0;
			((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)val2).receiveShadows = false;
			float bright = 1f;
			try
			{
				bright = GunFX.LightMul(casing.position);
			}
			catch
			{
			}
			SetTrailAlpha(val2, 1f, bright);
			if (_trails.Count >= 40)
			{
				Trail trail = _trails[0];
				try
				{
					Object.Destroy((Object)(object)trail.go);
				}
				catch
				{
				}
				_trailed.Remove(trail.casingId);
				_trails.RemoveAt(0);
			}
			_trails.Add(new Trail
			{
				go = val,
				tr = val2,
				casing = casing,
				casingId = casingId,
				barcode = barcode,
				lastPos = casing.position,
				dieTime = Time.time + val2.time + 2.5f,
				bright = bright
			});
			_trailed.Add(casingId);
		}

		private static Material TrailMaterial()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if ((Object)(object)_mat != (Object)null)
			{
				return _mat;
			}
			_mat = new Material(Shader.Find("Sprites/Default"));
			_mat.mainTexture = (Texture)(object)SmokeTexture();
			return _mat;
		}

		private static Texture2D SmokeTexture()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_tex != (Object)null)
			{
				return _tex;
			}
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1
			};
			float num = 31.5f;
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num2 = (float)j - num;
					float num3 = (float)i - num;
					float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3) / 32f;
					float num5 = Mathf.Clamp01(1f - num4);
					num5 *= num5;
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num5));
				}
			}
			val.Apply();
			_tex = val;
			return val;
		}

		public static void ClearAll()
		{
			foreach (Trail trail in _trails)
			{
				try
				{
					Object.Destroy((Object)(object)trail.go);
				}
				catch
				{
				}
			}
			_trails.Clear();
			_pending.Clear();
			_trailed.Clear();
			_pendingSpent.Clear();
		}

		public static string? BarcodeOf(Gun gun)
		{
			try
			{
				Poolee componentInParent = ((Component)gun).GetComponentInParent<Poolee>();
				SpawnableCrate obj = (((Object)(object)componentInParent != (Object)null) ? componentInParent.SpawnableCrate : null);
				object result;
				if (obj == null)
				{
					result = null;
				}
				else
				{
					Barcode barcode = ((Scannable)obj).Barcode;
					result = ((barcode != null) ? barcode.ID : null);
				}
				return (string?)result;
			}
			catch
			{
				return null;
			}
		}

		public static bool TryGetHeldGun(out string barcode, out string title)
		{
			barcode = "";
			title = "";
			try
			{
				RigManager rigManager = Player.RigManager;
				PhysicsRig val = ((rigManager != null) ? rigManager.physicsRig : null);
				if ((Object)(object)val == (Object)null)
				{
					return false;
				}
				Hand[] array = (Hand[])(object)new Hand[2] { val.rightHand, val.leftHand };
				foreach (Hand val2 in array)
				{
					GameObject val3 = (((Object)(object)val2 != (Object)null) ? val2.m_CurrentAttachedGO : null);
					if ((Object)(object)val3 == (Object)null)
					{
						continue;
					}
					Gun componentInParent = val3.GetComponentInParent<Gun>();
					if ((Object)(object)componentInParent == (Object)null)
					{
						continue;
					}
					Poolee componentInParent2 = ((Component)componentInParent).GetComponentInParent<Poolee>();
					SpawnableCrate val4 = (((Object)(object)componentInParent2 != (Object)null) ? componentInParent2.SpawnableCrate : null);
					if (!((Object)(object)val4 == (Object)null))
					{
						Barcode barcode2 = ((Scannable)val4).Barcode;
						barcode = ((barcode2 != null) ? barcode2.ID : null) ?? "";
						title = ((Scannable)val4).Title ?? "gun";
						if (!string.IsNullOrEmpty(barcode))
						{
							return true;
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}
	}
	public static class ChamberOffsets
	{
		private static MelonPreferences_Category _cat = null;

		private static MelonPreferences_Entry<string> _data = null;

		private static readonly Dictionary<string, Vector2> _map = new Dictionary<string, Vector2>();

		public static void Initialize()
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			_cat = MelonPreferences.CreateCategory("QuickGunFXChamberOffsets");
			_data = _cat.CreateEntry<string>("Offsets", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_map.Clear();
			string[] array = _data.Value.Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries);
			foreach (string text in array)
			{
				int num = text.IndexOf('=');
				if (num >= 0)
				{
					string text2 = text.Substring(0, num);
					string[] array2 = text.Substring(num + 1).Split(',');
					if (!string.IsNullOrEmpty(text2) && array2.Length == 2)
					{
						_map[text2] = new Vector2(P(array2[0]), P(array2[1]));
					}
				}
			}
		}

		public static Vector2 Get(string barcode)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(barcode) || !_map.TryGetValue(barcode, out var value))
			{
				return Vector2.zero;
			}
			return value;
		}

		public static void Set(string barcode, Vector2 v)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrEmpty(barcode))
			{
				_map[barcode] = v;
				Save();
			}
		}

		private static float P(string s)
		{
			if (!float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return 0f;
			}
			return result;
		}

		private static void Save()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, Vector2> item in _map)
			{
				list.Add(item.Key + "=" + item.Value.x.ToString(CultureInfo.InvariantCulture) + "," + item.Value.y.ToString(CultureInfo.InvariantCulture));
			}
			_data.Value = string.Join("|", list);
			_cat.SaveToFile(false);
		}
	}
	public static class Exclusions
	{
		public static readonly string[] Sections = new string[6] { "chamber", "muzzle", "impact", "recoil", "tracer", "concussion" };

		private static MelonPreferences_Category _cat = null;

		private static readonly Dictionary<string, MelonPreferences_Entry<string>> _entries = new Dictionary<string, MelonPreferences_Entry<string>>();

		private static readonly Dictionary<string, HashSet<string>> _sets = new Dictionary<string, HashSet<string>>();

		public static void Initialize()
		{
			_cat = MelonPreferences.CreateCategory("QuickGunFXExclusions");
			string[] sections = Sections;
			foreach (string text in sections)
			{
				MelonPreferences_Entry<string> val = _cat.CreateEntry<string>("Exclude_" + text, "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
				_entries[text] = val;
				HashSet<string> hashSet = new HashSet<string>();
				string[] array = val.Value.Split(new char[1] { '|' }, StringSplitOptions.RemoveEmptyEntries);
				foreach (string item in array)
				{
					hashSet.Add(item);
				}
				_sets[text] = hashSet;
			}
		}

		public static bool IsExcluded(string? barcode, string section)
		{
			if (!string.IsNullOrEmpty(barcode) && _sets.TryGetValue(section, out HashSet<string> value))
			{
				return value.Contains(barcode);
			}
			return false;
		}

		public static int Count(string section)
		{
			if (!_sets.TryGetValue(section, out HashSet<string> value))
			{
				return 0;
			}
			return value.Count;
		}

		public static bool Add(string section, string barcode)
		{
			if (string.IsNullOrEmpty(barcode) || !_sets.TryGetValue(section, out HashSet<string> value) || !value.Add(barcode))
			{
				return false;
			}
			Save(section);
			return true;
		}

		public static bool Remove(string section, string barcode)
		{
			if (!_sets.TryGetValue(section, out HashSet<string> value) || !value.Remove(barcode))
			{
				return false;
			}
			Save(section);
			return true;
		}

		private static void Save(string section)
		{
			_entries[section].Value = string.Join("|", _sets[section]);
			_cat.SaveToFile(false);
		}
	}
	[HarmonyPatch(typeof(Gun), "Fire")]
	public static class Gun_Fire_Patch
	{
		private static readonly Dictionary<Gun, int> _lastAmmo = new Dictionary<Gun, int>();

		public static void Postfix(Gun __instance)
		{
			try
			{
				int num;
				try
				{
					num = __instance.AmmoCount();
				}
				catch
				{
					return;
				}
				int value;
				bool flag = _lastAmmo.TryGetValue(__instance, out value);
				bool flag2;
				try
				{
					flag2 = __instance.isTriggerPressed;
				}
				catch
				{
					flag2 = true;
				}
				bool flag3 = flag && num < value && flag2;
				_lastAmmo[__instance] = num;
				if (GunFXSettings.DebugLog && (flag3 || !flag || num != value))
				{
					MelonLogger.Msg($"[QuickGunFX] ammo {(flag ? value : (-1))}->{num}  trigger={flag2}  fired={flag3}");
				}
				if (GunFXSettings.Enabled && flag3)
				{
					GunFX.OnShot(__instance, num);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[QuickGunFX] shot fx failed: " + ex.Message);
			}
		}
	}
	public static class GunFX
	{
		private struct Pending
		{
			public Gun gun;

			public float emitTime;

			public int chamberN;

			public int barrelN;

			public int chamberMode;

			public Vector2 chamberOff;

			public int chamberRep;

			public int barrelRep;

			public int gen;
		}

		private struct Impact
		{
			public Vector3 pos;

			public Vector3 dir;

			public float emitTime;

			public int repeats;

			public int gen;
		}

		private class SNode
		{
			public Vector3 pos;

			public Vector3 vel;

			public float birth;

			public int dotIdx;
		}

		private class Strand
		{
			public GameObject root;

			public LineRenderer line;

			public GameObject[] dots;

			public MeshRenderer[] dotMr;

			public bool[] dotUsed;

			public readonly List<SNode> nodes = new List<SNode>();

			public Transform? muzzle;

			public Vector3 origin;

			public Vector3 dir;

			public float nextEmit;

			public int emitsLeft;

			public bool active;

			public float bright;
		}

		private struct Plume
		{
			public Gun gun;

			public float nextTime;

			public int remaining;
		}

		private static ParticleSystem? _chamber;

		private static ParticleSystem? _barrel;

		private static ParticleSystem? _impact;

		private static ParticleSystem? _curved;

		private static Material? _mat;

		private static Texture2D? _tex;

		public static BarcodeSet? ChamberPistolGuns;

		public static BarcodeSet? ChamberRifleGuns;

		private static readonly Dictionary<Gun, float> _heat = new Dictionary<Gun, float>();

		private static readonly List<Gun> _heatKeys = new List<Gun>();

		private static readonly Dictionary<Gun, int> _chamberCharge = new Dictionary<Gun, int>();

		private static readonly List<Pending> _pending = new List<Pending>();

		private static readonly List<Impact> _impacts = new List<Impact>();

		private const int StrandPool = 12;

		private const int MaxNodes = 50;

		private static Strand[]? _strands;

		private static Material? _lineMat2;

		private static readonly MaterialPropertyBlock _dotBlock = new MaterialPropertyBlock();

		private static readonly Dictionary<Gun, float> _lineLastShot = new Dictionary<Gun, float>();

		private static readonly List<Gun> _lineKeys = new List<Gun>();

		private static readonly List<Plume> _plumes = new List<Plume>();

		private static readonly Dictionary<Gun, int> _tracerCount = new Dictionary<Gun, int>();

		private static readonly HashSet<int> _concHit = new HashSet<int>();

		private static Il2CppArrayBase<Light>? _lights;

		private static float _lightsTime = -999f;

		private static Il2CppStructArray<Vector3>? _shDirs;

		private static Il2CppStructArray<Color>? _shCols;

		private static Vector3 _lightCachePos;

		private static float _lightCacheVal = 1f;

		private static float _lightCacheTime = -99f;

		private static int Buildup(int n, int gen)
		{
			if (!GunFXSettings.RepeatBuildup)
			{
				return n;
			}
			return Mathf.RoundToInt((float)n * (1f + (float)gen * 0.5f));
		}

		private static bool ShouldTracer(Gun gun)
		{
			int tracerEveryX = GunFXSettings.TracerEveryX;
			if (tracerEveryX > 1)
			{
				int value;
				int num = (_tracerCount.TryGetValue(gun, out value) ? value : 0) + 1;
				_tracerCount[gun] = num;
				return num % tracerEveryX == 0;
			}
			if (GunFXSettings.TracerRandom)
			{
				return Random.Range(0, Mathf.Max(1, GunFXSettings.TracerChance)) == 0;
			}
			return true;
		}

		public static void OnShot(Gun gun, int ammoLeft)
		{
			//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_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			CartridgeTrails.NotifyFired(gun);
			string text = CartridgeTrails.BarcodeOf(gun);
			bool flag = Exclusions.IsExcluded(text, "chamber");
			bool flag2 = Exclusions.IsExcluded(text, "muzzle");
			if (GunFXSettings.RecoilEnabled && !Exclusions.IsExcluded(text, "recoil"))
			{
				ApplyRecoil(gun, gun.firePointTransform);
			}
			if (GunFXSettings.ImpactEnabled && !Exclusions.IsExcluded(text, "impact"))
			{
				TryQueueImpact(gun);
			}
			if (GunFXSettings.TracerEnabled && ShouldTracer(gun) && !Exclusions.IsExcluded(text, "tracer"))
			{
				Transform firePointTransform = gun.firePointTransform;
				if ((Object)(object)firePointTransform != (Object)null)
				{
					Tracers.Spawn(firePointTransform.position, firePointTransform.forward);
				}
			}
			if (GunFXSettings.LineMode && !flag2)
			{
				_lineLastShot[gun] = Time.time;
			}
			if (GunFXSettings.ConcussionEnabled && !Exclusions.IsExcluded(text, "concussion"))
			{
				float num = CaliberScore(gun);
				if (GunFXSettings.DebugLog)
				{
					MelonLogger.Msg($"[QuickGunFX] caliber={num:0.00}");
				}
				if (num >= GunFXSettings.ConcussionThreshold)
				{
					ApplyConcussion(gun, num);
				}
			}
			float value;
			float num2 = (_heat.TryGetValue(gun, out value) ? value : 0f);
			int num4;
			if (GunFXSettings.ChamberEnabled && !flag && GunFXSettings.ChamberOnEmpty)
			{
				int value2;
				int num3 = (_chamberCharge.TryGetValue(gun, out value2) ? value2 : 0) + 1;
				if (ammoLeft <= 0)
				{
					num4 = Mathf.Clamp(Mathf.RoundToInt(GunFXSettings.ChamberAmount * (float)num3), Mathf.RoundToInt(GunFXSettings.ChamberAmount), 600);
					_chamberCharge[gun] = 0;
				}
				else
				{
					num4 = 0;
					_chamberCharge[gun] = num3;
				}
			}
			else
			{
				num4 = ((GunFXSettings.ChamberEnabled && !flag) ? Mathf.RoundToInt(GunFXSettings.ChamberAmount * (0.1f + 0.9f * num2)) : 0);
			}
			int num5 = ((GunFXSettings.BarrelEnabled && !flag2) ? Mathf.RoundToInt(GunFXSettings.BarrelAmount * (0.15f + 0.85f * num2)) : 0);
			int num6 = 0;
			Vector2 chamberOff = Vector2.zero;
			if (text != null)
			{
				if (ChamberPistolGuns != null && ChamberPistolGuns.Contains(text))
				{
					num6 = 1;
				}
				else if (ChamberRifleGuns != null && ChamberRifleGuns.Contains(text))
				{
					num6 = 2;
				}
				if (num6 != 0)
				{
					chamberOff = ChamberOffsets.Get(text);
				}
			}
			_heat[gun] = Mathf.Min(1f, num2 + GunFXSettings.Buildup);
			if (num4 > 0 || num5 > 0)
			{
				_pending.Add(new Pending
				{
					gun = gun,
					emitTime = Time.time + Mathf.Max(0f, GunFXSettings.Delay),
					chamberN = num4,
					barrelN = num5,
					chamberMode = num6,
					chamberOff = chamberOff,
					chamberRep = ((!GunFXSettings.LineMode) ? Mathf.Clamp(Mathf.RoundToInt(GunFXSettings.ChamberRepeat), 0, 500) : 0),
					barrelRep = ((!GunFXSettings.LineMode) ? Mathf.Clamp(Mathf.RoundToInt(GunFXSettings.BarrelRepeat), 0, 500) : 0)
				});
			}
		}

		public static void Update()
		{
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			float deltaTime = Time.deltaTime;
			UpdateStrands(time, deltaTime);
			ProcessLineGuns(time);
			if (_heat.Count > 0)
			{
				_heatKeys.Clear();
				foreach (Gun key in _heat.Keys)
				{
					_heatKeys.Add(key);
				}
				float num = GunFXSettings.Fade * deltaTime;
				foreach (Gun heatKey in _heatKeys)
				{
					if ((Object)(object)heatKey == (Object)null)
					{
						_heat.Remove(heatKey);
						_chamberCharge.Remove(heatKey);
						continue;
					}
					float num2 = _heat[heatKey] - num;
					if (num2 <= 0.01f)
					{
						_heat.Remove(heatKey);
					}
					else
					{
						_heat[heatKey] = num2;
					}
				}
			}
			for (int num3 = _pending.Count - 1; num3 >= 0; num3--)
			{
				if (!(time < _pending[num3].emitTime))
				{
					Pending p = _pending[num3];
					_pending.RemoveAt(num3);
					if (!((Object)(object)p.gun == (Object)null))
					{
						try
						{
							EnsureBuilt();
							EmitShot(p);
							if (p.chamberRep > 0 || p.barrelRep > 0)
							{
								_pending.Add(new Pending
								{
									gun = p.gun,
									emitTime = time + Mathf.Max(0.02f, GunFXSettings.RepeatDelay),
									chamberN = ((p.chamberRep > 0) ? p.chamberN : 0),
									barrelN = ((p.barrelRep > 0) ? p.barrelN : 0),
									chamberMode = p.chamberMode,
									chamberOff = p.chamberOff,
									chamberRep = Mathf.Max(0, p.chamberRep - 1),
									barrelRep = Mathf.Max(0, p.barrelRep - 1),
									gen = p.gen + 1
								});
							}
						}
						catch (Exception ex)
						{
							MelonLogger.Warning("[QuickGunFX] emit failed: " + ex.Message);
						}
					}
				}
			}
			for (int num4 = _impacts.Count - 1; num4 >= 0; num4--)
			{
				if (!(time < _impacts[num4].emitTime))
				{
					Impact impact = _impacts[num4];
					_impacts.RemoveAt(num4);
					try
					{
						EnsureBuilt();
						if ((Object)(object)_impact != (Object)null)
						{
							Emit(_impact, impact.pos, impact.dir, Buildup((int)GunFXSettings.ImpactAmount, impact.gen), GunFXSettings.ImpactSize, GunFXSettings.ImpactLifetime, GunFXSettings.ImpactOpacity, GunFXSettings.ImpactRise, GunFXSettings.ImpactRise * 0.3f);
						}
						if (impact.repeats > 0)
						{
							_impacts.Add(new Impact
							{
								pos = impact.pos,
								dir = impact.dir,
								emitTime = time + Mathf.Max(0.02f, GunFXSettings.RepeatDelay),
								repeats = impact.repeats - 1,
								gen = impact.gen + 1
							});
						}
					}
					catch (Exception ex2)
					{
						MelonLogger.Warning("[QuickGunFX] impact emit failed: " + ex2.Message);
					}
				}
			}
		}

		private static void TryQueueImpact(Gun gun)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			Transform firePointTransform = gun.firePointTransform;
			RaycastHit val = default(RaycastHit);
			if (!((Object)(object)firePointTransform == (Object)null) && Physics.Raycast(firePointTransform.position, firePointTransform.forward, ref val, GunFXSettings.ImpactRange, -1, (QueryTriggerInteraction)1))
			{
				Vector3 val2 = ((RaycastHit)(ref val)).normal * 0.6f + Vector3.up * 0.4f;
				Vector3 normalized = ((Vector3)(ref val2)).normalized;
				float num = Mathf.Clamp(((RaycastHit)(ref val)).distance / 250f, 0f, 0.25f);
				_impacts.Add(new Impact
				{
					pos = ((RaycastHit)(ref val)).point + ((RaycastHit)(ref val)).normal * 0.02f,
					dir = normalized,
					emitTime = Time.time + num,
					repeats = Mathf.Clamp(Mathf.RoundToInt(GunFXSettings.ImpactRepeat), 0, 50)
				});
			}
		}

		private static void EnsureStrands()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			if (_strands != null)
			{
				return;
			}
			_strands = new Strand[12];
			for (int i = 0; i < 12; i++)
			{
				GameObject val = new GameObject("[QuickGunFX] Strand" + i);
				Object.DontDestroyOnLoad((Object)(object)val);
				LineRenderer val2 = val.AddComponent<LineRenderer>();
				((Renderer)val2).material = LineMat();
				val2.useWorldSpace = true;
				val2.numCapVertices = 2;
				val2.numCornerVertices = 2;
				val2.alignment = (LineAlignment)0;
				val2.textureMode = (LineTextureMode)0;
				((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)val2).receiveShadows = false;
				val2.positionCount = 0;
				AnimationCurve val3 = new AnimationCurve();
				val3.AddKey(0f, 0.3f);
				val3.AddKey(1f, 1f);
				val2.widthCurve = val3;
				GameObject[] array = (GameObject[])(object)new GameObject[50];
				MeshRenderer[] array2 = (MeshRenderer[])(object)new MeshRenderer[50];
				bool[] dotUsed = new bool[50];
				for (int j = 0; j < 50; j++)
				{
					GameObject val4 = GameObject.CreatePrimitive((PrimitiveType)5);
					((Object)val4).name = "dot";
					Collider component = val4.GetComponent<Collider>();
					if ((Object)(object)component != (Object)null)
					{
						Object.Destroy((Object)(object)component);
					}
					MeshRenderer component2 = val4.GetComponent<MeshRenderer>();
					((Renderer)component2).material = SmokeMaterial();
					((Renderer)component2).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)component2).receiveShadows = false;
					val4.transform.SetParent(val.transform, false);
					val4.SetActive(false);
					array[j] = val4;
					array2[j] = component2;
				}
				_strands[i] = new Strand
				{
					root = val,
					line = val2,
					dots = array,
					dotMr = array2,
					dotUsed = dotUsed,
					active = false
				};
			}
		}

		private static Material LineMat()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if ((Object)(object)_lineMat2 != (Object)null)
			{
				return _lineMat2;
			}
			_lineMat2 = new Material(Shader.Find("Sprites/Default"));
			return _lineMat2;
		}

		private static void ProcessLineGuns(float now)
		{
			if (_lineLastShot.Count > 0)
			{
				_lineKeys.Clear();
				foreach (Gun key in _lineLastShot.Keys)
				{
					_lineKeys.Add(key);
				}
				foreach (Gun lineKey in _lineKeys)
				{
					if ((Object)(object)lineKey == (Object)null)
					{
						_lineLastShot.Remove(lineKey);
						continue;
					}
					float num = _lineLastShot[lineKey];
					bool flag;
					try
					{
						flag = lineKey.isTriggerPressed;
					}
					catch
					{
						flag = false;
					}
					if (!flag || !(now - num <= 0.6f))
					{
						_lineLastShot.Remove(lineKey);
						if (GunFXSettings.LineMode)
						{
							_plumes.Add(new Plume
							{
								gun = lineKey,
								nextTime = now,
								remaining = Mathf.Clamp(Mathf.RoundToInt(GunFXSettings.LineRepeat), 0, 50) + 1
							});
						}
					}
				}
			}
			for (int num2 = _plumes.Count - 1; num2 >= 0; num2--)
			{
				Plume value = _plumes[num2];
				if ((Object)(object)value.gun == (Object)null)
				{
					_plumes.RemoveAt(num2);
				}
				else
				{
					int num3 = 0;
					while (value.remaining > 0 && now >= value.nextTime && num3++ < 60)
					{
						Transform val = null;
						try
						{
							val = value.gun.firePointTransform;
						}
						catch
						{
						}
						if ((Object)(object)val == (Object)null)
						{
							try
							{
								val = ((Component)value.gun).transform;
							}
							catch
							{
							}
						}
						if ((Object)(object)val != (Object)null)
						{
							SpawnStrand(val);
						}
						value.remaining--;
						value.nextTime += Mathf.Max(0.02f, GunFXSettings.RepeatDelay);
					}
					if (value.remaining <= 0)
					{
						_plumes.RemoveAt(num2);
					}
					else
					{
						_plumes[num2] = value;
					}
				}
			}
		}

		private static void SpawnStrand(Transform muzzle)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			EnsureStrands();
			if (_strands == null || (Object)(object)muzzle == (Object)null)
			{
				return;
			}
			int num = -1;
			for (int i = 0; i < _strands.Length; i++)
			{
				if (!_strands[i].active)
				{
					num = i;
					break;
				}
			}
			if (num < 0)
			{
				num = 0;
			}
			Strand strand = _strands[num];
			for (int j = 0; j < 50; j++)
			{
				strand.dotUsed[j] = false;
				strand.dots[j].SetActive(false);
			}
			strand.nodes.Clear();
			strand.line.positionCount = 0;
			strand.muzzle = muzzle;
			strand.origin = muzzle.position;
			strand.dir = muzzle.forward;
			strand.emitsLeft = Mathf.Clamp(Mathf.RoundToInt(GunFXSettings.LineDots), 2, 50);
			strand.nextEmit = Time.time;
			strand.active = true;
			strand.bright = LightMul(muzzle.position);
		}

		private static void AddNode(Strand s)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_008c: 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)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			if (s.nodes.Count >= 50)
			{
				return;
			}
			int num = -1;
			for (int i = 0; i < 50; i++)
			{
				if (!s.dotUsed[i])
				{
					num = i;
					break;
				}
			}
			if (num >= 0)
			{
				s.dotUsed[num] = true;
				s.dots[num].SetActive(true);
				Transform muzzle = s.muzzle;
				Vector3 val;
				Vector3 val2;
				if ((Object)(object)muzzle != (Object)null)
				{
					val = muzzle.position + muzzle.forward * 0.03f;
					val2 = muzzle.forward * 0.6f + muzzle.up * 0.4f;
				}
				else
				{
					val = s.origin;
					val2 = s.dir;
				}
				if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
				{
					val2 = Vector3.up;
				}
				val2 = ((Vector3)(ref val2)).normalized;
				float num2 = (GunFXSettings.LineFast ? 1.1f : 0.55f);
				Vector3 val3 = Random.insideUnitSphere * (GunFXSettings.ChamberDrift * 0.3f);
				s.nodes.Add(new SNode
				{
					pos = val + Random.insideUnitSphere * 0.008f,
					vel = val2 * num2 + val3,
					birth = Time.time,
					dotIdx = num
				});
			}
		}

		private static void UpdateStrands(float now, float dt)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
			if (_strands == null)
			{
				return;
			}
			Transform head = Player.Head;
			Vector3 val = (((Object)(object)head != (Object)null) ? head.position : Vector3.zero);
			float num = Mathf.Max(0.2f, GunFXSettings.LineLife);
			float num2 = Mathf.Clamp01(GunFXSettings.ChamberOpacity);
			float num3 = Mathf.Max(0.003f, GunFXSettings.LineWidth);
			float num4 = num3 * 2.5f;
			Color val4 = default(Color);
			for (int i = 0; i < _strands.Length; i++)
			{
				Strand strand = _strands[i];
				if (!strand.active)
				{
					continue;
				}
				float num5 = GunFXSettings.Gray * strand.bright;
				int num6 = 0;
				while (strand.emitsLeft > 0 && now >= strand.nextEmit && num6++ < 50)
				{
					AddNode(strand);
					strand.emitsLeft--;
					strand.nextEmit += 0.03f;
				}
				Vector3 val2 = Vector3.up * (GunFXSettings.LineFast ? 0.7f : 0.32f);
				for (int j = 0; j < strand.nodes.Count; j++)
				{
					SNode sNode = strand.nodes[j];
					sNode.vel = Vector3.Lerp(sNode.vel, val2, 2.5f * dt);
					Vector3 val3 = Random.insideUnitSphere * 0.06f;
					sNode.pos += (sNode.vel + val3) * dt;
				}
				while (strand.nodes.Count > 0 && now - strand.nodes[0].birth > num)
				{
					int dotIdx = strand.nodes[0].dotIdx;
					strand.dotUsed[dotIdx] = false;
					strand.dots[dotIdx].SetActive(false);
					strand.nodes.RemoveAt(0);
				}
				for (int k = 0; k < strand.nodes.Count; k++)
				{
					SNode sNode2 = strand.nodes[k];
					Transform transform = strand.dots[sNode2.dotIdx].transform;
					float num7 = Mathf.Clamp01((now - sNode2.birth) / num);
					transform.position = sNode2.pos;
					if (val != Vector3.zero)
					{
						transform.rotation = Quaternion.LookRotation(sNode2.pos - val, Vector3.up);
					}
					float num8 = Mathf.Max(0.05f, 1f - GunFXSettings.LineShrink);
					transform.localScale = Vector3.one * num4 * Mathf.Lerp(1f, num8, num7);
					float num9 = num2 * ((num7 < 0.12f) ? (num7 / 0.12f) : 1f) * (1f - num7);
					_dotBlock.SetColor("_Color", new Color(num5, num5, num5, num9));
					((Renderer)strand.dotMr[sNode2.dotIdx]).SetPropertyBlock(_dotBlock);
				}
				if (strand.nodes.Count >= 2)
				{
					strand.line.positionCount = strand.nodes.Count;
					for (int l = 0; l < strand.nodes.Count; l++)
					{
						strand.line.SetPosition(l, strand.nodes[l].pos);
					}
					float num10 = Mathf.Clamp01((now - strand.nodes[strand.nodes.Count - 1].birth) / num);
					float num11 = Mathf.Lerp(1f, Mathf.Max(0.1f, 1f - GunFXSettings.LineShrink), num10);
					strand.line.widthMultiplier = num3 * 0.5f * num11;
					((Color)(ref val4))..ctor(num5, num5, num5, num2 * 0.55f);
					strand.line.startColor = val4;
					strand.line.endColor = val4;
				}
				else
				{
					strand.line.positionCount = 0;
				}
				if (strand.emitsLeft == 0 && strand.nodes.Count == 0)
				{
					strand.active = false;
					strand.line.positionCount = 0;
				}
			}
		}

		private static void EmitShot(Pending p)
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: 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_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: 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_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			Gun gun = p.gun;
			Transform firePointTransform = gun.firePointTransform;
			Transform shellSpawnTransform = gun.shellSpawnTransform;
			Transform val = (((Object)(object)firePointTransform != (Object)null) ? firePointTransform : ((Component)gun).transform);
			int num = Buildup(p.chamberN, p.gen);
			int num2 = Buildup(p.barrelN, p.gen);
			if (num > 0 && !GunFXSettings.LineMode)
			{
				Vector3 val2 = (((Object)(object)shellSpawnTransform != (Object)null) ? shellSpawnTransform.position : (((Object)(object)firePointTransform != (Object)null) ? (firePointTransform.position - firePointTransform.forward * 0.12f + firePointTransform.up * 0.03f) : ((Component)gun).transform.position));
				if (p.chamberMode != 0 && (Object)(object)_curved != (Object)null)
				{
					val2 += val.forward * p.chamberOff.x + val.right * p.chamberOff.y;
					Vector3 val3 = ((p.chamberMode == 1) ? val.forward : val.right);
					if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f)
					{
						val3 = Vector3.up;
					}
					SetCurveStrength();
					Emit(_curved, val2, ((Vector3)(ref val3)).normalized, num, GunFXSettings.ChamberSize, GunFXSettings.ChamberLifetime, GunFXSettings.ChamberOpacity, GunFXSettings.CurvePush, GunFXSettings.ChamberDrift);
				}
				else if ((Object)(object)_chamber != (Object)null)
				{
					Vector3 dir = val.right * GunFXSettings.ChamberDirSide + val.up * GunFXSettings.ChamberDirUp + val.forward * GunFXSettings.ChamberDirForward;
					if (((Vector3)(ref dir)).sqrMagnitude < 0.0001f)
					{
						dir = Vector3.up;
					}
					dir = ((Vector3)(ref dir)).normalized;
					Emit(_chamber, val2, dir, num, GunFXSettings.ChamberSize, GunFXSettings.ChamberLifetime, GunFXSettings.ChamberOpacity, GunFXSettings.ChamberRise, GunFXSettings.ChamberDrift);
				}
			}
			if (num2 > 0 && (Object)(object)firePointTransform != (Object)null)
			{
				if (GunFXSettings.BarrelCurve && (Object)(object)_curved != (Object)null)
				{
					SetCurveStrength();
					Emit(_curved, firePointTransform.position, firePointTransform.forward, num2, GunFXSettings.BarrelSize, GunFXSettings.BarrelLifetime, GunFXSettings.BarrelOpacity, GunFXSettings.CurvePush, GunFXSettings.ChamberDrift);
				}
				else if ((Object)(object)_barrel != (Object)null)
				{
					Emit(_barrel, firePointTransform.position, firePointTransform.forward, num2, GunFXSettings.BarrelSize, GunFXSettings.BarrelLifetime, GunFXSettings.BarrelOpacity, GunFXSettings.BarrelPush, GunFXSettings.ChamberDrift);
				}
			}
		}

		private static void SetCurveStrength()
		{
			if (!((Object)(object)_curved == (Object)null))
			{
				_curved.main.gravityModifier = MinMaxCurve.op_Implicit((0f - Mathf.Max(0f, GunFXSettings.CurveStrength)) / 9.81f);
			}
		}

		private static void Emit(ParticleSystem ps, Vector3 pos, Vector3 dir, int count, float size, float life, float opacity, float rise, float drift)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_0081: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			if (count <= 0)
			{
				return;
			}
			try
			{
				int num = ps.main.maxParticles - ps.particleCount;
				if (num <= 0)
				{
					return;
				}
				if (count > num)
				{
					count = num;
				}
			}
			catch
			{
			}
			float num2 = GunFXSettings.Gray * LightMulCached(pos);
			Color val = default(Color);
			((Color)(ref val))..ctor(num2, num2, num2, opacity);
			for (int i = 0; i < count; i++)
			{
				Vector3 val2 = Random.insideUnitSphere * drift;
				val2.y *= 0.3f;
				EmitParams val3 = default(EmitParams);
				((EmitParams)(ref val3)).position = pos + Random.insideUnitSphere * 0.008f;
				((EmitParams)(ref val3)).velocity = dir * (rise * Random.Range(0.8f, 1.2f)) + val2;
				((EmitParams)(ref val3)).startSize = size * Random.Range(0.75f, 1.25f);
				((EmitParams)(ref val3)).startLifetime = life * Random.Range(0.6f, 1.15f);
				((EmitParams)(ref val3)).startColor = Color32.op_Implicit(val);
				ps.Emit(val3, 1);
			}
		}

		private static float CaliberScore(Gun gun)
		{
			try
			{
				CartridgeData val = gun.chamberedCartridge;
				if ((Object)(object)val == (Object)null)
				{
					val = gun.defaultCartridge;
				}
				ProjectileData val2 = ((val != null) ? val.projectile : null);
				if ((Object)(object)val2 == (Object)null)
				{
					return 0f;
				}
				float num = val2.startVelocity;
				if (num <= 0f)
				{
					try
					{
						num = gun.muzzleVelocity;
					}
					catch
					{
					}
				}
				return val2.mass * Mathf.Max(0f, num);
			}
			catch
			{
				return 0f;
			}
		}

		private static void ApplyConcussion(Gun gun, float score)
		{
			//IL_001e: 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)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: 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)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: 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_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Transform firePointTransform = gun.firePointTransform;
				Vector3 val = (((Object)(object)firePointTransform != (Object)null) ? firePointTransform.position : ((Component)gun).transform.position);
				float concussionRadius = GunFXSettings.ConcussionRadius;
				Il2CppReferenceArray<Collider> val2 = Physics.OverlapSphere(val, concussionRadius, -1, (QueryTriggerInteraction)1);
				if (val2 == null)
				{
					return;
				}
				float num = Mathf.Min(score - GunFXSettings.ConcussionThreshold, GunFXSettings.ConcussionMax);
				float num2 = Mathf.Max(0.2f, num) * GunFXSettings.ConcussionStrength;
				Rigidbody val3 = null;
				try
				{
					val3 = ((Component)gun).GetComponentInParent<Rigidbody>();
				}
				catch
				{
				}
				RigManager rigManager = Player.RigManager;
				int num3 = 0;
				_concHit.Clear();
				foreach (Collider item in (Il2CppArrayBase<Collider>)(object)val2)
				{
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					Rigidbody attachedRigidbody = item.attachedRigidbody;
					if (!((Object)(object)attachedRigidbody == (Object)null) && !attachedRigidbody.isKinematic && _concHit.Add(((Object)attachedRigidbody).GetInstanceID()) && (!((Object)(object)val3 != (Object)null) || ((Object)attachedRigidbody).GetInstanceID() != ((Object)val3).GetInstanceID()) && !IsPlayerOrNpc(attachedRigidbody, rigManager) && !((Object)(object)((Component)attachedRigidbody).GetComponentInParent<FirearmCartridge>() != (Object)null))
					{
						Vector3 val4 = attachedRigidbody.worldCenterOfMass - val;
						float magnitude = ((Vector3)(ref val4)).magnitude;
						if (!(magnitude > concussionRadius))
						{
							Vector3 val5 = ((magnitude > 0.01f) ? (val4 / magnitude) : Vector3.up);
							float num4 = 1f - magnitude / concussionRadius;
							num4 *= num4;
							float num5 = num2 * num4;
							Vector3 val6 = val5 + Vector3.up * 0.6f;
							Vector3 val7 = ((Vector3)(ref val6)).normalized * num5 + Random.insideUnitSphere * (num5 * 0.2f);
							attachedRigidbody.AddForce(val7, (ForceMode)1);
							attachedRigidbody.AddTorque(Random.insideUnitSphere * (num5 * 0.3f), (ForceMode)1);
							num3++;
						}
					}
				}
				if (GunFXSettings.DebugLog)
				{
					MelonLogger.Msg($"[QuickGunFX] concussion score={score:0.00} power={num2:0.00} pushed={num3}");
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[QuickGunFX] concussion failed: " + ex.Message);
			}
		}

		private static bool IsPlayerOrNpc(Rigidbody rb, RigManager? playerRig)
		{
			try
			{
				if ((Object)(object)((Component)rb).GetComponentInParent<AIBrain>() != (Object)null)
				{
					return true;
				}
				if ((Object)(object)playerRig != (Object)null)
				{
					RigManager componentInParent = ((Component)rb).GetComponentInParent<RigManager>();
					if ((Object)(object)componentInParent != (Object)null && ((Object)componentInParent).GetInstanceID() == ((Object)playerRig).GetInstanceID())
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static void ApplyRecoil(Gun gun, Transform? fire)
		{
			//IL_002d: 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)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Rigidbody componentInParent = ((Component)gun).GetComponentInParent<Rigidbody>();
				if (!((Object)(object)componentInParent == (Object)null) && !componentInParent.isKinematic)
				{
					object obj = (((Object)(object)fire != (Object)null) ? ((object)fire) : ((object)((Component)gun).transform));
					Vector3 forward = ((Transform)obj).forward;
					Vector3 up = ((Transform)obj).up;
					Vector3 val = Random.insideUnitSphere * GunFXSettings.RecoilRandom;
					componentInParent.AddForce((-forward + val) * GunFXSettings.RecoilKick, (ForceMode)2);
					Vector3 val2 = Vector3.Cross(forward, up);
					Vector3 normalized = ((Vector3)(ref val2)).normalized;
					componentInParent.AddTorque(normalized * GunFXSettings.RecoilRise, (ForceMode)2);
				}
			}
			catch
			{
			}
		}

		private static void EnsureBuilt()
		{
			if ((Object)(object)_chamber == (Object)null)
			{
				_chamber = BuildSystem("[QuickGunFX] ChamberVapor");
			}
			if ((Object)(object)_barrel == (Object)null)
			{
				_barrel = BuildSystem("[QuickGunFX] MuzzleVapor");
			}
			if ((Object)(object)_impact == (Object)null)
			{
				_impact = BuildSystem("[QuickGunFX] ImpactSmoke");
			}
			if ((Object)(object)_curved == (Object)null)
			{
				_curved = BuildSystem("[QuickGunFX] CurvedSmoke");
			}
		}

		private static ParticleSystem BuildSystem(string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Expected O, but got Unknown
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Expected O, but got Unknown
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			Object.DontDestroyOnLoad((Object)(object)val);
			ParticleSystem obj = val.AddComponent<ParticleSystem>();
			MainModule main = obj.main;
			main.loop = true;
			main.playOnAwake = false;
			main.maxParticles = 800;
			main.simulationSpace = (ParticleSystemSimulationSpace)1;
			main.startSpeed = new MinMaxCurve(0f);
			main.startSize = new MinMaxCurve(0.03f);
			main.startLifetime = new MinMaxCurve(0.6f);
			main.gravityModifier = MinMaxCurve.op_Implicit(0f);
			main.startRotation = new MinMaxCurve(0f, (float)Math.PI * 2f);
			EmissionModule emission = obj.emission;
			emission.enabled = true;
			emission.rateOverTime = MinMaxCurve.op_Implicit(0f);
			ColorOverLifetimeModule colorOverLifetime = obj.colorOverLifetime;
			colorOverLifetime.enabled = true;
			Gradient val2 = new Gradient();
			val2.SetKeys(new Il2CppStructArray<GradientColorKey>(2L)
			{
				[0] = new GradientColorKey(Color.white, 0f),
				[1] = new GradientColorKey(Color.white, 1f)
			}, new Il2CppStructArray<GradientAlphaKey>(3L)
			{
				[0] = new GradientAlphaKey(0f, 0f),
				[1] = new GradientAlphaKey(1f, 0.25f),
				[2] = new GradientAlphaKey(0f, 1f)
			});
			colorOverLifetime.color = new MinMaxGradient(val2);
			SizeOverLifetimeModule sizeOverLifetime = obj.sizeOverLifetime;
			sizeOverLifetime.enabled = true;
			AnimationCurve val3 = new AnimationCurve();
			val3.AddKey(0f, 0.7f);
			val3.AddKey(0.3f, 1f);
			val3.AddKey(1f, 1.6f);
			sizeOverLifetime.size = new MinMaxCurve(1f, val3);
			RotationOverLifetimeModule rotationOverLifetime = obj.rotationOverLifetime;
			rotationOverLifetime.enabled = true;
			rotationOverLifetime.z = new MinMaxCurve(-0.6f, 0.6f);
			NoiseModule noise = obj.noise;
			noise.enabled = true;
			noise.strength = new MinMaxCurve(0.04f);
			noise.frequency = 0.8f;
			noise.scrollSpeed = new MinMaxCurve(0.25f);
			ParticleSystemRenderer component = val.GetComponent<ParticleSystemRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				((Renderer)component).material = SmokeMaterial();
				component.renderMode = (ParticleSystemRenderMode)0;
				component.sortMode = (ParticleSystemSortMode)1;
				((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)component).receiveShadows = false;
			}
			obj.Play();
			return obj;
		}

		private static Material SmokeMaterial()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if ((Object)(object)_mat != (Object)null)
			{
				return _mat;
			}
			_mat = new Material(Shader.Find("Sprites/Default"));
			_mat.mainTexture = (Texture)(object)SmokeTexture();
			return _mat;
		}

		public static void RefreshSmokeMaterials()
		{
		}

		public static float LightMul(Vector3 pos)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!GunFXSettings.SmokeLit)
			{
				return 1f;
			}
			try
			{
				float num = ProbeLum(pos) + RealtimeLum(pos);
				if (num <= 0f)
				{
					num = 0.04f;
				}
				return Mathf.Clamp(Mathf.Clamp01(num * GunFXSettings.LightSensitivity), 0.03f, 1f);
			}
			catch
			{
				return 1f;
			}
		}

		private static float ProbeLum(Vector3 pos)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_shDirs == null)
				{
					_shDirs = new Il2CppStructArray<Vector3>(6L);
					((Il2CppArrayBase<Vector3>)(object)_shDirs)[0] = Vector3.up;
					((Il2CppArrayBase<Vector3>)(object)_shDirs)[1] = Vector3.down;
					((Il2CppArrayBase<Vector3>)(object)_shDirs)[2] = Vector3.left;
					((Il2CppArrayBase<Vector3>)(object)_shDirs)[3] = Vector3.right;
					((Il2CppArrayBase<Vector3>)(object)_shDirs)[4] = Vector3.forward;
					((Il2CppArrayBase<Vector3>)(object)_shDirs)[5] = Vector3.back;
					_shCols = new Il2CppStructArray<Color>(6L);
				}
				SphericalHarmonicsL2 val = default(SphericalHarmonicsL2);
				LightProbes.GetInterpolatedProbe(pos, (Renderer)null, ref val);
				((SphericalHarmonicsL2)(ref val)).Evaluate(_shDirs, _shCols);
				float num = 0f;
				for (int i = 0; i < 6; i++)
				{
					Color val2 = ((Il2CppArrayBase<Color>)(object)_shCols)[i];
					num += val2.r * 0.299f + val2.g * 0.587f + val2.b * 0.114f;
				}
				return Mathf.Max(0f, num / 6f);
			}
			catch
			{
				return 0f;
			}
		}

		private static float LightMulCached(Vector3 pos)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time - _lightCacheTime < 0.2f)
			{
				Vector3 val = pos - _lightCachePos;
				if (((Vector3)(ref val)).sqrMagnitude < 0.25f)
				{
					return _lightCacheVal;
				}
			}
			_lightCacheVal = LightMul(pos);
			_lightCachePos = pos;
			_lightCacheTime = Time.time;
			return _lightCacheVal;
		}

		private static float RealtimeLum(Vector3 pos)
		{
			//IL_008a: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Invalid comparison between Unknown and I4
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			if (_lights == null || Time.time - _lightsTime > 3f)
			{
				_lightsTime = Time.time;
				try
				{
					_lights = Object.FindObjectsOfType<Light>();
				}
				catch
				{
				}
			}
			if (_lights == null)
			{
				return 0f;
			}
			float num = 0f;
			int num2 = 0;
			foreach (Light light in _lights)
			{
				if ((Object)(object)light == (Object)null || !((Behaviour)light).isActiveAndEnabled)
				{
					continue;
				}
				float intensity = light.intensity;
				if (intensity <= 0.01f)
				{
					continue;
				}
				LightType type = light.type;
				if ((int)type == 1)
				{
					if (!Occluded(pos, pos + -((Component)light).transform.forward * 40f))
					{
						num += intensity;
					}
					continue;
				}
				Vector3 position = ((Component)light).transform.position;
				float range = light.range;
				float num3 = Vector3.Distance(pos, position);
				if (range <= 0.01f || num3 > range)
				{
					continue;
				}
				if ((int)type == 0)
				{
					Vector3 val = pos - position;
					Vector3 normalized = ((Vector3)(ref val)).normalized;
					float num4 = Mathf.Cos(light.spotAngle * 0.5f * ((float)Math.PI / 180f));
					if (Vector3.Dot(normalized, ((Component)light).transform.forward) < num4)
					{
						continue;
					}
				}
				if (num2++ <= 8 && !Occluded(pos, position))
				{
					float num5 = 1f - num3 / range;
					num5 *= num5;
					num += intensity * num5;
				}
			}
			return num;
		}

		private static bool Occluded(Vector3 from, Vector3 to)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = to - from;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.02f)
			{
				return false;
			}
			val /= magnitude;
			return Physics.Raycast(from + val * 0.2f, val, magnitude - 0.2f, -1, (QueryTriggerInteraction)1);
		}

		private static Texture2D SmokeTexture()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_tex != (Object)null)
			{
				return _tex;
			}
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1
			};
			float num = Random.value * 100f;
			float num2 = Random.value * 100f;
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num3 = ((float)j + 0.5f) / 128f - 0.5f;
					float num4 = ((float)i + 0.5f) / 128f - 0.5f;
					float num5 = Mathf.Sqrt(num3 * num3 + num4 * num4) * 2f;
					float num6 = Mathf.Clamp01(1f - num5);
					num6 = num6 * num6 * num6;
					float num7 = 0.85f + 0.15f * Mathf.PerlinNoise((float)j * 0.03f + num, (float)i * 0.03f + num2);
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num6 * num7));
				}
			}
			val.Apply();
			_tex = val;
			return val;
		}
	}
	public class GunFXMod : MelonMod
	{
		private static FloatElement? _offX;

		private static FloatElement? _offY;

		private static FloatElement? _offZ;

		private static FunctionElement? _offStatus;

		private static string? _lastHeld;

		private static float _offTimer;

		private static FloatElement? _cfB;

		private static FloatElement? _cfLR;

		private static FunctionElement? _cfStatus;

		private static string? _cfLastHeld;

		private static float _cfTimer;

		public override void OnInitializeMelon()
		{
			GunFXSettings.Initialize();
			SavedGuns.Initialize();
			ChamberOffsets.Initialize();
			Exclusions.Initialize();
			AirRack.Guns = new BarcodeSet("QuickGunFXAirRackGuns");
			MagInsert.Guns = new BarcodeSet("QuickGunFXMagGuns");
			GunFX.ChamberPistolGuns = new BarcodeSet("QuickGunFXChamberPistolGuns");
			GunFX.ChamberRifleGuns = new BarcodeSet("QuickGunFXChamberRifleGuns");
			QuickModsTheme.Initialize();
			Hooking.OnLevelLoaded += delegate
			{
				CartridgeTrails.ClearAll();
			};
			SetupMenu();
			((MelonBase)this).LoggerInstance.Msg("QuickGunFX loaded!");
		}

		public override void OnUpdate()
		{
			GunFX.Update();
			CartridgeTrails.Update();
			Tracers.Update();
			AirRack.Update();
			MagInsert.Update();
			_offTimer -= Time.deltaTime;
			if (_offTimer <= 0f)
			{
				_offTimer = 0.2f;
				SyncOffset();
			}
			_cfTimer -= Time.deltaTime;
			if (_cfTimer <= 0f)
			{
				_cfTimer = 0.2f;
				ChamberSyncOffset();
			}
		}

		private static bool HeldChamberCurveGun(out string bc, out string title)
		{
			bc = "";
			title = "";
			if (!CartridgeTrails.TryGetHeldGun(out string barcode, out string title2))
			{
				return false;
			}
			if ((GunFX.ChamberPistolGuns == null || !GunFX.ChamberPistolGuns.Contains(barcode)) && (GunFX.ChamberRifleGuns == null || !GunFX.ChamberRifleGuns.Contains(barcode)))
			{
				return false;
			}
			bc = barcode;
			title = title2;
			return true;
		}

		private static void ChamberSyncOffset()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			string text = null;
			string text2 = "";
			if (HeldChamberCurveGun(out string bc, out string title))
			{
				text = bc;
				text2 = title;
			}
			if (text == _cfLastHeld)
			{
				return;
			}
			_cfLastHeld = text;
			if (text != null)
			{
				Vector2 val = ChamberOffsets.Get(text);
				if (_cfB != null)
				{
					_cfB.Value = val.x;
				}
				if (_cfLR != null)
				{
					_cfLR.Value = val.y;
				}
				if (_cfStatus != null)
				{
					((Element)_cfStatus).ElementName = "Editing: " + text2;
				}
			}
			else if (_cfStatus != null)
			{
				((Element)_cfStatus).ElementName = "Hold a pistol/rifle from the sets";
			}
		}

		private static void SetHeldChamberOffset(int axis, float v)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (HeldChamberCurveGun(out string bc, out string _))
			{
				Vector2 v2 = ChamberOffsets.Get(bc);
				if (axis == 0)
				{
					v2.x = v;
				}
				else
				{
					v2.y = v;
				}
				ChamberOffsets.Set(bc, v2);
			}
		}

		private static void SyncOffset()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			string text = null;
			string text2 = "";
			if (CartridgeTrails.TryGetHeldGun(out string barcode, out string title) && SavedGuns.Contains(barcode))
			{
				text = barcode;
				text2 = title;
			}
			if (text == _lastHeld)
			{
				return;
			}
			_lastHeld = text;
			if (text != null)
			{
				Vector3 offset = SavedGuns.GetOffset(text);
				if (_offX != null)
				{
					_offX.Value = offset.x;
				}
				if (_offY != null)
				{
					_offY.Value = offset.y;
				}
				if (_offZ != null)
				{
					_offZ.Value = offset.z;
				}
				if (_offStatus != null)
				{
					((Element)_offStatus).ElementName = "Editing: " + text2;
				}
			}
			else if (_offStatus != null)
			{
				((Element)_offStatus).ElementName = "Offset: hold a saved gun";
			}
		}

		private static void SetHeldOffset(int axis, float v)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (CartridgeTrails.TryGetHeldGun(out string barcode, out string _) && SavedGuns.Contains(barcode))
			{
				Vector3 offset = SavedGuns.GetOffset(barcode);
				switch (axis)
				{
				case 0:
					offset.x = v;
					break;
				case 1:
					offset.y = v;
					break;
				default:
					offset.z = v;
					break;
				}
				SavedGuns.SetOffset(barcode, offset);
			}
		}

		private static void BuildPresetsPage(Page root)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: 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_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: 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)
			Page val = root.CreatePage("Presets (save / share)", new Color(0.6f, 0.85f, 1f), 0, true);
			FunctionElement status = val.CreateFunction("hold a .cat path in your clipboard to load", Color.gray, (Action)delegate
			{
			});
			val.CreateFunction("Save To Downloads", new Color(0.5f, 1f, 0.7f), (Action)delegate
			{
				((Element)status).ElementName = PresetIO.Save();
			});
			val.CreateFunction("Load From Clipboard Path", new Color(0.7f, 0.9f, 1f), (Action)delegate
			{
				((Element)status).ElementName = PresetIO.Load();
			});
			val.CreateFunction("--- how to ---", Color.gray, (Action)delegate
			{
			});
			val.CreateFunction("save: writes a .cat to Downloads,", Color.gray, (Action)delegate
			{
			});
			val.CreateFunction("copies its path to your clipboard", Color.gray, (Action)delegate
			{
			});
			val.CreateFunction("load: copy a .cat's file path", Color.gray, (Action)delegate
			{
			});
			val.CreateFunction("(shift+right-click > copy as path)", Color.gray, (Action)delegate
			{
			});
			val.CreateFunction("then hit Load", Color.gray, (Action)delegate
			{
			});
		}

		private static Page GetOrCreateQuickModsPage()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			object? data = AppDomain.CurrentDomain.GetData("QuickMods.RootPage");
			Page val = (Page)((data is Page) ? data : null);
			if (val != null)
			{
				return val;
			}
			Page val2 = Page.Root.CreatePage("Quick Mods", new Color(0.35f, 0.27f, 0.9f), 0, true);
			AppDomain.CurrentDomain.SetData("QuickMods.RootPage", val2);
			return val2;
		}

		private static void AddExclusionControls(Page page, string section)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			FunctionElement status = page.CreateFunction($"Excluded here: {Exclusions.Count(section)}", Color.gray, (Action)delegate
			{
			});
			page.CreateFunction("Exclude Held Gun", new Color(1f, 0.55f, 0.35f), (Action)delegate
			{
				if (CartridgeTrails.TryGetHeldGun(out string barcode, out string title))
				{
					((Element)status).ElementName = (Exclusions.Add(section, barcode) ? $"Excluded {title} ({Exclusions.Count(section)})" : ("Already excluded " + title));
				}
				else
				{
					((Element)status).ElementName = "No gun in hand";
				}
			});
			page.CreateFunction("Un-exclude Held Gun", new Color(0.5f, 1f, 0.7f), (Action)delegate
			{
				if (CartridgeTrails.TryGetHeldGun(out string barcode, out string title))
				{
					((Element)status).ElementName = (Exclusions.Remove(section, barcode) ? $"Un-excluded {title} ({Exclusions.Count(section)})" : ("Not excluded " + title));
				}
				else
				{
					((Element)status).ElementName = "No gun in hand";
				}
			});
		}

		private static void AddSelectionControls(Page page, BarcodeSet set)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			FunctionElement status = page.CreateFunction($"Selected guns: {set.Count}", Color.gray, (Action)delegate
			{
			});
			page.CreateFunction("Add Held Gun", new Color(0.5f, 1f, 0.7f), (Action)delegate
			{
				if (CartridgeTrails.TryGetHeldGun(out string barcode, out string title))
				{
					((Element)status).ElementName = (set.Add(barcode) ? $"Added {title}  (total {set.Count})" : ("Already added " + title));
				}
				else
				{
					((Element)status).ElementName = "No gun in hand";
				}
			});
			page.CreateFunction("Remove Held Gun", new Color(1f, 0.6f, 0.5f), (Action)delegate
			{
				if (CartridgeTrails.TryGetHeldGun(out string barcode, out string title))
				{
					((Element)status).ElementName = (set.Remove(barcode) ? $"Removed {title}  (total {set.Count})" : ("Not added " + title));
				}
				else
				{
					((Element)status).ElementName = "No gun in hand";
				}
			});
			page.CreateFunction("Clear All", new Color(1f, 0.4f, 0.4f), (Action)delegate
			{
				set.Clear();
				((Element)status).ElementName = "Selected guns: 0";
			});
		}

		private static void SetupMenu()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0407: Unknown result type (might be due to invalid IL or missing references)
			//IL_044b: Unknown result type (might be due to invalid IL or missing references)
			//IL_048f: Unknown result type (mig