Decompiled source of More Guns Forked Mono v1.6.5

MoreGunsMono.dll

Decompiled 4 hours ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using FishNet.Object;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using MoreGuns;
using MoreGuns.Dialogue;
using MoreGuns.Gui;
using MoreGuns.Guns;
using MoreGuns.Patches;
using MoreGuns.Sync;
using ScheduleOne;
using ScheduleOne.Audio;
using ScheduleOne.AvatarFramework;
using ScheduleOne.AvatarFramework.Equipping;
using ScheduleOne.Combat;
using ScheduleOne.Core.Items.Framework;
using ScheduleOne.DevUtilities;
using ScheduleOne.Dialogue;
using ScheduleOne.Equipping;
using ScheduleOne.FX;
using ScheduleOne.ItemFramework;
using ScheduleOne.Levelling;
using ScheduleOne.Networking;
using ScheduleOne.PlayerScripts;
using ScheduleOne.Tools;
using ScheduleOne.Trash;
using ScheduleOne.UI;
using ScheduleOne.UI.Shop;
using Steamworks;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(MoreGunsMod), "MoreGuns", "1.6.5", "Voidane", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: HarmonyDontPatchAll]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MoreGunsMono")]
[assembly: AssemblyConfiguration("Mono")]
[assembly: AssemblyFileVersion("1.6.5.0")]
[assembly: AssemblyInformationalVersion("1.6.5+a0f53f1260275c51c2e8503266a34bd2e4d56883")]
[assembly: AssemblyProduct("MoreGunsMono")]
[assembly: AssemblyTitle("MoreGunsMono")]
[assembly: AssemblyVersion("1.6.5.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal static class ModVersion
{
	public const string Current = "1.6.5";
}
namespace MoreGuns
{
	[GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
	[DebuggerNonUserCode]
	[CompilerGenerated]
	internal class Assets
	{
		private static ResourceManager resourceMan;

		private static CultureInfo resourceCulture;

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static ResourceManager ResourceManager
		{
			get
			{
				if (resourceMan == null)
				{
					ResourceManager resourceManager = new ResourceManager("MoreGuns.Assets", typeof(Assets).Assembly);
					resourceMan = resourceManager;
				}
				return resourceMan;
			}
		}

		[EditorBrowsable(EditorBrowsableState.Advanced)]
		internal static CultureInfo Culture
		{
			get
			{
				return resourceCulture;
			}
			set
			{
				resourceCulture = value;
			}
		}

		internal static byte[] VoidanesGuns
		{
			get
			{
				object obj = ResourceManager.GetObject("VoidanesGuns", resourceCulture);
				return (byte[])obj;
			}
		}

		internal Assets()
		{
		}
	}
	internal static class Compat
	{
		public static T As<T>(this object obj) where T : class
		{
			return obj as T;
		}

		public static string LocalPlayerId()
		{
			//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)
			try
			{
				return ((object)SteamUser.GetSteamID()/*cast due to .constrained prefix*/).ToString();
			}
			catch
			{
				return "unknown";
			}
		}

		public static CSteamID LobbySteamId()
		{
			//IL_001e: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			ulong num = (((Object)(object)Singleton<Lobby>.Instance != (Object)null) ? Singleton<Lobby>.Instance.LobbyID : 0);
			return new CSteamID(num);
		}
	}
	public static class Config
	{
		public static string folderPath = "UserData/MoreGuns.cfg";

		public const string PREFIX = "MoreGuns";

		public static MelonPreferences_Category Category { get; private set; }

		public static MelonPreferences_Entry<bool> EnableCrosshairForGuns { get; private set; }

		public static MelonPreferences_Entry<bool> AllowMinigunManualReload { get; private set; }

		public static void Initialize()
		{
			Category = MelonPreferences.CreateCategory("MoreGuns-! User Settings");
			EnableCrosshairForGuns = Category.CreateEntry<bool>("Allow Gun Crosshair", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			AllowMinigunManualReload = Category.CreateEntry<bool>("Allow Minigun Manual Reload", true, (string)null, "If false, the MiniGun can only be reloaded by talking to Stan.", false, false, (ValueValidator)null, (string)null);
			Category.SetFilePath(folderPath);
			Category.SaveToFile(true);
		}
	}
	internal static class GameAccess
	{
		private static readonly Dictionary<(Type Type, string Name), MemberInfo> MemberCache = new Dictionary<(Type, string), MemberInfo>();

		private static readonly Dictionary<(Type Type, string Name, int ArgCount), MethodInfo> MethodCache = new Dictionary<(Type, string, int), MethodInfo>();

		private const BindingFlags Flags = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		public static void Call(object instance, string method, params object[] args)
		{
			if (instance != null)
			{
				FindMethod(instance.GetType(), method, (args != null) ? args.Length : 0)?.Invoke(instance, args);
			}
		}

		public static T Call<T>(object instance, string method, params object[] args)
		{
			if (instance == null)
			{
				return default(T);
			}
			return (FindMethod(instance.GetType(), method, (args != null) ? args.Length : 0)?.Invoke(instance, args) is T val) ? val : default(T);
		}

		public static void Set(object instance, string member, object value)
		{
			if (instance == null)
			{
				return;
			}
			MemberInfo memberInfo = ResolveMember(instance.GetType(), member);
			MemberInfo memberInfo2 = memberInfo;
			if (!(memberInfo2 is FieldInfo fieldInfo))
			{
				if (memberInfo2 is PropertyInfo { CanWrite: not false } propertyInfo)
				{
					propertyInfo.SetValue(instance, value);
				}
			}
			else
			{
				fieldInfo.SetValue(instance, value);
			}
		}

		public static T Get<T>(object instance, string member)
		{
			if (instance == null)
			{
				return default(T);
			}
			MemberInfo memberInfo = ResolveMember(instance.GetType(), member);
			MemberInfo memberInfo2 = memberInfo;
			if (!(memberInfo2 is FieldInfo fieldInfo))
			{
				if (memberInfo2 is PropertyInfo { CanRead: not false } propertyInfo)
				{
					return (propertyInfo.GetValue(instance) is T val) ? val : default(T);
				}
				return default(T);
			}
			return (fieldInfo.GetValue(instance) is T val2) ? val2 : default(T);
		}

		public static bool CanFire(Equippable_RangedWeapon weapon, bool checkAmmo)
		{
			return Call<bool>(weapon, "CanFire", new object[1] { checkAmmo });
		}

		public static void Cock(Equippable_RangedWeapon weapon)
		{
			Call(weapon, "Cock");
		}

		public static void Recalculate(FloatStack stack)
		{
			Call(stack, "Recalculate");
		}

		public static void SetCurrentEquippable(object avatar, AvatarEquippable equippable)
		{
			Set(avatar, "CurrentEquippable", equippable);
		}

		public static void CreateListingUI(ShopInterface shop, ShopListing listing)
		{
			Call(shop, "CreateListingUI", listing);
		}

		public static void RefreshShownItems(ShopInterface shop)
		{
			Call(shop, "RefreshShownItems");
		}

		private static MemberInfo ResolveMember(Type type, string name)
		{
			(Type, string) key = (type, name);
			if (MemberCache.TryGetValue(key, out var value))
			{
				return value;
			}
			MemberInfo memberInfo = FindOnType(type, name);
			if (memberInfo == null && type.BaseType != null)
			{
				memberInfo = FindOnType(type.BaseType, name);
			}
			MemberCache[key] = memberInfo;
			return memberInfo;
		}

		private static MemberInfo FindOnType(Type type, string name)
		{
			PropertyInfo propertyInfo = type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetProperty(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
			if (propertyInfo != null)
			{
				return propertyInfo;
			}
			return type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField(name, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
		}

		private static MethodInfo FindMethod(Type type, string name, int argCount)
		{
			(Type, string, int) key = (type, name, argCount);
			if (MethodCache.TryGetValue(key, out var value))
			{
				return value;
			}
			MethodInfo methodInfo = MatchMethod(type, name, argCount);
			if (methodInfo == null && type.BaseType != null)
			{
				methodInfo = MatchMethod(type.BaseType, name, argCount);
			}
			MethodCache[key] = methodInfo;
			return methodInfo;
		}

		private static MethodInfo MatchMethod(Type type, string name, int argCount)
		{
			MethodInfo[] methods = type.GetMethods(BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
			foreach (MethodInfo methodInfo in methods)
			{
				if (string.Equals(methodInfo.Name, name, StringComparison.OrdinalIgnoreCase) && methodInfo.GetParameters().Length == argCount)
				{
					return methodInfo;
				}
			}
			return null;
		}
	}
	public class GunConfiguration
	{
		public static string folderPath = "UserData/MoreGuns.cfg";

		public string ID { get; private set; }

		public MelonPreferences_Category Category { get; private set; }

		public MelonPreferences_Entry<float> Damage { get; private set; }

		public MelonPreferences_Entry<float> ImpactForce { get; private set; }

		public MelonPreferences_Entry<float> MinAimFOVReduction { get; private set; }

		public MelonPreferences_Entry<float> MaxAimFOVReduction { get; private set; }

		public MelonPreferences_Entry<float> AccuracyChangeDuration { get; private set; }

		public MelonPreferences_Entry<int> MagazineSize { get; private set; }

		public MelonPreferences_Entry<string> DisplayItemName { get; private set; }

		public MelonPreferences_Entry<string> DisplayDescription { get; private set; }

		public MelonPreferences_Entry<ELegalStatus> LegalStatus { get; private set; }

		public MelonPreferences_Entry<FullRank> RequiredRank { get; private set; }

		public MelonPreferences_Entry<string> MagDisplayItemName { get; private set; }

		public MelonPreferences_Entry<string> MagDisplayDescription { get; private set; }

		public MelonPreferences_Entry<ELegalStatus> MagLegalStatus { get; private set; }

		public MelonPreferences_Entry<FullRank> MagRequiredRank { get; private set; }

		public MelonPreferences_Entry<float> PurchasePrice { get; private set; }

		public MelonPreferences_Entry<float> MagPurchasePrice { get; private set; }

		public MelonPreferences_Entry<string> ItemName { get; private set; }

		public MelonPreferences_Entry<string> MagItemName { get; private set; }

		public MelonPreferences_Entry<bool> Available { get; private set; }

		public MelonPreferences_Entry<bool> MagAvailable { get; private set; }

		public MelonPreferences_Entry<string> AvailableReason { get; private set; }

		public MelonPreferences_Entry<string> MagAvailableReason { get; private set; }

		public event Action OnSettingChanged;

		public GunConfiguration(WeaponBase weapon)
		{
			ID = weapon.ID;
			string text = "MoreGuns-" + ID + " Settings";
			string text2 = ID + " Settings";
			Category = MelonPreferences.CreateCategory(text, text2);
			InitializePreferences(ID, weapon);
			Category.SetFilePath(folderPath);
			Category.SaveToFile(true);
			MelonLogger.Msg("Loaded configuration for " + ID + " from: " + folderPath);
		}

		private void InitializePreferences(string ID, WeaponBase weapon)
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			Equippable_RangedWeapon gunRangedWeapon = weapon.gunRangedWeapon;
			Damage = Category.CreateEntry<float>(ID + " Damage", gunRangedWeapon.Damage, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			ImpactForce = Category.CreateEntry<float>(ID + " Impact Force", gunRangedWeapon.ImpactForce, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MinAimFOVReduction = Category.CreateEntry<float>(ID + " Min Aim FOV Reduction", gunRangedWeapon.MinAimFOVReduction, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MaxAimFOVReduction = Category.CreateEntry<float>(ID + " Max Aim FOV Reduction", gunRangedWeapon.MaxAimFOVReduction, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			AccuracyChangeDuration = Category.CreateEntry<float>(ID + " Accuracy Change Duration", gunRangedWeapon.AccuracyChangeDuration, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MagazineSize = Category.CreateEntry<int>(ID + " Magazine Size", gunRangedWeapon.MagazineSize, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			IntegerItemDefinition gunIntItemDef = weapon.gunIntItemDef;
			DisplayItemName = Category.CreateEntry<string>(ID + " Display Name", ((BaseItemDefinition)gunIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			DisplayDescription = Category.CreateEntry<string>(ID + " Display Description", ((BaseItemDefinition)gunIntItemDef).Description, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			LegalStatus = Category.CreateEntry<ELegalStatus>(ID + " Legal Status", ((BaseItemDefinition)gunIntItemDef).legalStatus, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			RequiredRank = Category.CreateEntry<FullRank>(ID + " Required Rank", ((StorableItemDefinition)gunIntItemDef).RequiredRank, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			IntegerItemDefinition magIntItemDef = weapon.magIntItemDef;
			MagDisplayItemName = Category.CreateEntry<string>(ID + " Mag Display Name", ((BaseItemDefinition)magIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MagDisplayDescription = Category.CreateEntry<string>(ID + " Mag Display Description", ((BaseItemDefinition)magIntItemDef).Description, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MagLegalStatus = Category.CreateEntry<ELegalStatus>(ID + " Mag Legal Status", (ELegalStatus)0, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MagRequiredRank = Category.CreateEntry<FullRank>(ID + " Mag Required Rank", ((StorableItemDefinition)magIntItemDef).RequiredRank, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			PurchasePrice = Category.CreateEntry<float>(ID + " Price", ((StorableItemDefinition)gunIntItemDef).BasePurchasePrice, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			ItemName = Category.CreateEntry<string>(ID + " Name", ((BaseItemDefinition)gunIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			Available = Category.CreateEntry<bool>(ID + " Shop Availability", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			AvailableReason = Category.CreateEntry<string>(ID + " Non-Available Reason", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MagPurchasePrice = Category.CreateEntry<float>(ID + " Magazine Price", ((StorableItemDefinition)magIntItemDef).BasePurchasePrice, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MagItemName = Category.CreateEntry<string>(ID + " Magazine Name", ((BaseItemDefinition)magIntItemDef).Name, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MagAvailable = Category.CreateEntry<bool>(ID + " Magazine Shop Availability", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			MagAvailableReason = Category.CreateEntry<string>(ID + " Magazine Non-Available Reason", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		}

		public void HandleSettingsUpdate()
		{
			MelonLogger.Msg("Updating More Guns Settings");
			Category.LoadFromFile(true);
			this.OnSettingChanged?.Invoke();
		}
	}
	internal static class MagazineSocketFix
	{
		private static readonly HashSet<int> LeftoverAkMagazineMeshIds = new HashSet<int>();

		public static void CacheLeftoverMeshesFromGun(GameObject root)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || ((Object)val).name != "Magazine" || ((Component)val).gameObject.activeSelf)
				{
					continue;
				}
				Vector3 localScale = val.localScale;
				Vector3 localPosition = val.localPosition;
				if ((!(localScale.x >= 5f) || !(localScale.x < 40f)) && !(Mathf.Abs(localPosition.z) > 1f) && !(Mathf.Abs(localPosition.x) > 1.5f) && (!(localScale.x > 0f) || !(localScale.x < 0.05f)))
				{
					continue;
				}
				MeshFilter[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<MeshFilter>(true);
				foreach (MeshFilter obj in componentsInChildren2)
				{
					Mesh val2 = ((obj != null) ? obj.sharedMesh : null);
					if ((Object)(object)val2 != (Object)null)
					{
						LeftoverAkMagazineMeshIds.Add(((Object)val2).GetInstanceID());
					}
				}
			}
		}

		[Obsolete("Use CacheLeftoverMeshesFromGun on smg/sniper/rpg instead.")]
		public static void CacheAkMagazineMeshes(GameObject akRoot)
		{
		}

		public static void FixGunHierarchy(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			string text = ((Object)root).name ?? "";
			if (IsAkRootName(text))
			{
				return;
			}
			bool flag = text.IndexOf("rpg", StringComparison.OrdinalIgnoreCase) >= 0;
			Transform[] componentsInChildren;
			try
			{
				componentsInChildren = root.GetComponentsInChildren<Transform>(true);
			}
			catch
			{
				return;
			}
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (((Object)val).name == "MagazineMesh")
				{
					try
					{
						Object.Destroy((Object)(object)((Component)val).gameObject);
					}
					catch
					{
					}
				}
				else
				{
					if (((Object)val).name != "Magazine")
					{
						continue;
					}
					if (flag)
					{
						if (!IsRpgAkLeftover(val))
						{
							continue;
						}
					}
					else if (!IsLegacyAkMagazine(val))
					{
						continue;
					}
					try
					{
						Object.Destroy((Object)(object)((Component)val).gameObject);
					}
					catch
					{
						((Component)val).gameObject.SetActive(false);
						DisableRenderers(val);
					}
				}
			}
			StripReloadClips(root);
		}

		private static bool IsAkRootName(string rootName)
		{
			return rootName.IndexOf("ak47", StringComparison.OrdinalIgnoreCase) >= 0 || rootName.Equals("AK47", StringComparison.OrdinalIgnoreCase) || rootName.Equals("K47", StringComparison.OrdinalIgnoreCase) || rootName.IndexOf("AK47_", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static bool IsRpgAkLeftover(Transform magazine)
		{
			//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)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (((Component)magazine).gameObject.activeSelf)
			{
				return false;
			}
			Vector3 localScale = magazine.localScale;
			if (localScale.x >= 40f)
			{
				return false;
			}
			if (localScale.x > 0f && localScale.x < 0.05f)
			{
				return true;
			}
			MeshFilter[] componentsInChildren = ((Component)magazine).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter obj in componentsInChildren)
			{
				Mesh val = ((obj != null) ? obj.sharedMesh : null);
				if (!((Object)(object)val == (Object)null))
				{
					if (LeftoverAkMagazineMeshIds.Contains(((Object)val).GetInstanceID()))
					{
						return true;
					}
					string text = ((Object)val).name ?? "";
					if (text.IndexOf("AK", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool IsLegacyAkMagazine(Transform magazine)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			Vector3 localScale = magazine.localScale;
			Vector3 localPosition = magazine.localPosition;
			if ((localScale.x >= 5f && localScale.x < 40f) || (localScale.y >= 5f && localScale.y < 40f) || (localScale.z >= 5f && localScale.z < 40f) || Mathf.Abs(localPosition.z) > 1f || Mathf.Abs(localPosition.x) > 1.5f)
			{
				return true;
			}
			if (((Component)magazine).gameObject.activeSelf)
			{
				return false;
			}
			MeshFilter[] componentsInChildren = ((Component)magazine).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter obj in componentsInChildren)
			{
				Mesh val = ((obj != null) ? obj.sharedMesh : null);
				if (!((Object)(object)val == (Object)null))
				{
					if (LeftoverAkMagazineMeshIds.Contains(((Object)val).GetInstanceID()))
					{
						return true;
					}
					string text = ((Object)val).name ?? "";
					if (text.IndexOf("AK", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return true;
					}
				}
			}
			if (localScale.x > 0f && localScale.x < 0.05f)
			{
				foreach (MeshFilter obj2 in componentsInChildren)
				{
					if ((Object)(object)((obj2 != null) ? obj2.sharedMesh : null) != (Object)null)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static void DisableRenderers(Transform root)
		{
			Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					componentsInChildren[i].enabled = false;
				}
			}
		}

		private static void StripReloadClips(GameObject root)
		{
			try
			{
				Animation[] componentsInChildren = root.GetComponentsInChildren<Animation>(true);
				foreach (Animation val in componentsInChildren)
				{
					if (!((Object)(object)val == (Object)null))
					{
						TryRemoveClip(val, "Other Reload");
						TryRemoveClip(val, "OtherReload");
						TryRemoveClip(val, "AK47 Reload");
						TryRemoveClip(val, "AK47Reload");
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("StripReloadClips: " + ex.Message);
			}
		}

		private static void TryRemoveClip(Animation anim, string clipName)
		{
			try
			{
				AnimationClip clip = anim.GetClip(clipName);
				if ((Object)(object)clip != (Object)null)
				{
					anim.RemoveClip(clip);
				}
			}
			catch
			{
			}
		}
	}
	internal static class ManualReload
	{
		public static bool TryReload(Equippable_RangedWeapon weapon, WeaponBase source = null, bool useGunReloadAnim = true)
		{
			if ((Object)(object)weapon == (Object)null)
			{
				return false;
			}
			if (source == null)
			{
				source = GunSettings.ResolveWeaponBase(weapon);
			}
			try
			{
				try
				{
					if (weapon.IsReloading)
					{
						GameAccess.Set(weapon, "IsReloading", false);
					}
				}
				catch
				{
				}
				IntegerItemInstance val = ResolveGunAmmo(weapon);
				if (val == null)
				{
					MelonLogger.Warning("ManualReload: no IntegerItemInstance on equipped weapon.");
					return false;
				}
				int num = Mathf.Max(1, weapon.MagazineSize);
				if (source != null && source.config != null)
				{
					num = Mathf.Max(num, source.config.MagazineSize.Value);
				}
				if (val.Value >= num)
				{
					return true;
				}
				string text = ResolveMagazineId(weapon, source);
				if (string.IsNullOrEmpty(text))
				{
					MelonLogger.Warning("ManualReload: magazine ID is missing.");
					return false;
				}
				if (!TryFindMagazine(text, out var slot, out var magAmmo))
				{
					return false;
				}
				int value = magAmmo.Value;
				if (value <= 0)
				{
					return false;
				}
				int take = Mathf.Min(num - val.Value, value);
				float seconds = 2.5f;
				try
				{
					if (weapon.ReloadStartTime > 0.2f)
					{
						seconds = weapon.ReloadStartTime;
					}
				}
				catch
				{
				}
				MelonCoroutines.Start(ReloadRoutine(weapon, source, val, slot, magAmmo, take, num, seconds, useGunReloadAnim));
				return true;
			}
			catch (Exception value2)
			{
				MelonLogger.Error($"ManualReload failed: {value2}");
				return false;
			}
		}

		private static IEnumerator ReloadRoutine(Equippable_RangedWeapon weapon, WeaponBase source, IntegerItemInstance gunAmmo, ItemSlot magSlot, IntegerItemInstance magAmmo, int take, int capacity, float seconds, bool useGunReloadAnim)
		{
			try
			{
				GameAccess.Set(weapon, "IsReloading", true);
			}
			catch
			{
			}
			PlayReloadFeedback(weapon, source, useGunReloadAnim);
			float wait = Mathf.Clamp(seconds, 0.5f, 5f);
			bool isAk = source != null && string.Equals(source.ID, "ak47", StringComparison.OrdinalIgnoreCase);
			if (useGunReloadAnim && !isAk)
			{
				yield return AnimateSeatedMagazine(weapon, wait);
			}
			else
			{
				yield return (object)new WaitForSeconds(wait);
			}
			if ((Object)(object)weapon == (Object)null || gunAmmo == null || magAmmo == null)
			{
				try
				{
					if ((Object)(object)weapon != (Object)null)
					{
						GameAccess.Set(weapon, "IsReloading", false);
					}
					yield break;
				}
				catch
				{
					yield break;
				}
			}
			try
			{
				int newAmmo = Mathf.Min(capacity, gunAmmo.Value + take);
				int actuallyTook = newAmmo - gunAmmo.Value;
				if (actuallyTook <= 0)
				{
					try
					{
						GameAccess.Set(weapon, "IsReloading", false);
						yield break;
					}
					catch
					{
						yield break;
					}
				}
				gunAmmo.SetValue(newAmmo);
				try
				{
					gunAmmo.Value = newAmmo;
				}
				catch
				{
				}
				int left = magAmmo.Value - actuallyTook;
				bool emptiedMag = false;
				if (left <= 0)
				{
					emptiedMag = true;
					magAmmo.SetValue(0);
					try
					{
						magAmmo.Value = 0;
					}
					catch
					{
					}
					try
					{
						((BaseItemInstance)magSlot.ItemInstance).ChangeQuantity(-1);
					}
					catch
					{
						try
						{
							magSlot.ChangeQuantity(-1, false);
						}
						catch (Exception ex)
						{
							Exception ex2 = ex;
							MelonLogger.Warning("ManualReload: could not remove empty mag: " + ex2.Message);
						}
					}
				}
				else
				{
					magAmmo.SetValue(left);
					try
					{
						magAmmo.Value = left;
					}
					catch
					{
					}
				}
				if (emptiedMag)
				{
					SpawnTrashSafe(weapon, source);
				}
				if (weapon.MustBeCocked && weapon.AutoCockAfterReload)
				{
					try
					{
						GameAccess.Set(weapon, "IsCocked", true);
					}
					catch
					{
					}
					try
					{
						GameAccess.Set(weapon, "IsCocking", false);
					}
					catch
					{
					}
				}
				GunSettings settings = ((Component)weapon).GetComponent<GunSettings>();
				if ((Object)(object)settings != (Object)null && settings.SyncMagazineToAmmo)
				{
					WeaponBehavior.SyncMagazineVisualToAmmo(weapon);
				}
			}
			catch (Exception ex)
			{
				Exception ex3 = ex;
				MelonLogger.Error($"ManualReload apply failed: {ex3}");
			}
			finally
			{
				try
				{
					GameAccess.Set(weapon, "IsReloading", false);
				}
				catch
				{
				}
			}
		}

		private static void PlayReloadFeedback(Equippable_RangedWeapon weapon, WeaponBase source, bool useGunReloadAnim)
		{
			if (useGunReloadAnim)
			{
				if (source != null && string.Equals(source.ID, "ak47", StringComparison.OrdinalIgnoreCase))
				{
					try
					{
						if (weapon.onReloadStart != null)
						{
							weapon.onReloadStart.Invoke();
						}
					}
					catch (Exception)
					{
						PlayGunReloadClip(weapon);
						PlayReloadSound(weapon);
					}
				}
				else
				{
					try
					{
						MagazineSocketFix.FixGunHierarchy(((Component)weapon).gameObject);
					}
					catch
					{
					}
					StopGunAnimation(weapon);
					PlayReloadSound(weapon);
				}
			}
			else
			{
				PlayReloadSound(weapon);
			}
			string text = null;
			try
			{
				text = weapon.ReloadStartAnimTrigger;
			}
			catch
			{
			}
			if (string.IsNullOrEmpty(text))
			{
				text = "MagazineReload";
			}
			try
			{
				ViewmodelAvatar instance = Singleton<ViewmodelAvatar>.Instance;
				if ((Object)(object)instance?.Animator != (Object)null)
				{
					instance.Animator.SetTrigger(text);
				}
			}
			catch
			{
			}
			try
			{
				Player local = Player.Local;
				if ((Object)(object)local != (Object)null)
				{
					local.SetAnimationTrigger(text);
					try
					{
						local.SendAnimationTrigger(text);
						return;
					}
					catch
					{
						return;
					}
				}
			}
			catch
			{
			}
		}

		private static void PlayReloadSound(Equippable_RangedWeapon weapon)
		{
			try
			{
				Transform val = FindDeep(((Component)weapon).transform, "Reload Sound");
				if ((Object)(object)val != (Object)null)
				{
					AudioSourceController component = ((Component)val).GetComponent<AudioSourceController>();
					if ((Object)(object)component != (Object)null)
					{
						component.Play();
					}
				}
			}
			catch
			{
			}
		}

		private static void StopGunAnimation(Equippable_RangedWeapon weapon)
		{
			try
			{
				Animation[] componentsInChildren = ((Component)weapon).GetComponentsInChildren<Animation>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] != (Object)null && componentsInChildren[i].isPlaying)
					{
						componentsInChildren[i].Stop();
					}
				}
			}
			catch
			{
			}
		}

		private static IEnumerator AnimateSeatedMagazine(Equippable_RangedWeapon weapon, float seconds)
		{
			Transform mag = null;
			Vector3 homePos = Vector3.zero;
			Quaternion homeRot = Quaternion.identity;
			Vector3 homeScale = Vector3.one;
			try
			{
				MagazineSocketFix.FixGunHierarchy(((Component)weapon).gameObject);
				mag = FindSeatedMagazine(weapon);
				if ((Object)(object)mag != (Object)null)
				{
					homePos = mag.localPosition;
					homeRot = mag.localRotation;
					homeScale = mag.localScale;
				}
			}
			catch (Exception)
			{
			}
			if ((Object)(object)mag == (Object)null)
			{
				yield return (object)new WaitForSeconds(seconds);
				yield break;
			}
			float drop = Mathf.Clamp(0.22f + homeScale.y * 0.5f, 0.15f, 0.45f);
			Vector3 ejected = homePos + new Vector3(0f, 0f - drop, 0f);
			float outTime = seconds * 0.32f;
			float holdTime = seconds * 0.2f;
			float naturalIn = Mathf.Max(0.2f, seconds - outTime - holdTime);
			float inTime = Mathf.Max(0.12f, naturalIn * 0.5f);
			float padAfter = Mathf.Max(0f, naturalIn - inTime);
			float t = 0f;
			while (t < outTime && (Object)(object)mag != (Object)null)
			{
				t += Time.deltaTime;
				float u = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(t / outTime));
				mag.localPosition = Vector3.Lerp(homePos, ejected, u);
				yield return null;
			}
			if ((Object)(object)mag != (Object)null)
			{
				mag.localPosition = ejected;
				((Component)mag).gameObject.SetActive(false);
			}
			yield return (object)new WaitForSeconds(holdTime);
			if ((Object)(object)mag != (Object)null)
			{
				mag.localPosition = ejected;
				mag.localScale = homeScale;
				mag.localRotation = homeRot;
				((Component)mag).gameObject.SetActive(true);
			}
			t = 0f;
			while (t < inTime && (Object)(object)mag != (Object)null)
			{
				t += Time.deltaTime;
				float u2 = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(t / inTime));
				mag.localPosition = Vector3.Lerp(ejected, homePos, u2);
				yield return null;
			}
			if ((Object)(object)mag != (Object)null)
			{
				mag.localPosition = homePos;
				mag.localRotation = homeRot;
				mag.localScale = homeScale;
				((Component)mag).gameObject.SetActive(true);
			}
			if (padAfter > 0.01f)
			{
				yield return (object)new WaitForSeconds(padAfter);
			}
		}

		private static Transform FindSeatedMagazine(Equippable_RangedWeapon weapon)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)weapon == (Object)null)
			{
				return null;
			}
			Transform result = null;
			float num = float.MaxValue;
			Transform[] componentsInChildren = ((Component)weapon).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || ((Object)val).name != "Magazine")
				{
					continue;
				}
				Vector3 localScale = val.localScale;
				Vector3 localPosition = val.localPosition;
				if (!(localScale.x >= 5f) && !(localScale.y >= 5f) && !(localScale.z >= 5f) && !(Mathf.Abs(localPosition.z) > 1f) && !(Mathf.Abs(localPosition.x) > 1.5f) && (!((Object)(object)((Component)val).GetComponent<MeshFilter>() == (Object)null) || !((Object)(object)((Component)val).GetComponentInChildren<MeshFilter>(true) == (Object)null)))
				{
					float num2 = ((Vector3)(ref localPosition)).sqrMagnitude + (((Component)val).gameObject.activeSelf ? 0f : 100f);
					if (num2 < num)
					{
						num = num2;
						result = val;
					}
				}
			}
			return result;
		}

		private static void PlayGunReloadClip(Equippable_RangedWeapon weapon)
		{
			try
			{
				string[] array = new string[3] { "AK47 Reload", "Other Reload", "Reload" };
				Animation[] componentsInChildren = ((Component)weapon).GetComponentsInChildren<Animation>(true);
				foreach (Animation val in componentsInChildren)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					for (int j = 0; j < array.Length; j++)
					{
						if (!((Object)(object)val.GetClip(array[j]) == (Object)null))
						{
							val.Play(array[j]);
							return;
						}
					}
				}
				PlayAnimation componentInChildren = ((Component)weapon).GetComponentInChildren<PlayAnimation>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.Play("AK47 Reload");
				}
			}
			catch
			{
			}
		}

		private static string ResolveMagazineId(Equippable_RangedWeapon weapon, WeaponBase source)
		{
			try
			{
				if ((Object)(object)weapon.Magazine != (Object)null && !string.IsNullOrEmpty(((BaseItemDefinition)weapon.Magazine).ID))
				{
					return ((BaseItemDefinition)weapon.Magazine).ID;
				}
			}
			catch
			{
			}
			if ((Object)(object)source?.magIntItemDef != (Object)null && !string.IsNullOrEmpty(((BaseItemDefinition)source.magIntItemDef).ID))
			{
				return ((BaseItemDefinition)source.magIntItemDef).ID;
			}
			if (source != null && !string.IsNullOrEmpty(source.ID))
			{
				return source.ID + "mag";
			}
			return null;
		}

		private static void SpawnTrashSafe(Equippable_RangedWeapon weapon, WeaponBase source)
		{
			//IL_00a2: 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_00b7: 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_00c1: 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)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PlayerCamera instance = PlayerSingleton<PlayerCamera>.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return;
				}
				TrashItem val = ResolveTrashPrefab(weapon, source);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				if (source != null)
				{
					TrashRegistryPatch.EnsureTrashId(source);
				}
				if ((string.IsNullOrEmpty(val.ID) || string.Equals(val.ID, "trashid", StringComparison.OrdinalIgnoreCase)) && source != null && !string.IsNullOrEmpty(source.ID))
				{
					val.ID = source.ID + "mag";
				}
				Vector3 val2 = ((Component)instance).transform.position - ((Component)instance).transform.up * 0.4f;
				try
				{
					Object.Instantiate<GameObject>(((Component)val).gameObject, val2, Random.rotation);
				}
				catch
				{
				}
			}
			catch
			{
			}
		}

		private static TrashItem ResolveTrashPrefab(Equippable_RangedWeapon weapon, WeaponBase source)
		{
			try
			{
				TrashItem reloadTrash = weapon.ReloadTrash;
				if ((Object)(object)reloadTrash != (Object)null)
				{
					return reloadTrash;
				}
			}
			catch
			{
			}
			return source?.gunMagTrashItem;
		}

		private static Transform FindDeep(Transform root, string name)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			if (((Object)root).name == name)
			{
				return root;
			}
			for (int i = 0; i < root.childCount; i++)
			{
				Transform val = FindDeep(root.GetChild(i), name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static IntegerItemInstance ResolveGunAmmo(Equippable_RangedWeapon weapon)
		{
			return GameAccess.Get<IntegerItemInstance>(weapon, "weaponItem");
		}

		private static bool TryFindMagazine(string magId, out ItemSlot slot, out IntegerItemInstance magAmmo)
		{
			slot = null;
			magAmmo = null;
			PlayerInventory instance = PlayerSingleton<PlayerInventory>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			if (instance.hotbarSlots != null)
			{
				for (int i = 0; i < instance.hotbarSlots.Count; i++)
				{
					if (MatchSlot((ItemSlot)(object)instance.hotbarSlots[i], magId, out slot, out magAmmo))
					{
						return true;
					}
				}
			}
			try
			{
				List<ItemSlot> allInventorySlots = instance.GetAllInventorySlots();
				if (allInventorySlots != null)
				{
					for (int j = 0; j < allInventorySlots.Count; j++)
					{
						if (MatchSlot(allInventorySlots[j], magId, out slot, out magAmmo))
						{
							return true;
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool MatchSlot(ItemSlot s, string magId, out ItemSlot slot, out IntegerItemInstance magAmmo)
		{
			slot = null;
			magAmmo = null;
			ItemInstance val = ((s != null) ? s.ItemInstance : null);
			if ((Object)(object)((val != null) ? val.Definition : null) == (Object)null)
			{
				return false;
			}
			if (!string.Equals(((BaseItemDefinition)val.Definition).ID, magId, StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			IntegerItemInstance val2 = val.As<IntegerItemInstance>();
			if (val2 == null)
			{
				return false;
			}
			slot = s;
			magAmmo = val2;
			return true;
		}
	}
	internal static class MaterialFixup
	{
		private static Shader _lit;

		private static Shader _unlit;

		private static Shader _particles;

		private static bool _resolved;

		public static void FixHierarchy(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			EnsureShaders();
			if ((Object)(object)_lit == (Object)null && (Object)(object)_unlit == (Object)null && (Object)(object)_particles == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren;
			try
			{
				componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("MaterialFixup: could not read renderers on " + ((Object)root).name + ": " + ex.Message);
				return;
			}
			if (componentsInChildren == null)
			{
				return;
			}
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				try
				{
					Material[] sharedMaterials = val.sharedMaterials;
					if (sharedMaterials == null || sharedMaterials.Length == 0)
					{
						continue;
					}
					bool flag = false;
					foreach (Material val2 in sharedMaterials)
					{
						if ((Object)(object)val2 == (Object)null)
						{
							continue;
						}
						try
						{
							if (FixMaterial(val2))
							{
								flag = true;
							}
						}
						catch (Exception ex2)
						{
							MelonLogger.Warning("MaterialFixup: skipped '" + ((Object)val2).name + "': " + ex2.Message);
						}
					}
					if (flag)
					{
						val.sharedMaterials = sharedMaterials;
					}
				}
				catch (Exception ex3)
				{
					MelonLogger.Warning("MaterialFixup: renderer '" + ((Object)val).name + "' failed: " + ex3.Message);
				}
			}
		}

		private static void EnsureShaders()
		{
			if (!_resolved)
			{
				_resolved = true;
				_lit = Shader.Find("Universal Render Pipeline/Lit");
				_unlit = Shader.Find("Universal Render Pipeline/Unlit");
				_particles = Shader.Find("Universal Render Pipeline/Particles/Unlit") ?? Shader.Find("Universal Render Pipeline/Particles/Simple Lit");
				if ((Object)(object)_lit == (Object)null && (Object)(object)_unlit == (Object)null)
				{
					MelonLogger.Warning("Could not find URP Lit/Unlit shaders; gun materials may stay transparent.");
				}
			}
		}

		private static bool FixMaterial(Material mat)
		{
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: 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_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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)
			//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_0130: 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)
			string text = ((Object)mat).name ?? string.Empty;
			string text2 = text.ToLowerInvariant();
			bool flag = text2.Contains("particle") || text2.Contains("muzzle") || text2.Contains("flash") || text2.Contains("smoke") || text2.Contains("tracer") || text2.Contains("ray");
			bool flag2 = text2.Contains("glass");
			Shader val = (flag ? (_particles ?? _unlit ?? _lit) : ((!flag2) ? (_lit ?? _unlit) : (_lit ?? _unlit)));
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Texture val2 = GetTexture(mat, "_BaseMap") ?? GetTexture(mat, "_MainTex");
			Color val3 = Color.white;
			try
			{
				if (mat.HasProperty("_BaseColor"))
				{
					val3 = mat.GetColor("_BaseColor");
				}
				else if (mat.HasProperty("_Color"))
				{
					val3 = mat.GetColor("_Color");
				}
			}
			catch
			{
				val3 = Color.white;
			}
			mat.shader = val;
			if ((Object)(object)val2 != (Object)null)
			{
				if (mat.HasProperty("_BaseMap"))
				{
					mat.SetTexture("_BaseMap", val2);
				}
				if (mat.HasProperty("_MainTex"))
				{
					mat.SetTexture("_MainTex", val2);
				}
			}
			if (mat.HasProperty("_BaseColor"))
			{
				mat.SetColor("_BaseColor", val3);
			}
			if (mat.HasProperty("_Color"))
			{
				mat.SetColor("_Color", val3);
			}
			if (flag)
			{
				SetSurfaceTransparent(mat);
				if (mat.HasProperty("_Blend"))
				{
					mat.SetFloat("_Blend", 0f);
				}
				if (mat.HasProperty("_Cutoff"))
				{
					mat.SetFloat("_Cutoff", 0.1f);
				}
			}
			else if (!flag2)
			{
				SetSurfaceOpaque(mat);
			}
			return true;
		}

		private static Texture GetTexture(Material mat, string property)
		{
			try
			{
				return mat.HasProperty(property) ? mat.GetTexture(property) : null;
			}
			catch
			{
				return null;
			}
		}

		private static void SetSurfaceOpaque(Material mat)
		{
			if (mat.HasProperty("_Surface"))
			{
				mat.SetFloat("_Surface", 0f);
			}
			mat.DisableKeyword("_SURFACE_TYPE_TRANSPARENT");
			mat.SetOverrideTag("RenderType", "Opaque");
			mat.renderQueue = 2000;
			if (mat.HasProperty("_ZWrite"))
			{
				mat.SetFloat("_ZWrite", 1f);
			}
		}

		private static void SetSurfaceTransparent(Material mat)
		{
			if (mat.HasProperty("_Surface"))
			{
				mat.SetFloat("_Surface", 1f);
			}
			mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
			mat.SetOverrideTag("RenderType", "Transparent");
			mat.renderQueue = 3000;
			if (mat.HasProperty("_ZWrite"))
			{
				mat.SetFloat("_ZWrite", 0f);
			}
		}
	}
	public class MoreGunsMod : MelonMod
	{
		public static Transform map;

		public static Transform container;

		public static Transform midcanal;

		public static Transform stanNPC;

		public static AssetBundle assetBundle;

		public static readonly Dictionary<string, Object> Resources = new Dictionary<string, Object>(StringComparer.OrdinalIgnoreCase);

		public static bool isInitialized;

		public static Harmony harmony;

		private static bool harmonyApplied;

		private static bool bootStarted;

		private static readonly Dictionary<string, RuntimeAnimatorController> animatorControllers = new Dictionary<string, RuntimeAnimatorController>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, Sprite> sprites = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase);

		private static bool animatorControllersLoaded;

		private static bool spritesLoaded;

		public override void OnInitializeMelon()
		{
			MelonLogger.Msg("Thank you for using More Guns! Discord: discord.gg/XB7ruKtJje");
			assetBundle = AssetBundle.LoadFromMemory(Assets.VoidanesGuns);
			if ((Object)(object)assetBundle == (Object)null)
			{
				MelonLogger.Error("The asset bundle could not be loaded. MoreGuns will not run.");
				isInitialized = false;
				return;
			}
			isInitialized = true;
			Config.Initialize();
			new AK47();
			new MiniGun();
			new Sniper();
			new SMG();
			new RPG();
		}

		public override void OnApplicationQuit()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (!isInitialized)
			{
				return;
			}
			if (sceneName != "Main")
			{
				ItemRegistryPatch.Reset();
				bootStarted = false;
				return;
			}
			if (!bootStarted)
			{
				bootStarted = true;
				MelonCoroutines.Start(BootAfterSaveSettles());
			}
			try
			{
				NetworkController.SyncConfiguration();
			}
			catch (Exception value)
			{
				MelonLogger.Error($"Failed to sync MoreGuns configuration: {value}");
			}
			MelonCoroutines.Start(ItemRegistryPatch.RegisterWhenReady());
			Reticle.Initialize();
			GameObject val = GameObject.Find("UI/HUD");
			if ((Object)(object)val == (Object)null)
			{
				MelonLogger.Warning("Could not find 'UI/HUD'; the reload message and windup indicator will be unavailable.");
				return;
			}
			ReloadMessage.Initialize(val.transform);
			WindupIndicator.Initialize(val.transform);
		}

		private static IEnumerator BootAfterSaveSettles()
		{
			float waited = 0f;
			while ((Object)(object)GameObject.Find("Player_Local") == (Object)null && waited < 90f)
			{
				yield return (object)new WaitForSeconds(0.25f);
				waited += 0.25f;
			}
			yield return (object)new WaitForSecondsRealtime(2.5f);
			if (!harmonyApplied)
			{
				harmony = new Harmony("com.voidane.moregunsmono");
				MelonLogger.Msg("Applying MoreGuns Harmony patches after save settle (batched)...");
				yield return SafeHarmony.ApplyBatched(harmony, typeof(ArmsDealerInterfacePatch), typeof(CameraJoltPatch), typeof(DialoguePatch), typeof(Equippalbe_RangedWeaponPatch), typeof(ItemRegistryPatch), typeof(RangedWeaponEquipPatch), typeof(ReloadingPatch), typeof(SetEquippablePatch), typeof(TrashRegistryPatch));
				harmonyApplied = true;
			}
			while (!SafeHarmony.PatchesLive)
			{
				yield return null;
			}
			MelonCoroutines.Start(ArmsDealerInterfacePatch.FindAndInjectAfterHarmony());
		}

		public static void RegisterAsset(string path, Object asset)
		{
			Resources[path] = asset;
		}

		public static Object TryGetAsset(string path)
		{
			if (path != null && Resources.TryGetValue(path, out var value))
			{
				return value;
			}
			return null;
		}

		public static Sprite GetSprite(string name)
		{
			if (string.IsNullOrEmpty(name) || (Object)(object)assetBundle == (Object)null)
			{
				return null;
			}
			EnsureSpritesLoaded();
			Sprite value;
			return sprites.TryGetValue(name, out value) ? value : null;
		}

		private static void EnsureSpritesLoaded()
		{
			if (spritesLoaded || (Object)(object)assetBundle == (Object)null)
			{
				return;
			}
			spritesLoaded = true;
			try
			{
				string[] array = new string[20]
				{
					"assets/sprite/ak47__icon.asset", "assets/sprite/ak47__magazine_icon.asset", "assets/sprite/minigun__icon.asset", "assets/sprite/minigun__magazine_icon.asset", "assets/sprite/sniper__icon.asset", "assets/sprite/sniper__magazine_icon.asset", "assets/sprite/smg__icon.asset", "assets/sprite/smg__magazine_icon.asset", "assets/sprite/rpg__icon.asset", "assets/sprite/rpg__magazine_icon.asset",
					"AK47__Icon", "AK47__Magazine_Icon", "MiniGun__Icon", "MiniGun__Magazine_Icon", "Sniper__Icon", "Sniper__Magazine_Icon", "SMG__Icon", "SMG__Magazine_Icon", "RPG__Icon", "RPG__Magazine_Icon"
				};
				string[] array2 = array;
				foreach (string text in array2)
				{
					TryCacheSprite(assetBundle.LoadAsset(text));
				}
				Object[] array3 = assetBundle.LoadAllAssets();
				if (array3 != null)
				{
					Object[] array4 = array3;
					foreach (Object asset in array4)
					{
						TryCacheSprite(asset);
					}
				}
				string[] array5 = new string[10] { "Sniper__Icon", "Sniper__Magazine_Icon", "SMG__Icon", "SMG__Magazine_Icon", "RPG__Icon", "RPG__Magazine_Icon", "AK47__Icon", "AK47__Magazine_Icon", "MiniGun__Icon", "MiniGun__Magazine_Icon" };
				string[] array6 = array5;
				foreach (string text2 in array6)
				{
					if (!sprites.ContainsKey(text2))
					{
						TryCacheSpriteFromTexture(assetBundle.LoadAsset(text2), text2);
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Failed to preload sprites: " + ex.Message);
			}
		}

		private static void TryCacheSprite(Object asset)
		{
			if (!(asset == (Object)null))
			{
				Sprite val = asset.As<Sprite>();
				if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name))
				{
					sprites[((Object)val).name] = val;
				}
			}
		}

		private static void TryCacheSpriteFromTexture(Object asset, string name)
		{
			//IL_0046: 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)
			if (!(asset == (Object)null) && !string.IsNullOrEmpty(name))
			{
				Texture2D val = asset.As<Texture2D>();
				if (!((Object)(object)val == (Object)null))
				{
					Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
					((Object)val2).name = name;
					sprites[name] = val2;
				}
			}
		}

		public static RuntimeAnimatorController GetAnimatorController(string name)
		{
			if (string.IsNullOrEmpty(name) || (Object)(object)assetBundle == (Object)null)
			{
				return null;
			}
			EnsureAnimatorControllersLoaded();
			RuntimeAnimatorController value;
			return animatorControllers.TryGetValue(name, out value) ? value : null;
		}

		private static void EnsureAnimatorControllersLoaded()
		{
			if (animatorControllersLoaded || (Object)(object)assetBundle == (Object)null)
			{
				return;
			}
			animatorControllersLoaded = true;
			try
			{
				TryLoadAnimatorByPath("assets/animatorcontroller/handgunanimator.controller", "HandgunAnimator");
				TryLoadAnimatorByPath("assets/animatorcontroller/minigunanimator.controller", "MiniGunAnimator");
				TryLoadAnimatorByPath("HandgunAnimator", "HandgunAnimator");
				TryLoadAnimatorByPath("MiniGunAnimator", "MiniGunAnimator");
				if (animatorControllers.Count != 0)
				{
					return;
				}
				Object[] array = assetBundle.LoadAllAssets();
				if (array == null)
				{
					return;
				}
				Object[] array2 = array;
				foreach (Object val in array2)
				{
					if (!(val == (Object)null))
					{
						RuntimeAnimatorController val2 = val.As<RuntimeAnimatorController>();
						if (!((Object)(object)val2 == (Object)null) && !string.IsNullOrEmpty(((Object)val2).name))
						{
							animatorControllers[((Object)val2).name] = val2;
						}
					}
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Failed to preload animator controllers: " + ex.Message);
			}
		}

		private static void TryLoadAnimatorByPath(string path, string cacheName)
		{
			if (animatorControllers.ContainsKey(cacheName))
			{
				return;
			}
			Object val = assetBundle.LoadAsset(path);
			if (val == (Object)null)
			{
				return;
			}
			RuntimeAnimatorController val2 = val.As<RuntimeAnimatorController>();
			if (!((Object)(object)val2 == (Object)null))
			{
				animatorControllers[cacheName] = val2;
				if (!string.IsNullOrEmpty(((Object)val2).name))
				{
					animatorControllers[((Object)val2).name] = val2;
				}
			}
		}

		public static void StopProcess()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			isInitialized = false;
		}
	}
	internal static class MuzzleAligner
	{
		public static Vector3 LastMuzzleWorldPos { get; private set; }

		public static bool HasLastMuzzle { get; private set; }

		public static bool RedirectPlayerTrail { get; set; }

		public static void Align(GameObject root, string bodyToken)
		{
			//IL_0060: 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_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_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_00be: 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_00ec: 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_011a: 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)
			HasLastMuzzle = false;
			RedirectPlayerTrail = false;
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			try
			{
				Transform val = FindDeep(root.transform, "MuzzlePoint");
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Transform val2 = FindBarrelAnchor(root.transform);
				if ((Object)(object)val2 != (Object)null)
				{
					val.position = val2.position;
					val.rotation = val2.rotation;
				}
				else
				{
					Renderer val3 = FindBodyRenderer(root, bodyToken);
					if ((Object)(object)val3 == (Object)null)
					{
						return;
					}
					Vector3 position = FindBarrelTip(val3, val);
					val.position = position;
				}
				Vector3 position2 = val.position;
				SnapNearNamed(root.transform, "Muzzle Flash", position2, 0.5f);
				SnapNearNamed(root.transform, "Flash Orange", position2, 0.5f);
				SnapNearNamed(root.transform, "Flash Red", position2, 0.5f);
				SnapNearNamed(root.transform, "Point Light", position2, 0.5f);
				SnapNearNamed(root.transform, "Point Light (1)", position2, 0.5f);
				LastMuzzleWorldPos = position2;
				HasLastMuzzle = true;
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("MuzzleAligner failed: " + ex.Message);
			}
		}

		public static void RememberFrom(Equippable_RangedWeapon weapon)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			HasLastMuzzle = false;
			RedirectPlayerTrail = false;
			if ((Object)(object)weapon == (Object)null)
			{
				return;
			}
			try
			{
				Transform val = FindDeep(((Component)weapon).transform, "MuzzlePoint");
				if (!((Object)(object)val == (Object)null))
				{
					LastMuzzleWorldPos = val.position;
					HasLastMuzzle = true;
					RedirectPlayerTrail = true;
				}
			}
			catch
			{
			}
		}

		private static Transform FindBarrelAnchor(Transform root)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			string[] array = new string[5] { "Muzzle Flash", "Flash Orange", "Flash Red", "Point Light", "Point Light (1)" };
			Transform result = null;
			float num = 0.25f;
			for (int i = 0; i < array.Length; i++)
			{
				Transform val = FindDeep(root, array[i]);
				if (!((Object)(object)val == (Object)null))
				{
					Vector3 localPosition = val.localPosition;
					float magnitude = ((Vector3)(ref localPosition)).magnitude;
					if (magnitude > num)
					{
						num = magnitude;
						result = val;
					}
				}
			}
			return result;
		}

		private static Renderer FindBodyRenderer(GameObject root, string bodyToken)
		{
			//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_0109: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: 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)
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			Renderer result = null;
			float num = -1f;
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || !val.enabled || !((Component)val).gameObject.activeInHierarchy)
				{
					continue;
				}
				string text = ((Object)((Component)val).gameObject).name ?? "";
				if (text.IndexOf("Magazine", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Flash", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Bullet", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Smoke", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Shell", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					continue;
				}
				Vector3 lossyScale = ((Component)val).transform.lossyScale;
				if (!(lossyScale.x >= 5f) && !(lossyScale.y >= 5f) && !(lossyScale.z >= 5f))
				{
					bool flag = !string.IsNullOrEmpty(bodyToken) && text.IndexOf(bodyToken, StringComparison.OrdinalIgnoreCase) >= 0;
					Bounds bounds = val.bounds;
					Vector3 size = ((Bounds)(ref bounds)).size;
					float sqrMagnitude = ((Vector3)(ref size)).sqrMagnitude;
					float num2 = sqrMagnitude + (flag ? 1000f : 0f);
					if (num2 > num)
					{
						num = num2;
						result = val;
					}
				}
			}
			return result;
		}

		private static Vector3 FindBarrelTip(Renderer body, Transform muzzle)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0064: 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_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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_008b: 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_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_00ab: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = body.bounds;
			Vector3 val = muzzle.forward;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f && (Object)(object)muzzle.parent != (Object)null)
			{
				val = -muzzle.parent.right;
			}
			((Vector3)(ref val)).Normalize();
			Vector3 val2 = ((Bounds)(ref bounds)).center;
			float num = float.MinValue;
			Vector3 center = ((Bounds)(ref bounds)).center;
			Vector3 extents = ((Bounds)(ref bounds)).extents;
			for (int i = -1; i <= 1; i += 2)
			{
				for (int j = -1; j <= 1; j += 2)
				{
					for (int k = -1; k <= 1; k += 2)
					{
						Vector3 val3 = center + new Vector3(extents.x * (float)i, extents.y * (float)j, extents.z * (float)k);
						float num2 = Vector3.Dot(val3 - center, val);
						if (num2 > num)
						{
							num = num2;
							val2 = val3;
						}
					}
				}
			}
			return val2 + val * 0.02f;
		}

		private static void SnapNearNamed(Transform root, string name, Vector3 worldPos, float maxDist)
		{
			//IL_0017: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			Transform val = FindDeep(root, name);
			if (!((Object)(object)val == (Object)null) && (Vector3.Distance(val.position, worldPos) <= maxDist || name.StartsWith("Flash", StringComparison.Ordinal) || name.StartsWith("Muzzle", StringComparison.Ordinal) || name.StartsWith("Point Light", StringComparison.Ordinal)))
			{
				val.position = worldPos;
			}
		}

		private static Transform FindDeep(Transform root, string name)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			if (((Object)root).name == name)
			{
				return root;
			}
			for (int i = 0; i < root.childCount; i++)
			{
				Transform val = FindDeep(root.GetChild(i), name);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}
	}
	internal static class SafeHarmony
	{
		public static bool PatchesLive { get; private set; }

		public static void Apply(Harmony harmony, params Type[] patchClasses)
		{
			foreach (Type patchClass in patchClasses)
			{
				TryPatch(harmony, patchClass);
			}
			PatchesLive = true;
		}

		public static IEnumerator ApplyBatched(Harmony harmony, params Type[] patchClasses)
		{
			PatchesLive = false;
			int ok = 0;
			foreach (Type patchClass in patchClasses)
			{
				if (TryPatch(harmony, patchClass))
				{
					ok++;
				}
				yield return null;
				yield return null;
				yield return null;
			}
			MelonLogger.Msg($"MoreGuns Harmony applied {ok}/{patchClasses.Length} patch classes (batched).");
			yield return (object)new WaitForSecondsRealtime(2f);
			PatchesLive = true;
			MelonLogger.Msg("MoreGuns Harmony patch gate open.");
		}

		private static bool TryPatch(Harmony harmony, Type patchClass)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				new PatchClassProcessor(harmony, patchClass).Patch();
				return true;
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Harmony class " + patchClass.Name + " failed to bind: " + ex.Message);
				return false;
			}
		}
	}
	public static class Tools
	{
		public static class LegalStatus
		{
			public static ELegalStatus StringConvertToELegalStatus(string eLegalStatus)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				if (Enum.TryParse<ELegalStatus>(eLegalStatus, out ELegalStatus result))
				{
					return result;
				}
				throw new ArgumentException("Could not convert '" + eLegalStatus + "' to an ELegalStatus.");
			}
		}

		public static class Rank
		{
			public static FullRank Parse(string rank, string tier)
			{
				//IL_0065: 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_006e: 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_007d: 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)
				if (!Enum.TryParse<ERank>(rank?.Trim(), out ERank result))
				{
					throw new ArgumentException("Could not convert '" + rank + "' to an ERank.");
				}
				if (!int.TryParse(tier?.Trim(), out var result2))
				{
					throw new ArgumentException("Could not convert '" + tier + "' to a rank tier.");
				}
				return new FullRank
				{
					Rank = result,
					Tier = result2
				};
			}
		}

		public static bool Alive(Object obj)
		{
			if (obj == null)
			{
				return false;
			}
			try
			{
				return obj != (Object)null;
			}
			catch
			{
				return false;
			}
		}

		public static bool IsLocalPlayerHeld(Equippable_RangedWeapon weapon)
		{
			if (!Alive((Object)(object)weapon))
			{
				return false;
			}
			try
			{
				Player local = Player.Local;
				if ((Object)(object)local == (Object)null)
				{
					return false;
				}
				Transform transform = ((Component)local).transform;
				Transform val = ((Component)weapon).transform;
				for (int i = 0; i < 12; i++)
				{
					if (!Alive((Object)(object)val))
					{
						break;
					}
					if ((Object)(object)val == (Object)(object)transform)
					{
						return true;
					}
					val = val.parent;
				}
			}
			catch
			{
				return false;
			}
			return false;
		}
	}
}
namespace MoreGuns.Sync
{
	public static class NetworkController
	{
		private const string IDENTIFICATION_PREFIX = "moreguns_settings";

		private const int FIELD_COUNT = 25;

		private static readonly string version = typeof(MoreGunsMod).Assembly.GetName().Version.ToString();

		public static StringBuilder payload = new StringBuilder();

		public static bool forceHost = false;

		public static bool forceClient = false;

		public static bool IsSynced { get; private set; } = false;

		public static void SyncConfiguration()
		{
			Lobby instance = Singleton<Lobby>.Instance;
			bool flag = instance != null && instance.IsHost;
			Lobby instance2 = Singleton<Lobby>.Instance;
			int num;
			if (instance2 != null && !instance2.IsHost)
			{
				Lobby instance3 = Singleton<Lobby>.Instance;
				num = ((instance3 != null && instance3.IsInLobby) ? 1 : 0);
			}
			else
			{
				num = 0;
			}
			bool flag2 = (byte)num != 0;
			payload = new StringBuilder();
			StringBuilder stringBuilder = payload;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(2, 2, stringBuilder);
			handler.AppendFormatted("moreguns_settings");
			handler.AppendLiteral("_");
			handler.AppendFormatted(version);
			handler.AppendLiteral("|");
			stringBuilder.Append(ref handler);
			if (flag || forceHost)
			{
				MelonCoroutines.Start(SyncHostToLobbyPayload());
				return;
			}
			if (flag2 || forceClient)
			{
				MelonCoroutines.Start(WaitOnLobbyPayload());
				return;
			}
			foreach (WeaponBase allWeapon in WeaponBase.allWeapons)
			{
				allWeapon.ApplySettingsFromConfig();
			}
			MelonCoroutines.Start(SyncHostToLobbyPayload());
		}

		public static IEnumerator WaitOnLobbyPayload()
		{
			string data;
			while (true)
			{
				data = SteamMatchmaking.GetLobbyData(Compat.LobbySteamId(), "MoreGunsConfig");
				if (!string.IsNullOrEmpty(data) && data.IndexOf('@') >= 0)
				{
					break;
				}
				yield return (object)new WaitForSeconds(1f);
			}
			HostToClientConfigurationSync(data);
		}

		private static IEnumerator SyncHostToLobbyPayload()
		{
			foreach (WeaponBase weapon in WeaponBase.allWeapons)
			{
				if (weapon != null && !((Object)(object)weapon.gunRangedWeapon == (Object)null) && weapon.config != null)
				{
					weapon.ApplySettingsFromConfig();
					while (!weapon.IsConfigurationFinished)
					{
						yield return (object)new WaitForSeconds(0.05f);
					}
					StringBuilder stringBuilder = payload;
					StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(25, 25, stringBuilder);
					handler.AppendLiteral("@");
					handler.AppendFormatted(weapon.ID);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.gunRangedWeapon.Damage);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.gunRangedWeapon.ImpactForce);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.gunRangedWeapon.MinAimFOVReduction);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.gunRangedWeapon.MaxAimFOVReduction);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.gunRangedWeapon.AccuracyChangeDuration);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.gunRangedWeapon.MagazineSize);
					handler.AppendLiteral(":");
					handler.AppendFormatted(((BaseItemDefinition)weapon.gunIntItemDef).Name);
					handler.AppendLiteral(":");
					handler.AppendFormatted(((BaseItemDefinition)weapon.gunIntItemDef).Description);
					handler.AppendLiteral(":");
					handler.AppendFormatted<ELegalStatus>(((BaseItemDefinition)weapon.gunIntItemDef).legalStatus);
					handler.AppendLiteral(":");
					handler.AppendFormatted<ERank>(((StorableItemDefinition)weapon.gunIntItemDef).RequiredRank.Rank);
					handler.AppendLiteral(":");
					handler.AppendFormatted(((StorableItemDefinition)weapon.gunIntItemDef).RequiredRank.Tier);
					handler.AppendLiteral(":");
					handler.AppendFormatted(((BaseItemDefinition)weapon.magIntItemDef).Name);
					handler.AppendLiteral(":");
					handler.AppendFormatted(((BaseItemDefinition)weapon.magIntItemDef).Description);
					handler.AppendLiteral(":");
					handler.AppendFormatted<ELegalStatus>(((BaseItemDefinition)weapon.magIntItemDef).legalStatus);
					handler.AppendLiteral(":");
					handler.AppendFormatted<ERank>(((StorableItemDefinition)weapon.magIntItemDef).RequiredRank.Rank);
					handler.AppendLiteral(":");
					handler.AppendFormatted(((StorableItemDefinition)weapon.magIntItemDef).RequiredRank.Tier);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.rangedGun.Name);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.rangedGun.Price);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.rangedGun.IsAvailable);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.rangedGun.NotAvailableReason);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.ammoGun.Name);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.ammoGun.Price);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.ammoGun.IsAvailable);
					handler.AppendLiteral(":");
					handler.AppendFormatted(weapon.ammoGun.NotAvailableReason);
					stringBuilder.Append(ref handler);
				}
			}
			try
			{
				if ((Object)(object)Singleton<Lobby>.Instance != (Object)null && (Singleton<Lobby>.Instance.IsHost || forceHost))
				{
					Singleton<Lobby>.Instance.SetLobbyData("MoreGunsConfig", payload.ToString());
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("Failed to publish MoreGuns lobby config: " + ex.Message);
			}
		}

		private static void HostToClientConfigurationSync(string data)
		{
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: 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_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			string[] array = (from item in data.Split('|')
				where !string.IsNullOrEmpty(item)
				select item).ToArray();
			if (!IsModValidForSync(array[0]))
			{
				MelonLogger.Warning("MoreGuns is outdated with the host or server.");
				MelonLogger.Warning($"Your Version: {"moreguns_settings"}_{version}, Host Version: {array[0]}");
			}
			string[] array2 = (from item in array[1].Split('@')
				where !string.IsNullOrEmpty(item)
				select item).ToArray();
			string[] array3 = array2;
			foreach (string text in array3)
			{
				string[] array4 = text.Split(':');
				if (array4.Length < 25)
				{
					MelonLogger.Warning($"Skipping malformed weapon entry in host payload (got {array4.Length} fields, expected {25}).");
				}
				else
				{
					if (!WeaponBase.weaponsByName.TryGetValue(array4[0], out var value) || !float.TryParse(array4[1], out var result) || !float.TryParse(array4[2], out var result2) || !float.TryParse(array4[3], out var result3) || !float.TryParse(array4[4], out var result4) || !float.TryParse(array4[5], out var result5) || !int.TryParse(array4[6], out var result6))
					{
						continue;
					}
					string name = array4[7];
					string description = array4[8];
					ELegalStatus legalStatus = Tools.LegalStatus.StringConvertToELegalStatus(array4[9]);
					FullRank requiredRank = Tools.Rank.Parse(array4[10], array4[11]);
					string name2 = array4[12];
					string description2 = array4[13];
					ELegalStatus legalStatus2 = Tools.LegalStatus.StringConvertToELegalStatus(array4[14]);
					FullRank requiredRank2 = Tools.Rank.Parse(array4[15], array4[16]);
					string name3 = array4[17];
					if (float.TryParse(array4[18], out var result7) && bool.TryParse(array4[19], out var result8))
					{
						string notAvailableReason = array4[20];
						string name4 = array4[21];
						if (float.TryParse(array4[22], out var result9) && bool.TryParse(array4[23], out var result10))
						{
							string notAvailableReason2 = array4[24];
							value.gunRangedWeapon.Damage = result;
							value.gunRangedWeapon.ImpactForce = result2;
							value.gunRangedWeapon.MinAimFOVReduction = result3;
							value.gunRangedWeapon.MaxAimFOVReduction = result4;
							value.gunRangedWeapon.AccuracyChangeDuration = result5;
							value.gunRangedWeapon.MagazineSize = result6;
							((BaseItemDefinition)value.gunIntItemDef).Name = name;
							((BaseItemDefinition)value.gunIntItemDef).Description = description;
							((BaseItemDefinition)value.gunIntItemDef).legalStatus = legalStatus;
							((StorableItemDefinition)value.gunIntItemDef).RequiredRank = requiredRank;
							((BaseItemDefinition)value.magIntItemDef).Name = name2;
							((BaseItemDefinition)value.magIntItemDef).Description = description2;
							((BaseItemDefinition)value.magIntItemDef).legalStatus = legalStatus2;
							((StorableItemDefinition)value.magIntItemDef).RequiredRank = requiredRank2;
							((BaseItemDefinition)value.gunIntItemDef).Name = name3;
							((StorableItemDefinition)value.gunIntItemDef).BasePurchasePrice = result7;
							value.rangedGun.IsAvailable = result8;
							value.rangedGun.NotAvailableReason = notAvailableReason;
							((BaseItemDefinition)value.magIntItemDef).Name = name4;
							((StorableItemDefinition)value.magIntItemDef).BasePurchasePrice = result9;
							value.ammoGun.IsAvailable = result10;
							value.ammoGun.NotAvailableReason = notAvailableReason2;
							value.RefreshShopListings();
						}
					}
				}
			}
		}

		private static bool IsModValidForSync(string pIdentify)
		{
			string text = "moreguns_settings_" + version;
			return pIdentify == text;
		}
	}
}
namespace MoreGuns.Patches
{
	[HarmonyPatch]
	public static class ArmsDealerInterfacePatch
	{
		private const string SHOP_OBJECT_NAME = "ArmsDealerInterface";

		private const float READY_POLL_INTERVAL = 0.25f;

		private const float READY_TIMEOUT = 60f;

		private static readonly List<ShopInterface> knownShops = new List<ShopInterface>();

		[HarmonyPatch(typeof(ShopInterface), "Awake")]
		[HarmonyPostfix]
		public static void PostfixAwake(ShopInterface __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !(((Object)((Component)__instance).gameObject).name != "ArmsDealerInterface"))
			{
				if (!knownShops.Contains(__instance))
				{
					knownShops.Add(__instance);
				}
				MelonCoroutines.Start(InjectWhenReady(__instance));
			}
		}

		public static IEnumerator FindAndInjectAfterHarmony()
		{
			while (!SafeHarmony.PatchesLive)
			{
				yield return null;
			}
			float waited = 0f;
			while (waited < 60f)
			{
				GameObject go = GameObject.Find("ArmsDealerInterface");
				if ((Object)(object)go != (Object)null)
				{
					ShopInterface shop = go.GetComponent<ShopInterface>();
					if ((Object)(object)shop != (Object)null)
					{
						if (!knownShops.Contains(shop))
						{
							knownShops.Add(shop);
						}
						while (!WeaponBase.AllWeaponsLoaded && waited < 60f)
						{
							waited += 0.25f;
							yield return (object)new WaitForSeconds(0.25f);
						}
						yield return null;
						Inject(shop);
						yield break;
					}
				}
				waited += 0.25f;
				yield return (object)new WaitForSeconds(0.25f);
			}
			MelonLogger.Warning($"Could not find {"ArmsDealerInterface"} after {60f}s.");
		}

		private static IEnumerator InjectWhenReady(ShopInterface shop)
		{
			while (!SafeHarmony.PatchesLive)
			{
				yield return null;
			}
			float waited = 0f;
			while (!WeaponBase.AllWeaponsLoaded)
			{
				if ((Object)(object)shop == (Object)null)
				{
					yield break;
				}
				if (waited >= 60f)
				{
					MelonLogger.Warning($"Weapons were still loading after {60f}s; adding whatever is ready to {"ArmsDealerInterface"}.");
					break;
				}
				waited += 0.25f;
				yield return (object)new WaitForSeconds(0.25f);
			}
			yield return null;
			yield return null;
			if (!((Object)(object)shop == (Object)null))
			{
				Inject(shop);
			}
		}

		public static void InjectAllKnownShops()
		{
			knownShops.RemoveAll((ShopInterface shop) => (Object)(object)shop == (Object)null);
			foreach (ShopInterface knownShop in knownShops)
			{
				try
				{
					Inject(knownShop);
				}
				catch (Exception ex)
				{
					MelonLogger.Warning("Shop inject failed: " + ex.Message);
				}
			}
		}

		private static void Inject(ShopInterface shop)
		{
			if ((Object)(object)shop == (Object)null || !SafeHarmony.PatchesLive)
			{
				return;
			}
			if (shop.Listings == null)
			{
				MelonLogger.Warning("ArmsDealerInterface has no listing collection; skipping MoreGuns listings.");
				return;
			}
			if (!knownShops.Contains(shop))
			{
				knownShops.Add(shop);
			}
			ShopListing template = FindTemplate(shop);
			int num = 0;
			foreach (WeaponBase allWeapon in WeaponBase.allWeapons)
			{
				try
				{
					if (AddListing(shop, (StorableItemDefinition)(object)allWeapon.gunIntItemDef, template))
					{
						num++;
					}
					if (AddListing(shop, (StorableItemDefinition)(object)allWeapon.magIntItemDef, template))
					{
						num++;
					}
				}
				catch (Exception ex)
				{
					MelonLogger.Warning("Failed to add shop listing for " + allWeapon?.ID + ": " + ex.Message);
				}
			}
			if (num > 0)
			{
				GameAccess.RefreshShownItems(shop);
				MelonLogger.Msg($"Added {num} MoreGuns listing(s) to {"ArmsDealerInterface"}.");
			}
		}

		private static ShopListing FindTemplate(ShopInterface shop)
		{
			if (shop.Listings == null)
			{
				return null;
			}
			foreach (ShopListing listing in shop.Listings)
			{
				if (listing != null && (Object)(object)listing.Item != (Object)null)
				{
					return listing;
				}
			}
			return null;
		}

		private static bool AddListing(ShopInterface shop, StorableItemDefinition item, ShopListing template)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)item == (Object)null || string.IsNullOrEmpty(((BaseItemDefinition)item).ID))
			{
				return false;
			}
			if (shop.GetListing(((BaseItemDefinition)item).ID) != null)
			{
				return false;
			}
			ShopListing val = new ShopListing();
			val.name = ((BaseItemDefinition)item).Name;
			val.Item = item;
			val.CanBeDelivered = template?.CanBeDelivered ?? false;
			val.LimitedStock = template?.LimitedStock ?? false;
			val.DefaultStock = template?.DefaultStock ?? 0;
			val.RestockRate = (ERestockRate)((template == null) ? 2 : ((int)template.RestockRate));
			val.ConditionalVisibility = false;
			if (item.ShopCategories == null)
			{
				item.ShopCategories = new List<CategoryInstance>();
			}
			shop.Listings.Add(val);
			val.Initialize(shop);
			if (val.LimitedStock)
			{
				val.SetStock(val.DefaultStock, false);
			}
			GameAccess.CreateListingUI(shop, val);
			return true;
		}

		public static void RefreshListings()
		{
			knownShops.RemoveAll((ShopInterface shop) => (Object)(object)shop == (Object)null);
			foreach (ShopInterface knownShop in knownShops)
			{
				GameAccess.RefreshShownItems(knownShop);
			}
		}
	}
	[HarmonyPatch]
	public static class CameraJoltPatch
	{
		public static string ID = "";

		[HarmonyPatch(typeof(PlayerCamera), "JoltCamera")]
		[HarmonyPrefix]
		public static bool Prefix(PlayerCamera __instance)
		{
			if (WeaponBase.weaponsByName.TryGetValue(ID, out var value))
			{
				return value.settings == null || value.settings.cameraJolt;
			}
			return true;
		}

		[HarmonyPatch(typeof(Equippable_RangedWeapon), "Fire")]
		[HarmonyPrefix]
		public static void Prefix(Equippable_RangedWeapon __instance)
		{
			try
			{
				ID = ((Object)((Component)__instance).gameObject).name.Replace("_Equippable(Clone)", "").ToLower();
			}
			catch
			{
				ID = "";
			}
		}
	}
	[HarmonyPatch]
	public static class DialoguePatch
	{
		public static bool isInititalized;

		private static DialogueChoiceData reloadDialogue;

		[HarmonyPatch(typeof(DialogueHandler), "ShowNode")]
		[HarmonyPrefix]
		public static void Prefix(DialogueHandler __instance, DialogueNodeData node)
		{
			//IL_000e: 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_001e: 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: Expected O, but got Unknown
			if (!isInititalized)
			{
				reloadDialogue = new DialogueChoiceData
				{
					Guid = "voiddial-stan-guns-opti-reloadmultgn",
					ChoiceText = "Reload Guns",
					ChoiceLabel = "Reload Guns"
				};
				isInititalized = true;
			}
			List<DialogueChoiceData> list = node.choices.ToList();
			if (node.Guid == "72f05df5-cfd4-4be3-9239-fc31bb44f49b" && ((Object)__instance.NPC).name == "Stan")
			{
				foreach (DialogueChoiceData item in list)
				{
					if (item.ChoiceLabel == "Reload Guns")
					{
						return;
					}
				}
				list.Add(reloadDialogue);
				node.choices = list.ToArray();
			}
			else
			{
				list.RemoveAll((DialogueChoiceData choice) => choice.ChoiceLabel == "Reload Guns");
				node.choices = list.ToArray();
			}
		}

		[HarmonyPatch(typeof(DialogueController_ArmsDealer), "ChoiceCallback")]
		[HarmonyPrefix]
		public static void Prefix(DialogueController_ArmsDealer __instance, string choiceLabel)
		{
			if (choiceLabel == "Reload Guns")
			{
				StanDialogue.StartSpecialGunReloads();
			}
		}
	}
	[HarmonyPatch]
	public static class Equippalbe_RangedWeaponPatch
	{
		private static float timeSinceLastAutoFire;

		private static float timeSinceWindingUp;

		[HarmonyPatch(typeof(Equippable_RangedWeapon), "UpdateInput")]
		[HarmonyPostfix]
		public static void Postfix(Equippable_RangedWeapon __instance)
		{
			if (Time.timeScale == 0f)
			{
				return;
			}
			try
			{
				if ((Object)(object)Singleton<PauseMenu>.Instance != (Object)null && Singleton<PauseMenu>.Instance.IsPaused)
				{
					return;
				}
			}
			catch
			{
				return;
			}
			GunSettings gunSettings = GunSettings.EnsureOn(__instance);
			if ((Object)(object)gunSettings == (Object)null)
			{
				return;
			}
			bool button = GameInput.GetButton((ButtonCode)0);
			bool button2 = GameInput.GetButton((ButtonCode)1);
			if (gunSettings.RequireWindup)
			{
				PlayAnimation val = null;
				AudioSourceController val2 = null;
				try
				{
					val = ((Component)((Component)__instance).transform.GetChild(0)).GetComponent<PlayAnimation>();
					val2 = ((Component)((Component)val).transform.Find("Windup Sound")).GetComponent<AudioSourceController>();
				}
				catch
				{
					return;
				}
				if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
				{
					return;
				}
				timeSinceWindingUp += Time.deltaTime;
				WindupIndicator.SetValueByTime(timeSinceWindingUp, gunSettings.WindupTime);
				if (button2)
				{
					if (timeSinceWindingUp <= gunSettings.WindupTime || !button)
					{
						val.Play("MiniGun Windup");
						if (!val2.IsPlaying)
						{
							val2.Play();
						}
					}
				}
				else
				{
					WindupIndicator.SetValue(0);
					timeSinceWindingUp = 0f;
					val2.Stop();
				}
			}
			if (gunSettings.IsAutomatic && (!gunSettings.RequireWindup || timeSinceWindingUp > gunSettings.WindupTime))
			{
				timeSinceLastAutoFire += Time.deltaTime;
				if (button)
				{
					if (timeSinceLastAutoFire >= __instance.FireCooldown)
					{
						timeSinceLastAutoFire = 0f;
						if (GameAccess.CanFire(__instance, checkAmmo: false) && __instance.Ammo > 0)
						{
							if (!__instance.MustBeCocked || __instance.IsCocked)
							{
								__instance.Fire();
							}
							else
							{
								GameAccess.Cock(__instance);
							}
						}
					}
				}
				else
				{
					timeSinceLastAutoFire = __instance.FireCooldown;
				}
			}
			if (gunSettings.SyncMagazineToAmmo && !__instance.IsReloading)
			{
				WeaponBehavior.SyncMagazineVisualToAmmo(__instance);
			}
		}

		[HarmonyPatch(typeof(Equippable_RangedWeapon), "Fire")]
		[HarmonyPrefix]
		public static bool Prefix(Equippable_RangedWeapon __instance)
		{
			GunSettings gunSettings = GunSettings.EnsureOn(__instance);
			if ((Object)(object)gunSettings == (Object)null)
			{
				return true;
			}
			if (gunSettings.RequireWindup && timeSinceWindingUp < gunSettings.WindupTime)
			{
				return false;
			}
			MuzzleAligner.RememberFrom(__instance);
			return true;
		}

		[HarmonyPatch(typeof(FXManager), "CreateBulletTrail")]
		[HarmonyPrefix]
		public static void PrefixBulletTrail(ref Vector3 start)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (MuzzleAligner.RedirectPlayerTrail && MuzzleAligner.HasLastMuzzle)
			{
				start = MuzzleAligner.LastMuzzleWorldPos;
				MuzzleAligner.RedirectPlayerTrail = false;
			}
		}

		[HarmonyPatch(typeof(Equippable_RangedWeapon), "Fire")]
		[HarmonyPostfix]
		public static void PostfixFire(Equippable_RangedWeapon __instance)
		{
			MuzzleAligner.RedirectPlayerTrail = false;
			GunSettings gunSettings = GunSettings.EnsureOn(__instance);
			if (!((Object)(object)gunSettings == (Object)null))
			{
				if (gunSettings.ExplosiveRounds)
				{
					WeaponBehavior.CreateExplosionAtAimPoint(__instance);
				}
				if (gunSettings.SyncMagazineToAmmo)
				{
					WeaponBehavior.SyncMagazineVisualToAmmo(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Equippable_RangedWeapon), "Reload")]
		[HarmonyPostfix]
		public static void PostfixReload(Equippable_RangedWeapon __instance)
		{
			GunSettings gunSettings = GunSettings.EnsureOn(__instance);
			if ((Object)(object)gunSettings != (Object)null && gunSettings.SyncMagazineToAmmo)
			{
				WeaponBehavior.SyncMagazineVisualToAmmo(__instance);
			}
		}
	}
	[HarmonyPatch]
	public static class ItemRegistryPatch
	{
		private static bool isRegistering;

		private static bool Prepare()
		{
			return TargetMethod() != null;
		}

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(Registry), "_GetItem", new Type[2]
			{
				typeof(string),
				typeof(bool)
			}, (Type[])null);
		}

		public static void Prefix(Registry __instance, string ID)
		{
			if (!isRegistering && !((Object)(object)__instance == (Object)null) && IsOurId(ID))
			{
				RegisterInto(__instance);
			}
		}

		public static void Reset()
		{
			isRegistering = false;
		}

		public static IEnumerator RegisterWhenReady()
		{
			float waited = 0f;
			while ((!WeaponBase.AllWeaponsLoaded || WeaponBase.allWeapons.Count == 0) && !(waited >= 60f))
			{
				waited += 0.25f;
				yield return (object)new WaitForSeconds(0.25f);
			}
			RegisterWeapons();
		}

		public static void RegisterWeapons()
		{
			Registry registry = null;
			try
			{
				registry = Singleton<Registry>.Instance;
			}
			catch
			{
			}
			RegisterInto(registry);
		}

		private static bool IsOurId(string id)
		{
			if (string.IsNullOrEmpty(id) || WeaponBase.weaponsByName.Count == 0)
			{
				return false;
			}
			if (WeaponBase.weaponsByName.ContainsKey(id))
			{
				return true;
			}
			if (id.Length > 3 && id.EndsWith("mag", StringComparison.OrdinalIgnoreCase))
			{
				string key = id.Substring(0, id.Length - 3);
				if (WeaponBase.weaponsByName.ContainsKey(key))
				{
					return true;
				}
			}
			foreach (string key2 in WeaponBase.weaponsByName.Keys)
			{
				if (string.Equals(key2, id, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
				if (string.Equals(key2 + "mag", id, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			return false;
		}

		private static void RegisterInto(Registry registry)
		{
			if ((Object)(object)registry == (Object)null || isRegistering || WeaponBase.allWeapons.Count == 0)
			{
				return;
			}
			isRegistering = true;
			try
			{
				foreach (WeaponBase allWeapon in WeaponBase.allWeapons)
				{
					if (!((Object)(object)allWeapon?.gunIntItemDef == (Object)null) && !string.IsNullOrEmpty(allWeapon.ID))
					{
						((BaseItemDefinition)allWeapon.gunIntItemDef).ID = allWeapon.ID;
						if ((Object)(object)allWeapon.magIntItemDef != (Object)null)
						{
							((BaseItemDefinition)allWeapon.magIntItemDef).ID = allWeapon.ID + "mag";
						}
						bool flag = AddIfMissing(registry, (ItemDefinition)(object)allWeapon.gunIntItemDef);
						bool flag2 = AddIfMissing(registry, (ItemDefinition)(object)allWeapon.magIntItemDef);
						if (flag || flag2)
						{
							MelonLogger.Msg("Registered " + allWeapon.ID + " item definition and magazine.");
						}
					}
				}
			}
			catch (Exception value)
			{
				MelonLogger.Error($"Failed to register More Guns items: {value}");
			}
			finally
			{
				isRegistering = false;
			}
		}

		private static bool AddIfMissing(Registry registry, ItemDefinition definition)
		{
			if ((Object)(object)definition == (Object)null || string.IsNullOrEmpty(((BaseItemDefinition)definition).ID))
			{
				return false;
			}
			try
			{
				if (Registry.ItemExists(((BaseItemDefinition)definition).ID))
				{
					return false;
				}
			}
			catch
			{
			}
			try
			{
				registry.AddToRegistry(definition);
			}
			catch
			{
				GameAccess.Call(registry, "AddToRegistry", definition);
			}
			return true;
		}
	}
	[HarmonyPatch]
	public static class RangedWeaponEquipPatch
	{
		private const string MOVE_SPEED_LABEL = "MoreGuns";

		[HarmonyPatch(typeof(Equippable_RangedWeapon), "Equip")]
		[HarmonyPostfix]
		public static void PostfixEquip(Equippable_RangedWeapon __instance)
		{
			WeaponBase weaponBase = GunSettings.ResolveWeaponBase(__instance);
			if (weaponBase != null && !string.Equals(weaponBase.ID, "ak47", StringComparison.OrdinalIgnoreCase) && !string.Equals(weaponBase.ID, "minigun", StringComparison.OrdinalIgnoreCase))
			{
				try
				{
					MagazineSocketFix.FixGunHierarchy(((Component)__instance).gameObject);
				}
				catch
				{
				}
				try
				{
					MuzzleAligner.Align(((Component)__instance).gameObject, weaponBase.name ?? weaponBase.ID);
				}
				catch
				{
				}
			}
			GunSettings gunSettings = GunSettings.EnsureOn(__instance);
			if (!((Object)(object)gunSettings == (Object)null))
			{
				Reticle.SetActive(Config.EnableCrosshairForGuns.Value);
				if (gunSettings.RequireWindup)
				{
					WindupIndicator.Show(shown: true);
				}
				SetMoveSpeedMultiplier(gunSettings.SpeedMultiplier);
				if (gunSettings.SyncMagazineToAmmo)
				{
					WeaponBehavior.SyncMagazineVisualToAmmo(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Equippable_RangedWeapon), "Unequip")]
		[HarmonyPostfix]
		public static void PostfixUnequip(Equippable_RangedWeapon __instance)
		{
			Reticle.SetActive(active: false);
			WindupIndicator.Show(shown: false);
			ClearMoveSpeedMultiplier();
		}

		private static void SetMoveSpeedMultiplier(float multiplier)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			FloatStack val = PlayerSingleton<PlayerMovement>.Instance?.MoveSpeedMultiplierStack;
			if (val != null)
			{
				val.Remove("MoreGuns");
				val.Add(new StackEntry("MoreGuns", multiplier, (EStackMode)2, 0));
				GameAccess.Recalculate(val);
			}
		}

		private static void ClearMoveSpeedMultiplier()
		{
			FloatStack val = PlayerSingleton<PlayerMovement>.Instance?.MoveSpeedMultiplierStack;
			if (val != null)
			{
				val.Remove("MoreGuns");
				GameAccess.Recalculate(val);
			}
		}
	}
	[HarmonyPatch]
	public static class ReloadingPatch
	{
		[HarmonyPatch(typeof(Equippable_RangedWeapon), "Reload")]
		[HarmonyPrefix]
		public static bool Prefix(Equippable_RangedWeapon __instance)
		{
			WeaponBase weaponBase = GunSettings.ResolveWeaponBase(__instance);
			if (weaponBase == null)
			{
				return true;
			}
			string a = weaponBase.ID ?? "";
			if (string.Equals(a, "minigun", StringComparison.OrdinalIgnoreCase))
			{
				if (Config.AllowMinigunManualReload != null && Config.AllowMinigunManualReload.Value)
				{
					ManualReload.TryReload(__instance, weaponBase, useGunReloadAnim: false);
					return false;
				}
				ReloadMessage.Show("Take the MiniGun to Stan to reload.");
				return false;
			}
			GunTuning settings = weaponBase.settings;
			if (settings != null && !settings.canManualyReload)
			{
				ReloadMessage.Show(show: true);
				return false;
			}
			GunSettings.EnsureOn(__instance);
			bool useGunReloadAnim = !string.Equals(a, "rpg", StringComparison.OrdinalIgnoreCase);
			ManualReload.TryReload(__instance, weaponBase, useGunReloadAnim);
			return false;
		}
	}
	[HarmonyPatch]
	public static class SetEquippablePatch
	{
		private static int _lastTrailWeaponId;

		private static float _lastTrailTime;

		private static Vector3 _lastTrailEnd;

		private static string _rifleHold;

		private static string _rifleLowered;

		private static string _rifleRaised;

		private static string _rifleRecoil;

		private static bool _rifleAnimCached;

		private static bool _