Decompiled source of TurretMod v0.1.23

BepInEx/plugins/TurretMod/AASC.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using FishNet;
using FishNet.Broadcast;
using FishNet.Connection;
using FishNet.Managing;
using FishNet.Managing.Object;
using FishNet.Object;
using FishNet.Serializing;
using FishNet.Transporting;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.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;
		}
	}
}
namespace AASC
{
	public enum GunClass
	{
		Shotgun,
		Pistol,
		SMG,
		Rifle,
		Sniper
	}
	public static class Rules
	{
		public const int KitPrice = 5000;

		public const int FishPrice = 20000;

		public const int BossPrice = 100000;

		public const int MaxLevel = 10;

		public const float ManagementRange = 12f;

		public static bool Finite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		public static bool SurfaceAllowed(float normalY)
		{
			if (Finite(normalY))
			{
				return normalY >= 0.02f;
			}
			return false;
		}

		public static bool CanRecall(bool freeSlot, bool emptyHands)
		{
			return freeSlot || emptyHands;
		}

		public static bool NeedsWeaponPurchase(int currentWeaponId, int requestedWeaponId)
		{
			return currentWeaponId != requestedWeaponId;
		}

		private static int Level(int level)
		{
			return Math.Min(10, Math.Max(0, level));
		}

		private static double Growth(double rate, int level)
		{
			return Math.Pow(1.0 + rate, Level(level));
		}

		public static float ReloadSeconds(float baseline, int upgrades)
		{
			return (float)((double)Math.Max(0.01f, baseline) / Growth(0.1, upgrades));
		}

		public static string CleanName(string value)
		{
			if (value == null)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			string text = value.Trim();
			foreach (char c in text)
			{
				if (!char.IsControl(c) && c != '<' && c != '>')
				{
					stringBuilder.Append(c);
					if (stringBuilder.Length == 32)
					{
						break;
					}
				}
			}
			return stringBuilder.ToString();
		}

		public static bool InManagementRange(float distance)
		{
			if (Finite(distance))
			{
				return distance <= 12f;
			}
			return false;
		}

		public static int TurretPrice(int ownedTurrets)
		{
			return 5000 * (1 << Math.Min(7, Math.Max(0, ownedTurrets)));
		}

		public static int UpgradePrice(int level)
		{
			if (level < 0 || level >= 10)
			{
				return 0;
			}
			return 1500 * (level + 1);
		}

		public static int TierPrice(int tier)
		{
			return tier switch
			{
				1 => 100000, 
				0 => 20000, 
				_ => 0, 
			};
		}

		public static int UpgradeInvestment(int level)
		{
			int num = 0;
			for (int i = 0; i < Math.Min(10, Math.Max(0, level)); i++)
			{
				num += UpgradePrice(i);
			}
			return num;
		}

		public static int TierInvestment(int tier)
		{
			if (tier > 0)
			{
				if (tier != 1)
				{
					return 120000;
				}
				return 20000;
			}
			return 0;
		}

		public static int ResaleValue(int purchasePrice, int level, int tier)
		{
			return (Math.Max(5000, purchasePrice) + UpgradeInvestment(level) + TierInvestment(tier)) / 2;
		}

		public static int ResaleValue(int level, int tier)
		{
			return ResaleValue(5000, level, tier);
		}

		public static GunClass Classify(string name)
		{
			string text = name.ToLowerInvariant();
			if (text.Contains("snip") || text.Contains("awp") || text.Contains("scout"))
			{
				return GunClass.Sniper;
			}
			if (text.Contains("shot") || text.Contains("blunder"))
			{
				return GunClass.Shotgun;
			}
			if (text.Contains("smg") || text.Contains("uzi") || text.Contains("submachine") || text.Contains("mp5") || text.Contains("p90"))
			{
				return GunClass.SMG;
			}
			if (text.Contains("pistol") || text.Contains("revol") || text.Contains("handgun") || text.Contains("glock") || text.Contains("deagle") || text.Contains("desert eagle"))
			{
				return GunClass.Pistol;
			}
			return GunClass.Rifle;
		}

		public static float Radius(GunClass gun, int level)
		{
			return (float)((double)(new float[5] { 25f, 45f, 55f, 75f, 120f })[(int)gun] * Growth(0.05, level));
		}

		public static float Reload(GunClass gun, int level)
		{
			return (float)((double)(new float[5] { 3f, 2.4f, 2.8f, 3f, 3.5f })[(int)gun] / Growth(0.1, level));
		}

		public static float Interval(GunClass gun, int level)
		{
			return (float)((double)(new float[5] { 1.1f, 0.4f, 0.16f, 0.22f, 1.6f })[(int)gun] / Growth(0.1, level));
		}

		public static int Magazine(GunClass gun)
		{
			return (new int[5] { 2, 12, 25, 20, 5 })[(int)gun];
		}

		public static int Damage(int damage, int level)
		{
			return Math.Max(1, (int)Math.Round((double)damage * Growth(0.1, level)));
		}

		public static float Accuracy(int level)
		{
			return 0.85f + (float)Math.Min(10, Math.Max(0, level)) * 0.015f;
		}

		public static float AccuracyCone(int level)
		{
			return 3f - (float)Math.Min(10, Math.Max(0, level)) * 0.27f;
		}

		public static bool Eligible(int tier, bool seagull, bool fish, bool boss, bool dead, bool held, bool albatross = false)
		{
			if (!dead && !held && (seagull || fish || albatross))
			{
				if (!boss)
				{
					if (!seagull)
					{
						return tier >= 1 && fish;
					}
					return true;
				}
				return tier >= 2;
			}
			return false;
		}
	}
	[Serializable]
	public sealed class TurretData
	{
		public int serial;

		public int level;

		public int tier;

		public int ammo;

		public int shots;

		public int reloads;

		public int acquisition;

		public int purchasePrice;

		public ulong owner;

		public string ownerName;

		public string customName;

		public bool deployed;

		public bool friendlyFire;

		public bool acquiring;

		public bool hasTarget;

		public bool available = true;

		public string combatStatus = "Not deployed";

		public Vector3 surfaceNormal = Vector3.up;

		public Vector3 position;

		public Vector3 aim;

		public Vector3 shotAim;

		public float yaw;

		public SavedItem weapon;

		[NonSerialized]
		public float nextShot;

		[NonSerialized]
		public bool reloading;

		[NonSerialized]
		public Creature lockedTarget;

		[NonSerialized]
		public float lockUntil;

		public string DisplayName
		{
			get
			{
				if (!string.IsNullOrEmpty(customName))
				{
					return customName;
				}
				return "Turret #" + serial;
			}
		}

		public Quaternion BaseRotation => Quaternion.FromToRotation(Vector3.up, (((Vector3)(ref surfaceNormal)).sqrMagnitude > 0.01f) ? surfaceNormal : Vector3.up) * Quaternion.Euler(0f, yaw, 0f);
	}
	[Serializable]
	public sealed class WorldData
	{
		public string name;

		public List<TurretData> turrets = new List<TurretData>();

		public List<int> retired = new List<int>();
	}
	[Serializable]
	public sealed class SaveData
	{
		public int version = 1;

		public int nextSerial = 1;

		public List<WorldData> worlds = new List<WorldData>();
	}
	[Serializable]
	public sealed class Command
	{
		public int protocol = 3;

		public int sequence;

		public int serial;

		public int argument;

		public string action;

		public string text;

		public Vector3 position;

		public Vector3 normal;
	}
	[Serializable]
	public sealed class Snapshot
	{
		public int protocol = 3;

		public string world;

		public List<TurretData> turrets = new List<TurretData>();
	}
	[Serializable]
	public sealed class Reply
	{
		public int sequence;

		public int serial;

		public string message;
	}
	public struct RequestMessage : IBroadcast
	{
		public string json;
	}
	public struct StateMessage : IBroadcast
	{
		public string json;
	}
	public struct ReplyMessage : IBroadcast
	{
		public string json;
	}
	public sealed class Gun
	{
		public Weapon prefab;

		public string name;

		public GunClass kind;

		public int damage;

		public int price;

		public int magazine;

		public int extendedMagazine;

		public int[] ammoDamages;

		public float reload;

		public int Magazine(SavedItem state)
		{
			if (state == null || !state.ExtendedMag)
			{
				return magazine;
			}
			return extendedMagazine;
		}

		public int Damage(SavedItem state)
		{
			int num = state?.AmmoType ?? 0;
			if (ammoDamages == null || num < 0 || num >= ammoDamages.Length)
			{
				return damage;
			}
			return ammoDamages[num];
		}
	}
	internal static class GlbModel
	{
		private const uint JsonChunk = 1313821514u;

		private const uint BinaryChunk = 5130562u;

		public const float TopHeight = 0.99f;

		public static Transform Create(Transform parent)
		{
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("AASC.turret-base.glb");
			if (stream == null)
			{
				throw new InvalidOperationException("Embedded turret base model is missing.");
			}
			using BinaryReader binaryReader = new BinaryReader(stream);
			if (binaryReader.ReadUInt32() != 1179937895 || binaryReader.ReadUInt32() != 2)
			{
				throw new InvalidDataException("Turret base is not a glTF 2.0 binary model.");
			}
			uint num = binaryReader.ReadUInt32();
			string text = null;
			byte[] array = null;
			while (stream.Position < num)
			{
				int count = binaryReader.ReadInt32();
				uint num2 = binaryReader.ReadUInt32();
				byte[] array2 = binaryReader.ReadBytes(count);
				switch (num2)
				{
				case 1313821514u:
					text = Encoding.UTF8.GetString(array2).TrimEnd('\0', ' ', '\t', '\r', '\n');
					break;
				case 5130562u:
					array = array2;
					break;
				}
			}
			if (text == null || array == null)
			{
				throw new InvalidDataException("Turret base GLB is missing JSON or mesh data.");
			}
			return Build(parent, JObject.Parse(text), array);
		}

		private static Transform Build(Transform parent, JObject gltf, byte[] binary)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Expected O, but got Unknown
			//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_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			JObject val = (JObject)gltf["meshes"][(object)0][(object)"primitives"][(object)0];
			JObject val2 = (JObject)val["attributes"];
			Vector3[] array = ReadVec3(gltf, binary, (int)val2["POSITION"]);
			Vector3[] array2 = ReadVec3(gltf, binary, (int)val2["NORMAL"]);
			Vector2[] array3 = ReadVec2(gltf, binary, (int)val2["TEXCOORD_0"]);
			int[] array4 = ReadIndices(gltf, binary, (int)val["indices"]);
			float num = float.MaxValue;
			Vector3 val3 = Vector3.zero;
			for (int i = 0; i < array.Length; i++)
			{
				val3 += array[i];
				if (array[i].y < num)
				{
					num = array[i].y;
				}
			}
			val3 /= (float)Mathf.Max(1, array.Length);
			for (int j = 0; j < array.Length; j++)
			{
				array[j] = new Vector3((array[j].x - val3.x) * 0.675f, (array[j].y - num) * 0.675f, (0f - (array[j].z - val3.z)) * 0.675f);
			}
			for (int k = 0; k < array2.Length; k++)
			{
				array2[k] = new Vector3(array2[k].x, array2[k].y, 0f - array2[k].z);
			}
			for (int l = 0; l < array3.Length; l++)
			{
				array3[l].y = 1f - array3[l].y;
			}
			for (int m = 0; m + 2 < array4.Length; m += 3)
			{
				int num2 = array4[m + 1];
				array4[m + 1] = array4[m + 2];
				array4[m + 2] = num2;
			}
			Mesh val4 = new Mesh
			{
				name = "Imported Turret Base"
			};
			val4.indexFormat = (IndexFormat)1;
			val4.vertices = array;
			val4.normals = array2;
			val4.uv = array3;
			val4.triangles = array4;
			val4.RecalculateBounds();
			GameObject val5 = new GameObject("AASCBase");
			val5.transform.SetParent(parent, false);
			val5.AddComponent<MeshFilter>().sharedMesh = val4;
			MeshRenderer obj = val5.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterial = Material(gltf, binary);
			((Renderer)obj).lightmapIndex = -1;
			((Renderer)obj).realtimeLightmapIndex = -1;
			return val5.transform;
		}

		private static Material Material(JObject gltf, byte[] binary)
		{
			//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_0028: 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_0034: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			//IL_00a4: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			Material val = new Material(Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard"))
			{
				name = "Imported Turret Base Material",
				color = Color.white
			};
			JArray val2 = (JArray)gltf["images"];
			if (val2 != null && ((JContainer)val2).Count > 0)
			{
				int num = (int)((JObject)val2[0])["bufferView"];
				JObject val3 = (JObject)gltf["bufferViews"][(object)num];
				int srcOffset = Value(val3, "byteOffset");
				int num2 = Value(val3, "byteLength");
				byte[] array = new byte[num2];
				Buffer.BlockCopy(binary, srcOffset, array, 0, num2);
				Texture2D val4 = new Texture2D(2, 2, (TextureFormat)4, false)
				{
					name = "Imported Turret Base Texture",
					wrapMode = (TextureWrapMode)0
				};
				if (!ImageConversion.LoadImage(val4, array))
				{
					throw new InvalidDataException("Turret base texture could not be decoded.");
				}
				val.mainTexture = (Texture)(object)val4;
				if (val.HasProperty("_BaseMap"))
				{
					val.SetTexture("_BaseMap", (Texture)(object)val4);
				}
			}
			return val;
		}

		private static int Value(JObject value, string name)
		{
			JToken val = value[name];
			if (val != null)
			{
				return (int)val;
			}
			return 0;
		}

		private static int Offset(JObject gltf, int accessorIndex, out JObject accessor, out JObject view)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			accessor = (JObject)gltf["accessors"][(object)accessorIndex];
			view = (JObject)gltf["bufferViews"][(object)(int)accessor["bufferView"]];
			return Value(view, "byteOffset") + Value(accessor, "byteOffset");
		}

		private static Vector3[] ReadVec3(JObject gltf, byte[] data, int index)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			JObject accessor;
			JObject view;
			int num = Offset(gltf, index, out accessor, out view);
			int num2 = (int)accessor["count"];
			int num3 = Value(view, "byteStride");
			if (num3 == 0)
			{
				num3 = 12;
			}
			Vector3[] array = (Vector3[])(object)new Vector3[num2];
			for (int i = 0; i < num2; i++)
			{
				int num4 = num + i * num3;
				array[i] = new Vector3(Float(data, num4), Float(data, num4 + 4), Float(data, num4 + 8));
			}
			return array;
		}

		private static Vector2[] ReadVec2(JObject gltf, byte[] data, int index)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			JObject accessor;
			JObject view;
			int num = Offset(gltf, index, out accessor, out view);
			int num2 = (int)accessor["count"];
			int num3 = Value(view, "byteStride");
			if (num3 == 0)
			{
				num3 = 8;
			}
			Vector2[] array = (Vector2[])(object)new Vector2[num2];
			for (int i = 0; i < num2; i++)
			{
				int num4 = num + i * num3;
				array[i] = new Vector2(Float(data, num4), Float(data, num4 + 4));
			}
			return array;
		}

		private static int[] ReadIndices(JObject gltf, byte[] data, int index)
		{
			JObject accessor;
			JObject view;
			int num = Offset(gltf, index, out accessor, out view);
			int num2 = (int)accessor["count"];
			int num3 = (int)accessor["componentType"];
			int num4 = num3 switch
			{
				5123 => 2, 
				5125 => 4, 
				_ => 1, 
			};
			int num5 = Value(view, "byteStride");
			if (num5 == 0)
			{
				num5 = num4;
			}
			int[] array = new int[num2];
			for (int i = 0; i < num2; i++)
			{
				int num6 = num + i * num5;
				array[i] = num3 switch
				{
					5123 => BitConverter.ToUInt16(data, num6), 
					5125 => (int)BitConverter.ToUInt32(data, num6), 
					_ => data[num6], 
				};
			}
			return array;
		}

		private static float Float(byte[] data, int offset)
		{
			return BitConverter.ToSingle(data, offset);
		}
	}
	public static class Kit
	{
		public const byte Id = 250;

		public const ushort Collection = 42420;

		public static Item Prefab;

		private static GameObject storage;

		public static bool Is(Item item)
		{
			if ((Object)(object)item != (Object)null && item.ID == 250)
			{
				return (Object)(object)((Component)item).GetComponent<KitVisual>() != (Object)null;
			}
			return false;
		}

		public static int Serial(Item item)
		{
			if (!Is(item))
			{
				return 0;
			}
			return Mathf.RoundToInt(item.BettingMultiplier);
		}

		public static void Register()
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Expected O, but got Unknown
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Prefab != (Object)null || (Object)(object)InstanceFinder.NetworkManager == (Object)null)
			{
				return;
			}
			Dictionary<byte, Item> dictionary = (Dictionary<byte, Item>)AccessTools.Field(typeof(GameInfo), "_idToSpawnable").GetValue(null);
			if (dictionary.Count == 0)
			{
				return;
			}
			if (dictionary.ContainsKey(250))
			{
				throw new Exception("AASC item ID 250 is already in use; refusing to replace another item.");
			}
			Item val = (from i in dictionary.Values
				where (Object)(object)i != (Object)null && ((object)i).GetType() == typeof(Item) && (Object)(object)((Component)i).GetComponent<NetworkObject>() != (Object)null
				orderby i.ID
				select i).FirstOrDefault();
			if ((Object)(object)val == (Object)null)
			{
				throw new Exception("No compatible base Item prefab found for the inventory kit.");
			}
			storage = new GameObject("AASC prefab storage");
			storage.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)storage);
			Item val2 = Object.Instantiate<Item>(val, storage.transform);
			((Object)val2).name = "Turret Mod Kit";
			AccessTools.Field(typeof(Item), "_id").SetValue(val2, (byte)250);
			AccessTools.Field(typeof(Item), "_cost").SetValue(val2, 5000);
			AccessTools.Field(typeof(Item), "_worth").SetValue(val2, 0);
			AccessTools.Field(typeof(Item), "_ignoredBySeagulls").SetValue(val2, true);
			AccessTools.Field(typeof(Item), "_ignoredByMoneyNPC").SetValue(val2, true);
			AccessTools.Field(typeof(Item), "_ignoredByCloseDots").SetValue(val2, false);
			AccessTools.Field(typeof(Item), "_heldPos").SetValue(val2, (object)new Vector3(0.25f, -0.45f, 0.75f));
			Renderer[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Renderer>(true);
			for (int num = 0; num < componentsInChildren.Length; num++)
			{
				componentsInChildren[num].enabled = false;
			}
			Collider[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Collider>(true);
			foreach (Collider val3 in componentsInChildren2)
			{
				if (!val3.isTrigger)
				{
					val3.enabled = false;
				}
			}
			GameObject val4 = new GameObject("AASCBodyCollider");
			val4.transform.SetParent(((Component)val2).transform, false);
			BoxCollider val5 = val4.AddComponent<BoxCollider>();
			val5.center = new Vector3(0f, 0.495f, 0f);
			val5.size = new Vector3(1.224f, 0.99f, 1.224f);
			AccessTools.Field(typeof(Item), "_worldColliders").SetValue(val2, new Collider[1] { (Collider)val5 });
			Collider val6 = (Collider)AccessTools.Field(typeof(Item), "_pickUpCollider").GetValue(val2);
			if (val6 is SphereCollider)
			{
				((SphereCollider)val6).radius = 0.765f;
				((SphereCollider)val6).center = new Vector3(0f, 0.495f, 0f);
			}
			else if (val6 is BoxCollider)
			{
				((BoxCollider)val6).size = new Vector3(1.395f, 1.17f, 1.395f);
				((BoxCollider)val6).center = new Vector3(0f, 0.495f, 0f);
			}
			AccessTools.Field(typeof(Item), "_outOfHandHolder").SetValue(val2, null);
			AccessTools.Field(typeof(Item), "_inHandHolder").SetValue(val2, null);
			KitVisual kitVisual = ((Component)val2).gameObject.AddComponent<KitVisual>();
			kitVisual.Build();
			AccessTools.Field(typeof(Item), "_mesh").SetValue(val2, kitVisual.InventoryMesh());
			AccessTools.Field(typeof(Item), "_inventoryMeshScale").SetValue(val2, 0.7f);
			AccessTools.Field(typeof(Item), "_inventoryMeshPos").SetValue(val2, (object)new Vector3(0f, -0.2f, 0f));
			AccessTools.Field(typeof(Item), "_inventoryMeshRot").SetValue(val2, (object)new Vector3(0f, 35f, 0f));
			AccessTools.Field(typeof(Item), "_renderers").SetValue(val2, (from r in ((Component)kitVisual).GetComponentsInChildren<Renderer>(true)
				where r.enabled
				select r).ToList());
			NetworkObject component = ((Component)val2).GetComponent<NetworkObject>();
			component.SetIsSpawnable(true);
			PrefabObjects prefabObjects = InstanceFinder.NetworkManager.GetPrefabObjects<SinglePrefabObjects>((ushort)42420, true);
			if (prefabObjects.GetObjectCount() != 0)
			{
				throw new Exception("AASC network prefab collection 42420 is already occupied.");
			}
			prefabObjects.AddObject(component, false, true);
			dictionary.Add(250, val2);
			((Dictionary<byte, Item>)AccessTools.Field(typeof(GameInfo), "_allItems").GetValue(null)).Add(250, val2);
			((Dictionary<string, Item>)AccessTools.Field(typeof(GameInfo), "_nameToSpawnable").GetValue(null)).Add("aascturretkit", val2);
			Prefab = val2;
			Plugin.Log("Inventory kit registered using " + ((Object)val).name + "; dedicated network collection " + (ushort)42420 + ".");
		}
	}
	public sealed class KitVisual : MonoBehaviour
	{
		public Transform head;

		public Transform socket;

		private Transform aimPivot;

		private Item item;

		private int gunId = -1;

		private int gunStateSignature = int.MinValue;

		private int lastShot;

		private int lastReload;

		private int lastAcquisition;

		private LineRenderer tracer;

		private LineRenderer lockLaser;

		private float tracerUntil;

		private GameObject mountedGun;

		private Animation mountedAnimation;

		private Transform mountedMuzzle;

		private ParticleSystem mountedFireParticle;

		private BarrelAttachment mountedBarrel;

		private AudioSequence fireSequence;

		private AudioSequence fireLastSequence;

		private AudioSequence reloadSequence;

		private AudioSequence reloadLastSequence;

		private bool hasLastFire;

		private bool hasLastReload;

		private bool proceduralReload;

		private float recoilUntil;

		private float reloadStarted;

		private float reloadUntil;

		private Vector3 mountedBasePosition;

		private Quaternion mountedBaseRotation;

		private static Material metal;

		private static Material orange;

		private static Material glow;

		private static Material lockGlow;

		public Vector3 MuzzlePosition
		{
			get
			{
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: 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_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)mountedMuzzle != (Object)null))
				{
					if (!((Object)(object)head != (Object)null))
					{
						return ((Component)this).transform.position + ((Component)this).transform.up * 1.2f;
					}
					return head.position + head.forward * 0.55f;
				}
				return mountedMuzzle.position;
			}
		}

		public int InventoryGunSignature => WeaponSignature(((Object)(object)Plugin.Instance == (Object)null) ? null : Plugin.Instance.Find(Kit.Serial(item))?.weapon);

		public void Build()
		{
			//IL_00da: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			if (!((Object)(object)((Component)this).transform.Find("AASCBase") != (Object)null))
			{
				if ((Object)(object)metal == (Object)null)
				{
					Shader obj = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard");
					metal = new Material(obj)
					{
						color = new Color(0.13f, 0.18f, 0.21f)
					};
					orange = new Material(obj)
					{
						color = new Color(0.98f, 0.46f, 0.08f)
					};
					glow = new Material(Shader.Find("Sprites/Default"))
					{
						color = Color.cyan
					};
					lockGlow = new Material(Shader.Find("Sprites/Default"))
					{
						color = Color.red
					};
				}
				GlbModel.Create(((Component)this).transform);
				head = new GameObject("AASCHead").transform;
				head.SetParent(((Component)this).transform, false);
				head.localPosition = new Vector3(0f, 0.99f, 0f);
				aimPivot = new GameObject("AASCGunAimPivot").transform;
				aimPivot.SetParent(head, false);
				aimPivot.localPosition = new Vector3(0f, 0.12f, 0f);
				socket = new GameObject("WeaponSocket").transform;
				socket.SetParent(aimPivot, false);
				socket.localPosition = Vector3.zero;
				Part("SocketEmpty", socket, (PrimitiveType)3, Vector3.zero, new Vector3(0.25f, 0.08f, 0.28f), metal);
			}
		}

		private static Transform Part(string name, Transform parent, PrimitiveType primitive, Vector3 pos, Vector3 scale, Material material)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive(primitive);
			((Object)obj).name = name;
			obj.transform.SetParent(parent, false);
			obj.transform.localPosition = pos;
			obj.transform.localScale = scale;
			Object.DestroyImmediate((Object)(object)obj.GetComponent<Collider>());
			obj.GetComponent<Renderer>().sharedMaterial = material;
			return obj.transform;
		}

		private static string RelativePath(Transform root, Transform child)
		{
			if ((Object)(object)root == (Object)null || (Object)(object)child == (Object)null)
			{
				return null;
			}
			if ((Object)(object)root == (Object)(object)child)
			{
				return "";
			}
			List<string> list = new List<string>();
			Transform val = child;
			while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			if ((Object)(object)val != (Object)(object)root)
			{
				return null;
			}
			list.Reverse();
			return string.Join("/", list.ToArray());
		}

		private static Transform CloneTransform(Transform sourceRoot, Transform cloneRoot, Transform source)
		{
			string text = RelativePath(sourceRoot, source);
			if (text != null)
			{
				if (text.Length != 0)
				{
					return cloneRoot.Find(text);
				}
				return cloneRoot;
			}
			return null;
		}

		private static T Private<T>(object target, string name) where T : class
		{
			FieldInfo fieldInfo = ((target == null) ? null : AccessTools.Field(target.GetType(), name));
			if (!(fieldInfo == null))
			{
				return fieldInfo.GetValue(target) as T;
			}
			return null;
		}

		private static void ActivatePath(Transform child, Transform root)
		{
			Transform val = child;
			while ((Object)(object)val != (Object)null)
			{
				((Component)val).gameObject.SetActive(true);
				if (!((Object)(object)val == (Object)(object)root))
				{
					val = val.parent;
					continue;
				}
				break;
			}
		}

		private static bool IsWeaponRenderer(Renderer renderer)
		{
			if (!(renderer is MeshRenderer))
			{
				return renderer is SkinnedMeshRenderer;
			}
			return true;
		}

		private static void EnableVisuals(Transform root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			ActivatePath(root, root);
			Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (IsWeaponRenderer(val))
				{
					ActivatePath(((Component)val).transform, root);
					val.enabled = true;
					val.forceRenderingOff = false;
					val.lightmapIndex = -1;
					val.realtimeLightmapIndex = -1;
				}
			}
		}

		private void ToggleCopies<T>(Transform sourceRoot, Transform cloneRoot, List<T> choices, int selected) where T : Component
		{
			if (choices == null)
			{
				return;
			}
			for (int i = 0; i < choices.Count; i++)
			{
				Transform val = CloneTransform(sourceRoot, cloneRoot, ((Object)(object)choices[i] == (Object)null) ? null : ((Component)choices[i]).transform);
				if (!((Object)(object)val == (Object)null))
				{
					((Component)val).gameObject.SetActive(i == selected);
					if (i == selected)
					{
						ActivatePath(val, cloneRoot);
						EnableVisuals(val);
					}
				}
			}
		}

		private void BuildMountedGun(Gun gun, SavedItem state)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0910: Unknown result type (might be due to invalid IL or missing references)
			//IL_0915: Unknown result type (might be due to invalid IL or missing references)
			//IL_0926: Unknown result type (might be due to invalid IL or missing references)
			//IL_092b: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_080b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0817: Unknown result type (might be due to invalid IL or missing references)
			//IL_083e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0845: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0892: Unknown result type (might be due to invalid IL or missing references)
			//IL_0897: Unknown result type (might be due to invalid IL or missing references)
			//IL_08c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_08cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_08dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_08fa: Unknown result type (might be due to invalid IL or missing references)
			Transform val = socket.Find("MountedGun");
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			mountedGun = null;
			mountedAnimation = null;
			mountedMuzzle = null;
			mountedFireParticle = null;
			mountedBarrel = null;
			fireSequence = (fireLastSequence = (reloadSequence = (reloadLastSequence = null)));
			hasLastFire = (hasLastReload = false);
			if (gun == null || (Object)(object)gun.prefab == (Object)null)
			{
				return;
			}
			mountedGun = new GameObject("MountedGun");
			mountedGun.transform.SetParent(socket, false);
			bool activeSelf = ((Component)socket).gameObject.activeSelf;
			((Component)socket).gameObject.SetActive(false);
			GameObject val2 = Object.Instantiate<GameObject>(((Component)gun.prefab).gameObject, mountedGun.transform, false);
			((Object)val2).name = "WeaponRig";
			Weapon component = val2.GetComponent<Weapon>();
			if ((Object)(object)component != (Object)null && state != null)
			{
				try
				{
					((Item)component).LoadFromSave(state);
				}
				catch (Exception ex)
				{
					Plugin.Log("Native visual configuration fallback for " + gun.name + ": " + ex.Message);
				}
			}
			MonoBehaviour[] componentsInChildren = val2.GetComponentsInChildren<MonoBehaviour>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			Collider[] componentsInChildren2 = val2.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			Rigidbody[] componentsInChildren3 = val2.GetComponentsInChildren<Rigidbody>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			((Component)socket).gameObject.SetActive(activeSelf);
			val2.SetActive(true);
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.Euler(((Item)gun.prefab).InventoryMeshRot);
			val2.transform.localScale = Vector3.one;
			Transform transform = ((Component)gun.prefab).transform;
			Attachments attachments = gun.prefab.Attachments;
			GameObject val3 = Private<GameObject>(gun.prefab, "_outOfHandHolder");
			GameObject val4 = Private<GameObject>(gun.prefab, "_inHandHolder");
			Transform val5 = CloneTransform(transform, val2.transform, ((Object)(object)val3 == (Object)null) ? null : val3.transform);
			Transform val6 = CloneTransform(transform, val2.transform, ((Object)(object)val4 == (Object)null) ? null : val4.transform);
			Transform val7 = (((Object)(object)val5 != (Object)null && ((Component)val5).GetComponentsInChildren<Renderer>(true).Any(IsWeaponRenderer)) ? val5 : (((Object)(object)val6 != (Object)null) ? val6 : val5));
			if ((Object)(object)val5 != (Object)null)
			{
				((Component)val5).gameObject.SetActive((Object)(object)val7 == (Object)(object)val5);
			}
			if ((Object)(object)val6 != (Object)null)
			{
				((Component)val6).gameObject.SetActive((Object)(object)val7 == (Object)(object)val6);
			}
			if ((Object)(object)val7 != (Object)null)
			{
				ActivatePath(val7, val2.transform);
				EnableVisuals(val7);
			}
			List<Renderer> list = Private<List<Renderer>>(gun.prefab, "_renderers");
			if (list != null)
			{
				foreach (Renderer item in list)
				{
					Transform val8 = CloneTransform(transform, val2.transform, ((Object)(object)item == (Object)null) ? null : ((Component)item).transform);
					if (!((Object)(object)val8 == (Object)null) && (!((Object)(object)val7 != (Object)null) || val8.IsChildOf(val7) || !((Object)(object)val8 != (Object)(object)val7)))
					{
						ActivatePath(val8, val2.transform);
						Renderer component2 = ((Component)val8).GetComponent<Renderer>();
						if ((Object)(object)component2 != (Object)null)
						{
							component2.enabled = true;
							component2.forceRenderingOff = false;
							component2.lightmapIndex = -1;
							component2.realtimeLightmapIndex = -1;
						}
					}
				}
			}
			List<Sight> list2 = Private<List<Sight>>(attachments, "_sights");
			List<BarrelAttachment> list3 = Private<List<BarrelAttachment>>(attachments, "_barrelAttachments");
			int selected = Mathf.Clamp((int)(state?.Sight ?? 0), 0, (list2 != null) ? (list2.Count - 1) : 0);
			int num = Mathf.Clamp((int)(state?.BarrelAttachment ?? 0), 0, (list3 != null) ? (list3.Count - 1) : 0);
			ToggleCopies<Sight>(transform, val2.transform, list2, selected);
			ToggleCopies<BarrelAttachment>(transform, val2.transform, list3, num);
			LaserSight val9 = Private<LaserSight>(attachments, "_laserSight");
			Transform val10 = CloneTransform(transform, val2.transform, ((Object)(object)val9 == (Object)null) ? null : ((Component)val9).transform);
			if ((Object)(object)val10 != (Object)null)
			{
				((Component)val10).gameObject.SetActive(state?.LaserSight ?? false);
				if (state != null && state.LaserSight)
				{
					ActivatePath(val10, val2.transform);
					EnableVisuals(val10);
				}
			}
			if (list3 != null && list3.Count > 0)
			{
				mountedBarrel = list3[num];
				mountedMuzzle = CloneTransform(transform, val2.transform, mountedBarrel.FirePoint);
				Transform val11 = CloneTransform(transform, val2.transform, ((Object)(object)mountedBarrel.FireParticle == (Object)null) ? null : ((Component)mountedBarrel.FireParticle).transform);
				if ((Object)(object)val11 != (Object)null)
				{
					mountedFireParticle = ((Component)val11).GetComponent<ParticleSystem>();
				}
			}
			Renderer[] componentsInChildren4;
			if (!val2.GetComponentsInChildren<Renderer>(false).Any(IsWeaponRenderer))
			{
				componentsInChildren4 = val2.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val12 in componentsInChildren4)
				{
					if (IsWeaponRenderer(val12))
					{
						ActivatePath(((Component)val12).transform, val2.transform);
						val12.enabled = true;
						val12.forceRenderingOff = false;
						val12.lightmapIndex = -1;
						val12.realtimeLightmapIndex = -1;
					}
				}
			}
			if (state != null && (Object)(object)((Item)gun.prefab).SkinPreset != (Object)null && ((Item)gun.prefab).SkinPreset.Skins.Count > 0)
			{
				int index = Mathf.Clamp((int)state.SkinIndex, 0, ((Item)gun.prefab).SkinPreset.Skins.Count - 1);
				componentsInChildren4 = val2.GetComponentsInChildren<Renderer>(false);
				foreach (Renderer val13 in componentsInChildren4)
				{
					if (IsWeaponRenderer(val13))
					{
						ShaderManager.ApplyItemSkin(((Item)gun.prefab).SkinPreset.Skins[index], val13, false);
					}
				}
			}
			mountedAnimation = val2.GetComponentInChildren<Animation>(true);
			fireSequence = Private<AudioSequence>(gun.prefab, "_fireAudioSeq");
			fireLastSequence = Private<AudioSequence>(gun.prefab, "_fireLastAudioSeq");
			reloadSequence = Private<AudioSequence>(gun.prefab, "_reloadAudioSeq");
			reloadLastSequence = Private<AudioSequence>(gun.prefab, "_reloadLastAudioSeq");
			hasLastFire = (bool)AccessTools.Field(typeof(Weapon), "_hasLastFireAnim").GetValue(gun.prefab);
			hasLastReload = (bool)AccessTools.Field(typeof(Weapon), "_hasLastReloadAnim").GetValue(gun.prefab);
			Renderer[] array = val2.GetComponentsInChildren<Renderer>(false).Where(IsWeaponRenderer).ToArray();
			Bounds val14 = default(Bounds);
			bool flag = false;
			componentsInChildren4 = array;
			foreach (Renderer val15 in componentsInChildren4)
			{
				if (!flag)
				{
					val14 = val15.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref val14)).Encapsulate(val15.bounds);
				}
			}
			if (flag)
			{
				float num2 = 1.35f / Mathf.Max(0.001f, Mathf.Max(((Bounds)(ref val14)).size.x, Mathf.Max(((Bounds)(ref val14)).size.y, ((Bounds)(ref val14)).size.z)));
				mountedGun.transform.localScale = Vector3.one * num2;
				Renderer[] array2 = val2.GetComponentsInChildren<Renderer>(false).Where(IsWeaponRenderer).ToArray();
				flag = false;
				componentsInChildren4 = array2;
				foreach (Renderer val16 in componentsInChildren4)
				{
					if (!flag)
					{
						val14 = val16.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref val14)).Encapsulate(val16.bounds);
					}
				}
				if (flag)
				{
					Vector3 val17 = socket.InverseTransformPoint(((Bounds)(ref val14)).center);
					mountedGun.transform.localPosition = new Vector3(0f - val17.x, 0.18f - val17.y, 0f - val17.z);
				}
			}
			mountedBasePosition = mountedGun.transform.localPosition;
			mountedBaseRotation = mountedGun.transform.localRotation;
			int num3 = val2.GetComponentsInChildren<Renderer>(false).Count(IsWeaponRenderer);
			Plugin.Log("Mounted visual " + gun.name + ": skin=" + (int)(state?.SkinIndex ?? 0) + ", sight=" + (int)(state?.Sight ?? 0) + ", barrel=" + (int)(state?.BarrelAttachment ?? 0) + ", active renderers=" + num3 + ", holder=" + (((Object)(object)val7 == (Object)null) ? "fallback" : ((Object)val7).name) + ".");
		}

		private static void SetLayerRecursively(GameObject root, int layer)
		{
			Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((Component)componentsInChildren[i]).gameObject.layer = layer;
			}
		}

		public GameObject CreateInventoryGunPreview(Transform parent)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)mountedGun == (Object)null || (Object)(object)parent == (Object)null)
			{
				return null;
			}
			GameObject val = Object.Instantiate<GameObject>(mountedGun, parent, false);
			((Object)val).name = "AASCInventoryGunPreview";
			MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			Collider[] componentsInChildren2 = val.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			val.transform.localPosition = new Vector3(0f, 0.02f, 0f);
			val.transform.localRotation = Quaternion.Euler(-8f, 20f, 0f);
			val.transform.localScale = mountedGun.transform.localScale * 0.82f;
			SetLayerRecursively(val, ((Component)parent).gameObject.layer);
			val.SetActive(true);
			Renderer[] componentsInChildren3 = val.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren3)
			{
				if (IsWeaponRenderer(val2))
				{
					ActivatePath(((Component)val2).transform, val.transform);
					val2.enabled = true;
					val2.lightmapIndex = -1;
					val2.realtimeLightmapIndex = -1;
				}
			}
			return val;
		}

		private static int WeaponSignature(SavedItem state)
		{
			if (state == null || !state.Exists)
			{
				return -1;
			}
			return ((((((17 * 31 + state.ItemID) * 31 + state.SkinIndex) * 31 + state.Sight) * 31 + state.BarrelAttachment) * 31 + state.AmmoType) * 31 + (state.ExtendedMag ? 1 : 0)) * 31 + (state.LaserSight ? 1 : 0);
		}

		private void PlayAnimation(string name, float duration = 0f)
		{
			if (!((Object)(object)mountedAnimation == (Object)null) && !((TrackedReference)(object)mountedAnimation[name] == (TrackedReference)null))
			{
				AnimationState val = mountedAnimation[name];
				val.speed = ((duration > 0f) ? (val.clip.length / Mathf.Max(0.05f, duration)) : 1f);
				mountedAnimation.Stop();
				mountedAnimation.Play(name);
			}
		}

		private void PlaySequence(AudioSequence sequence, float speed = 1f)
		{
			if (sequence != null && sequence.Steps != null && sequence.Steps.Length != 0)
			{
				((MonoBehaviour)this).StartCoroutine(PlaySequenceRoutine(sequence, Mathf.Max(0.05f, speed)));
			}
		}

		private IEnumerator PlaySequenceRoutine(AudioSequence sequence, float speed)
		{
			AudioSequenceStep[] steps = sequence.Steps;
			foreach (AudioSequenceStep step in steps)
			{
				if (step != null)
				{
					if (step.Timer > 0f)
					{
						yield return (object)new WaitForSeconds(step.Timer / speed);
					}
					AudioClip randomClip = step.GetRandomClip();
					if ((Object)(object)randomClip != (Object)null)
					{
						AudioSource.PlayClipAtPoint(randomClip, MuzzlePosition, sequence.Volume * step.Volume);
					}
				}
			}
		}

		private void PlayFire(TurretData data)
		{
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			recoilUntil = Time.time + 0.12f;
			string name = ((data.ammo == 0 && hasLastFire) ? "FireLast" : "Fire");
			PlayAnimation(name);
			if ((Object)(object)mountedFireParticle != (Object)null)
			{
				mountedFireParticle.Play();
			}
			if ((Object)(object)mountedBarrel != (Object)null && !string.IsNullOrEmpty(mountedBarrel.GetFireSound(1f)))
			{
				AudioManager.PlayRandomClipAt(mountedBarrel.GetFireSound(1f), 1, Mathf.Max(1, mountedBarrel.FireSoundCount), MuzzlePosition, false, (AudioDistance)(mountedBarrel.UseMediumSoundDistance ? 2 : 3), mountedBarrel.FireSoundVolume, 0.1f);
			}
			PlaySequence((data.ammo == 0 && fireLastSequence != null) ? fireLastSequence : fireSequence);
		}

		private void PlayReload(TurretData data, Gun gun)
		{
			float num = Rules.ReloadSeconds(gun.reload, data.level);
			reloadStarted = Time.time;
			reloadUntil = Time.time + num;
			string text = ((data.ammo == 0 && hasLastReload) ? "ReloadLast" : "Reload");
			proceduralReload = (Object)(object)mountedAnimation == (Object)null || (TrackedReference)(object)mountedAnimation[text] == (TrackedReference)null;
			PlayAnimation(text, num);
			PlaySequence((data.ammo == 0 && reloadLastSequence != null) ? reloadLastSequence : reloadSequence, gun.reload / Mathf.Max(0.05f, num));
		}

		public Mesh InventoryMesh()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			MeshFilter[] source = (from f in ((Component)this).GetComponentsInChildren<MeshFilter>(true)
				where ((Component)f).GetComponent<Renderer>().enabled
				select f).ToArray();
			Mesh val = new Mesh
			{
				name = "AASC inventory mesh"
			};
			val.CombineMeshes(source.Select(delegate(MeshFilter f)
			{
				//IL_0002: 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_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				CombineInstance result = default(CombineInstance);
				((CombineInstance)(ref result)).mesh = f.sharedMesh;
				((CombineInstance)(ref result)).transform = ((Component)this).transform.worldToLocalMatrix * ((Component)f).transform.localToWorldMatrix;
				return result;
			}).ToArray());
			return val;
		}

		private void Awake()
		{
			item = ((Component)this).GetComponent<Item>();
			head = ((Component)this).transform.Find("AASCHead");
			if ((Object)(object)head != (Object)null)
			{
				aimPivot = head.Find("AASCGunAimPivot");
				socket = (((Object)(object)aimPivot == (Object)null) ? head.Find("WeaponSocket") : aimPivot.Find("WeaponSocket"));
			}
		}

		private void AimMountedWeapon(Vector3 direction, float yawDegreesPerSecond, float aimDegreesPerSecond)
		{
			//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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//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_006a: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: 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_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_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			if (((Vector3)(ref direction)).sqrMagnitude < 0.0001f || (Object)(object)head == (Object)null || (Object)(object)aimPivot == (Object)null)
			{
				return;
			}
			((Vector3)(ref direction)).Normalize();
			Vector3 up = ((Component)this).transform.up;
			Vector3 val = Vector3.ProjectOnPlane(direction, up);
			if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
			{
				((Vector3)(ref val)).Normalize();
				Vector3 val2 = Vector3.ProjectOnPlane(((Component)this).transform.forward, up);
				Vector3 normalized = ((Vector3)(ref val2)).normalized;
				if (((Vector3)(ref normalized)).sqrMagnitude < 0.0001f)
				{
					val2 = Vector3.ProjectOnPlane(Vector3.forward, up);
					normalized = ((Vector3)(ref val2)).normalized;
				}
				float num = Vector3.SignedAngle(normalized, val, up);
				Quaternion val3 = Quaternion.Euler(0f, num, 0f);
				head.localRotation = ((yawDegreesPerSecond <= 0f) ? val3 : Quaternion.RotateTowards(head.localRotation, val3, yawDegreesPerSecond * Time.deltaTime));
			}
			Quaternion val5;
			if ((Object)(object)mountedMuzzle != (Object)null)
			{
				Quaternion val4 = Quaternion.Inverse(aimPivot.rotation) * mountedMuzzle.rotation;
				val5 = Quaternion.LookRotation(direction, up) * Quaternion.Inverse(val4);
			}
			else
			{
				val5 = Quaternion.LookRotation(direction, up);
			}
			aimPivot.rotation = ((aimDegreesPerSecond <= 0f) ? val5 : Quaternion.RotateTowards(aimPivot.rotation, val5, aimDegreesPerSecond * Time.deltaTime));
		}

		private void LateUpdate()
		{
			//IL_00a0: 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_0088: 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_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_0419: Unknown result type (might be due to invalid IL or missing references)
			//IL_057a: Unknown result type (might be due to invalid IL or missing references)
			//IL_058c: Unknown result type (might be due to invalid IL or missing references)
			//IL_050f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0516: Expected O, but got Unknown
			//IL_0464: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_046e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_048a: Unknown result type (might be due to invalid IL or missing references)
			//IL_048f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04be: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_06bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_063f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0646: Expected O, but got Unknown
			//IL_06f2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)item == (Object)null || (Object)(object)Plugin.Instance == (Object)null || (Object)(object)head == (Object)null)
			{
				return;
			}
			TurretData turretData = Plugin.Instance.Find(Kit.Serial(item));
			if (turretData == null)
			{
				return;
			}
			if (turretData.deployed && (Object)(object)item.SyncedHolder == (Object)null)
			{
				item.ReconcileLocalHolderWithSyncedHolder();
				item.RigidbodySync.SetKinematic(true);
				((Component)this).transform.SetPositionAndRotation(turretData.position, turretData.BaseRotation);
			}
			else
			{
				head.localRotation = Quaternion.identity;
				if ((Object)(object)aimPivot != (Object)null)
				{
					aimPivot.localRotation = Quaternion.identity;
				}
			}
			int wanted = ((turretData.weapon != null && turretData.weapon.Exists) ? turretData.weapon.ItemID : (-1));
			int num = WeaponSignature(turretData.weapon);
			if (wanted != gunId || num != gunStateSignature)
			{
				gunId = wanted;
				gunStateSignature = num;
				Transform val = socket.Find("SocketEmpty");
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(wanted < 0);
				}
				Gun gun = Plugin.Instance.Guns.FirstOrDefault((Gun g) => ((Item)g.prefab).ID == wanted);
				BuildMountedGun(gun, turretData.weapon);
				lastShot = turretData.shots;
				lastReload = turretData.reloads;
				lastAcquisition = turretData.acquisition;
			}
			Vector3 val2;
			if (turretData.deployed && (Object)(object)item.SyncedHolder == (Object)null && turretData.hasTarget && (Object)(object)mountedGun != (Object)null)
			{
				Vector3 direction = turretData.aim - MuzzlePosition;
				if (((Vector3)(ref direction)).sqrMagnitude > 0.01f)
				{
					AimMountedWeapon(direction, 0f, 0f);
				}
			}
			else if (turretData.deployed && (Object)(object)item.SyncedHolder == (Object)null && (Object)(object)mountedGun != (Object)null)
			{
				float num2 = Mathf.Repeat(Time.time * 12f + (float)turretData.serial * 47f, 360f);
				Vector3 up = ((Component)this).transform.up;
				val2 = Vector3.ProjectOnPlane(((Component)this).transform.forward, up);
				Vector3 normalized = ((Vector3)(ref val2)).normalized;
				if (((Vector3)(ref normalized)).sqrMagnitude < 0.01f)
				{
					val2 = Vector3.ProjectOnPlane(Vector3.forward, up);
					normalized = ((Vector3)(ref val2)).normalized;
				}
				Vector3 val3 = Quaternion.AngleAxis(num2, up) * normalized;
				val2 = Vector3.Cross(up, val3);
				Vector3 normalized2 = ((Vector3)(ref val2)).normalized;
				Vector3 direction2 = Quaternion.AngleAxis(-30f, normalized2) * val3;
				AimMountedWeapon(direction2, 20f, 45f);
			}
			else
			{
				head.localRotation = Quaternion.RotateTowards(head.localRotation, Quaternion.identity, 90f * Time.deltaTime);
				if ((Object)(object)aimPivot != (Object)null)
				{
					aimPivot.localRotation = Quaternion.RotateTowards(aimPivot.localRotation, Quaternion.identity, 90f * Time.deltaTime);
				}
			}
			if ((Object)(object)mountedGun != (Object)null)
			{
				mountedGun.transform.localPosition = mountedBasePosition;
				mountedGun.transform.localRotation = mountedBaseRotation;
				if (proceduralReload && Time.time < reloadUntil)
				{
					float num3 = Mathf.InverseLerp(reloadStarted, reloadUntil, Time.time);
					mountedGun.transform.localRotation = mountedBaseRotation * Quaternion.Euler(Mathf.Sin(num3 * (float)Math.PI) * 32f, 0f, Mathf.Sin(num3 * (float)Math.PI * 2f) * 8f);
				}
				else if (Time.time < recoilUntil)
				{
					val2 = socket.InverseTransformDirection(((Object)(object)mountedMuzzle != (Object)null) ? (-mountedMuzzle.forward) : (-head.forward));
					Vector3 normalized3 = ((Vector3)(ref val2)).normalized;
					mountedGun.transform.localPosition = mountedBasePosition + normalized3 * (Mathf.Sin(Mathf.InverseLerp(recoilUntil - 0.12f, recoilUntil, Time.time) * (float)Math.PI) * 0.07f);
				}
			}
			if (turretData.shots != lastShot)
			{
				lastShot = turretData.shots;
				if (turretData.deployed)
				{
					PlayFire(turretData);
					if ((Object)(object)tracer == (Object)null)
					{
						GameObject val4 = new GameObject("AASC tracer");
						val4.transform.SetParent(((Component)this).transform, false);
						tracer = val4.AddComponent<LineRenderer>();
						((Renderer)tracer).sharedMaterial = glow;
						tracer.startWidth = 0.025f;
						tracer.endWidth = 0.009f;
						tracer.positionCount = 2;
					}
					tracer.SetPosition(0, MuzzlePosition);
					tracer.SetPosition(1, turretData.shotAim);
					((Renderer)tracer).enabled = true;
					tracerUntil = Time.time + 0.09f;
				}
			}
			if (turretData.reloads != lastReload)
			{
				lastReload = turretData.reloads;
				Gun gun2 = Plugin.Instance.GetGun(turretData);
				if (turretData.deployed && gun2 != null)
				{
					PlayReload(turretData, gun2);
				}
			}
			if ((Object)(object)tracer != (Object)null && Time.time > tracerUntil)
			{
				((Renderer)tracer).enabled = false;
			}
			if (turretData.deployed && turretData.acquiring)
			{
				if ((Object)(object)lockLaser == (Object)null)
				{
					GameObject val5 = new GameObject("AASC target lock laser");
					val5.transform.SetParent(((Component)this).transform, false);
					lockLaser = val5.AddComponent<LineRenderer>();
					((Renderer)lockLaser).sharedMaterial = lockGlow;
					lockLaser.startWidth = 0.018f;
					lockLaser.endWidth = 0.008f;
					lockLaser.positionCount = 2;
				}
				lockLaser.SetPosition(0, MuzzlePosition);
				lockLaser.SetPosition(1, turretData.aim);
				((Renderer)lockLaser).enabled = true;
				if (turretData.acquisition != lastAcquisition)
				{
					lastAcquisition = turretData.acquisition;
					TargetSound.Play(((Component)this).transform.position);
				}
			}
			else if ((Object)(object)lockLaser != (Object)null)
			{
				((Renderer)lockLaser).enabled = false;
			}
		}
	}
	[BepInPlugin("ponyfisher.howtofish.aasc", "TURRET MOD", "0.1.23")]
	[DefaultExecutionOrder(29000)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "ponyfisher.howtofish.aasc";

		public static Plugin Instance;

		public List<Gun> Guns = new List<Gun>();

		public List<TurretData> Current = new List<TurretData>();

		public bool Open;

		public string Status = "Load a game, then buy an empty turret kit.";

		public int Selected;

		private SaveData save = new SaveData();

		private WorldData world;

		private NetworkManager manager;

		private Harmony harmony;

		private string savePath;

		private bool persistenceReady = true;

		private bool registrationFailed;

		private bool catalogReady;

		private float nextTick;

		private float nextSave;

		private float nextState;

		private float nextHello;

		private int sequence;

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

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

		private readonly Dictionary<int, Item> kits = new Dictionary<int, Item>();

		private Rect panel = new Rect(40f, 60f, 730f, 640f);

		private Vector2 turretScroll;

		private Vector2 gunScroll;

		private bool socketOpen;

		private string nameDraft = "";

		private string confirmAction = "";

		private int nameSerial;

		private CursorLockMode oldLock;

		private GUIStyle titleStyle;

		private GUIStyle bodyStyle;

		private GUIStyle slotStyle;

		private GUIStyle windowStyle;

		private GUIStyle buttonStyle;

		private GUIStyle accentButton;

		private GUIStyle dangerButton;

		private GUIStyle selectedButton;

		private GUIStyle inputStyle;

		private GUIStyle headerStyle;

		private GUIStyle statusStyle;

		private GUIStyle toggleStyle;

		private Texture2D steel;

		private Texture2D steelInset;

		private Texture2D steelEdge;

		private Texture2D cyan;

		private Texture2D cyanHover;

		private Texture2D orange;

		private Texture2D orangeHover;

		private Texture2D red;

		private Texture2D redHover;

		private float holdStart;

		private int holdSerial;

		private bool holdFired;

		private string holdAction;

		private GUIStyle turretLabelStyle;

		private bool audited;

		private float auditAfter;

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

		public static void Log(string text)
		{
			if ((Object)(object)Instance != (Object)null)
			{
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)text);
			}
		}

		private void Awake()
		{
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			Instance = this;
			savePath = Path.Combine(Paths.ConfigPath, "AASC-worlds.json");
			try
			{
				if (File.Exists(savePath))
				{
					save = Codec.FromJson<SaveData>(File.ReadAllText(savePath));
					if (save == null || save.version != 1 || save.worlds == null)
					{
						throw new Exception("Unrecognized save format");
					}
				}
			}
			catch (Exception ex)
			{
				persistenceReady = false;
				Status = "Turret Mod save could not be read. Purchases disabled to protect it.";
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
			GenericWriter<RequestMessage>.SetWrite((Action<Writer, RequestMessage>)delegate(Writer w, RequestMessage v)
			{
				w.WriteString(v.json);
			});
			GenericReader<RequestMessage>.SetRead((Func<Reader, RequestMessage>)((Reader r) => new RequestMessage
			{
				json = r.ReadStringAllocated()
			}));
			GenericWriter<StateMessage>.SetWrite((Action<Writer, StateMessage>)delegate(Writer w, StateMessage v)
			{
				w.WriteString(v.json);
			});
			GenericReader<StateMessage>.SetRead((Func<Reader, StateMessage>)((Reader r) => new StateMessage
			{
				json = r.ReadStringAllocated()
			}));
			GenericWriter<ReplyMessage>.SetWrite((Action<Writer, ReplyMessage>)delegate(Writer w, ReplyMessage v)
			{
				w.WriteString(v.json);
			});
			GenericReader<ReplyMessage>.SetRead((Func<Reader, ReplyMessage>)((Reader r) => new ReplyMessage
			{
				json = r.ReadStringAllocated()
			}));
			harmony = new Harmony("ponyfisher.howtofish.aasc");
			harmony.PatchAll(typeof(Plugin).Assembly);
			Log("TURRET MOD 0.1.23 loaded. Shared loose-item pickup and reduced imported base enabled.");
		}

		private void Update()
		{
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			if (Keyboard.current != null && ((ButtonControl)Keyboard.current.f2Key).wasPressedThisFrame)
			{
				Toggle(!Open);
			}
			UpdateHoldInteraction();
			if ((Object)(object)manager != (Object)(object)InstanceFinder.NetworkManager)
			{
				RegisterNetwork();
			}
			if (!registrationFailed && (Object)(object)Kit.Prefab == (Object)null)
			{
				try
				{
					Kit.Register();
				}
				catch (Exception ex)
				{
					registrationFailed = true;
					Status = "Turret item registration failed; see BepInEx log.";
					((BaseUnityPlugin)this).Logger.LogError((object)ex);
				}
			}
			if ((Object)(object)Kit.Prefab != (Object)null && !catalogReady)
			{
				BuildCatalog();
				catalogReady = true;
			}
			if (InstanceFinder.IsServerStarted && SaveManager.CurServerSave != null)
			{
				string name = SaveManager.CurServerSave.Name;
				if (world == null || world.name != name)
				{
					world = save.worlds.FirstOrDefault((WorldData w) => w.name == name);
					if (world == null)
					{
						world = new WorldData
						{
							name = name
						};
						save.worlds.Add(world);
					}
					Current = world.turrets;
					audited = false;
					auditAfter = Time.unscaledTime + 5f;
					missingSince.Clear();
					kits.Clear();
					lastSequence.Clear();
					rateLimit.Clear();
					foreach (TurretData item in Current)
					{
						item.nextShot = Time.time + 1f;
						item.reloading = false;
						item.lockedTarget = null;
						item.acquiring = false;
						item.hasTarget = false;
					}
				}
				if (Time.unscaledTime >= nextTick)
				{
					nextTick = Time.unscaledTime + 0.1f;
					ServerTick();
				}
				if (Time.unscaledTime >= nextState)
				{
					nextState = Time.unscaledTime + 0.25f;
					Broadcast();
				}
				if (Time.unscaledTime >= nextSave)
				{
					nextSave = Time.unscaledTime + 10f;
					Persist();
				}
			}
			else if (!InstanceFinder.IsClientStarted)
			{
				world = null;
				Current = new List<TurretData>();
				kits.Clear();
			}
			if (Open && InstanceFinder.IsClientStarted && !InstanceFinder.IsServerStarted && Time.unscaledTime >= nextHello)
			{
				nextHello = Time.unscaledTime + 3f;
				Send("hello");
			}
		}

		private void LateUpdate()
		{
			if (Open)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		private void RegisterNetwork()
		{
			if ((Object)(object)manager != (Object)null)
			{
				manager.ServerManager.UnregisterBroadcast<RequestMessage>((Action<NetworkConnection, RequestMessage, Channel>)Receive);
				manager.ClientManager.UnregisterBroadcast<StateMessage>((Action<StateMessage, Channel>)ReceiveState);
				manager.ClientManager.UnregisterBroadcast<ReplyMessage>((Action<ReplyMessage, Channel>)ReceiveReply);
			}
			manager = InstanceFinder.NetworkManager;
			if (!((Object)(object)manager == (Object)null))
			{
				manager.ServerManager.RegisterBroadcast<RequestMessage>((Action<NetworkConnection, RequestMessage, Channel>)Receive, true);
				manager.ClientManager.RegisterBroadcast<StateMessage>((Action<StateMessage, Channel>)ReceiveState);
				manager.ClientManager.RegisterBroadcast<ReplyMessage>((Action<ReplyMessage, Channel>)ReceiveReply);
			}
		}

		private static float ReadReload(Weapon weapon, GunClass kind)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Animation val = (Animation)AccessTools.Field(typeof(Tool), "_anim").GetValue(weapon);
			bool flag = (bool)AccessTools.Field(typeof(Weapon), "_hasLastReloadAnim").GetValue(weapon);
			AnimationState val2 = (((Object)(object)val == (Object)null) ? null : val[flag ? "ReloadLast" : "Reload"]);
			if ((TrackedReference)(object)val2 != (TrackedReference)null && val2.length > 0f)
			{
				return val2.length / Mathf.Max(0.01f, Mathf.Abs(val2.speed));
			}
			Log("Missing reload animation for " + ((Object)weapon).name + "; using fallback timing.");
			return Rules.Reload(kind, 0);
		}

		private void BuildCatalog()
		{
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			Dictionary<byte, Item> obj = (Dictionary<byte, Item>)AccessTools.Field(typeof(GameInfo), "_idToSpawnable").GetValue(null);
			Guns.Clear();
			foreach (Weapon item in from w in obj.Values.OfType<Weapon>()
				orderby ((Item)w).Cost
				select w)
			{
				WeaponInfo val = (WeaponInfo)AccessTools.Field(typeof(Weapon), "_weaponInfo").GetValue(item);
				if (val != null)
				{
					GunClass kind = Rules.Classify(((Object)item).name);
					int pellets = (int)AccessTools.Field(typeof(Weapon), "_projectileCountPerShot").GetValue(item);
					if (pellets > 1)
					{
						kind = GunClass.Shotgun;
					}
					else if ((Object)(object)item.Attachments != (Object)null && item.Attachments.UseSniperUi)
					{
						kind = GunClass.Sniper;
					}
					BulletUpgrade[] array = (BulletUpgrade[])AccessTools.Field(typeof(Attachments), "_bulletUpgrades").GetValue(item.Attachments);
					int val2 = (int)AccessTools.Field(typeof(Attachments), "_defaultAmmoPerMag").GetValue(item.Attachments);
					int val3 = (int)AccessTools.Field(typeof(Attachments), "_extendedAmmoPerMag").GetValue(item.Attachments);
					Guns.Add(new Gun
					{
						prefab = item,
						name = ((Object)item).name.Replace("(Clone)", ""),
						kind = kind,
						damage = Math.Max(1, val.ProjectileDamage) * Math.Max(1, pellets),
						ammoDamages = array?.Select((BulletUpgrade x) => Math.Max(1, x.Damage) * Math.Max(1, pellets)).ToArray(),
						price = Math.Max(250, ((Item)item).Cost),
						magazine = Math.Max(1, val2),
						extendedMagazine = Math.Max(Math.Max(1, val2), val3),
						reload = ReadReload(item, kind)
					});
				}
			}
			foreach (Gun gun in Guns)
			{
				Log("Gun " + gun.name + ": " + gun.kind.ToString() + ", range=" + Rules.Radius(gun.kind, 0) + ", magazine=" + gun.magazine + ", reload=" + gun.reload);
			}
			Log("Loaded " + Guns.Count + " socketable base-game guns.");
		}

		public TurretData Find(int id)
		{
			return Current.FirstOrDefault((TurretData t) => t.serial == id);
		}

		public Gun GetGun(TurretData t)
		{
			if (t.weapon != null)
			{
				return Guns.FirstOrDefault((Gun g) => ((Item)g.prefab).ID == t.weapon.ItemID);
			}
			return null;
		}

		public void Persist()
		{
			if (!persistenceReady || !InstanceFinder.IsServerStarted || world == null)
			{
				return;
			}
			try
			{
				string text = savePath + ".tmp";
				File.WriteAllText(text, Codec.ToJson(save, pretty: true));
				if (File.Exists(savePath))
				{
					File.Replace(text, savePath, savePath + ".bak");
				}
				else
				{
					File.Move(text, savePath);
				}
			}
			catch (Exception ex)
			{
				persistenceReady = false;
				Status = "Turret Mod could not save; purchases paused. Check disk access.";
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
		}

		public void Send(string action, int argument = 0, Vector3 position = default(Vector3), string text = null, Vector3 normal = default(Vector3))
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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)
			if ((Object)(object)Player.LocalPlayer == (Object)null)
			{
				Status = "Load a game first.";
				return;
			}
			Command command = new Command
			{
				action = action,
				serial = Selected,
				argument = argument,
				position = position,
				normal = normal,
				text = text,
				sequence = ++sequence
			};
			if (InstanceFinder.IsServerStarted)
			{
				Execute(Player.LocalPlayer, command, null);
			}
			else if ((Object)(object)manager != (Object)null && InstanceFinder.IsClientStarted)
			{
				manager.ClientManager.Broadcast<RequestMessage>(new RequestMessage
				{
					json = Codec.ToJson(command)
				}, (Channel)0);
				if (action != "hello")
				{
					Status = "Waiting for the host...";
				}
			}
		}

		private void Receive(NetworkConnection connection, RequestMessage message, Channel channel)
		{
			if (!InstanceFinder.IsServerStarted || message.json == null || message.json.Length > 1024)
			{
				return;
			}
			try
			{
				Command command = Codec.FromJson<Command>(message.json);
				if (command != null && command.protocol == 3 && command.sequence > 0 && (!lastSequence.TryGetValue(connection.ClientId, out var value) || command.sequence > value) && (!rateLimit.TryGetValue(connection.ClientId, out var value2) || !(Time.unscaledTime - value2 < 0.12f)))
				{
					lastSequence[connection.ClientId] = command.sequence;
					rateLimit[connection.ClientId] = Time.unscaledTime;
					Player val = ((IEnumerable<Player>)Object.FindObjectsByType<Player>()).FirstOrDefault((Func<Player, bool>)((Player p) => ((NetworkBehaviour)p).Owner == connection));
					if ((Object)(object)val != (Object)null)
					{
						Execute(val, command, connection);
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Rejected AASC request: " + ex.Message));
			}
		}

		private void Respond(Command cmd, NetworkConnection connection, string message, int selected = 0)
		{
			Reply value = new Reply
			{
				sequence = cmd.sequence,
				serial = selected,
				message = message
			};
			if (connection == (NetworkConnection)null || connection.IsLocalClient)
			{
				Status = message;
				if (selected > 0)
				{
					Selected = selected;
				}
			}
			else
			{
				manager.ServerManager.Broadcast<ReplyMessage>(connection, new ReplyMessage
				{
					json = Codec.ToJson(value)
				}, true, (Channel)0);
			}
		}

		private void ReceiveReply(ReplyMessage message, Channel channel)
		{
			Reply reply = Codec.FromJson<Reply>(message.json);
			Status = reply.message;
			if (reply.serial > 0)
			{
				Selected = reply.serial;
			}
		}

		private void ReceiveState(StateMessage message, Channel channel)
		{
			if (!InstanceFinder.IsServerStarted && message.json != null && message.json.Length <= 200000)
			{
				Snapshot snapshot = Codec.FromJson<Snapshot>(message.json);
				if (snapshot != null && snapshot.protocol == 3 && snapshot.turrets != null)
				{
					Current = snapshot.turrets;
				}
			}
		}

		private void Broadcast()
		{
			if ((Object)(object)manager != (Object)null && world != null)
			{
				manager.ServerManager.Broadcast<StateMessage>(new StateMessage
				{
					json = Codec.ToJson(new Snapshot
					{
						world = world.name,
						turrets = Current
					})
				}, true, (Channel)0);
			}
		}

		private void ScanKits()
		{
			kits.Clear();
			Item[] array = Object.FindObjectsByType<Item>((FindObjectsInactive)1);
			foreach (Item val in array)
			{
				if (Kit.Is(val) && ((NetworkBehaviour)val).IsSpawned && !((NetworkBehaviour)val).IsDeinitializing)
				{
					int num = Kit.Serial(val);
					if (num > 0 && !kits.ContainsKey(num))
					{
						kits.Add(num, val);
					}
				}
			}
		}

		private Item FindKit(int serial)
		{
			if (kits.TryGetValue(serial, out var value) && (Object)(object)value != (Object)null && ((NetworkBehaviour)value).IsSpawned && !((NetworkBehaviour)value).IsDeinitializing)
			{
				return value;
			}
			value = ((IEnumerable<Item>)Object.FindObjectsByType<Item>((FindObjectsInactive)1)).FirstOrDefault((Func<Item, bool>)((Item candidate) => Kit.Is(candidate) && ((NetworkBehaviour)candidate).IsSpawned && !((NetworkBehaviour)candidate).IsDeinitializing && Kit.Serial(candidate) == serial));
			if ((Object)(object)value != (Object)null)
			{
				kits[serial] = value;
			}
			return value;
		}

		public float ManagementDistance(TurretData turret, Player player)
		{
			//IL_0036: 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_003b: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			if (turret == null || (Object)(object)player == (Object)null)
			{
				return float.PositiveInfinity;
			}
			Item val = FindKit(turret.serial);
			Vector3 val2 = (((Object)(object)val != (Object)null) ? ((Component)val).transform.position : turret.position);
			float num = Vector3.Distance(((Component)player).transform.position, val2);
			if ((Object)(object)player.CamObject != (Object)null)
			{
				num = Mathf.Min(num, Vector3.Distance(player.CamObject.position, val2));
			}
			if ((Object)(object)val != (Object)null)
			{
				Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren<Collider>(true);
				foreach (Collider val3 in componentsInChildren)
				{
					if (!((Object)(object)val3 == (Object)null) && val3.enabled && !val3.isTrigger)
					{
						num = Mathf.Min(num, Vector3.Distance(((Component)player).transform.position, val3.ClosestPoint(((Component)player).transform.position)));
						if ((Object)(object)player.CamObject != (Object)null)
						{
							num = Mathf.Min(num, Vector3.Distance(player.CamObject.position, val3.ClosestPoint(player.CamObject.position)));
						}
					}
				}
			}
			return num;
		}

		private int OpenSlot(Player p)
		{
			int num = (int)AccessTools.Method(typeof(PlayerInventory), "GetTotalSlots", (Type[])null, (Type[])null).Invoke(p.Inventory, null);
			Item val = default(Item);
			for (byte b = 0; b < num; b++)
			{
				if (!p.Inventory._items.TryGetValue(b, ref val) || (Object)(object)val == (Object)null)
				{
					return b;
				}
			}
			return -1;
		}

		private Item SpawnForInventory(Item prefab, Player player, int slot, SavedItem data = null)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			Item val = Object.Instantiate<Item>(prefab, ((Component)player).transform.position + Vector3.up, Quaternion.identity, Server.Instance.DynamicObjectsHolder);
			if (data != null)
			{
				val.LoadFromSave(data);
			}
			InstanceFinder.ServerManager.Spawn(((Component)val).gameObject, (NetworkConnection)null, default(Scene));
			if (data != null)
			{
				val.ServerSetSkin(data.SkinIndex);
			}
			val.SetSyncedHolder(player, true);
			player.Inventory.AddItem((byte)slot, val);
			if (!player.Inventory.HasItemInInventory(val))
			{
				InstanceFinder.ServerManager.Despawn(((Component)val).gameObject, (DespawnType?)null);
				throw new Exception("The inventory did not accept the item; nothing was charged.");
			}
			return val;
		}

		private bool Ground(Player player, Vector3 requested, Vector3 requestedNormal, Item kit, out RaycastHit hit, out string reason)
		{
			//IL_0010: 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_002b: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00fe: 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_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			hit = default(RaycastHit);
			reason = "Look at a supported surface within 8 metres.";
			if (!Rules.Finite(requested.x) || !Rules.Finite(requested.y) || !Rules.Finite(requested.z) || !Rules.Finite(requestedNormal.x) || !Rules.Finite(requestedNormal.y) || !Rules.Finite(requestedNormal.z))
			{
				return false;
			}
			if (Vector3.Distance(requested, player.CamObject.position) > 8.35f || !Rules.SurfaceAllowed(requestedNormal.y))
			{
				return false;
			}
			Vector3 normalized = ((Vector3)(ref requestedNormal)).normalized;
			foreach (RaycastHit item in from val in Physics.RaycastAll(requested + normalized * 0.35f, -normalized, 0.7f, -1, (QueryTriggerInteraction)1)
				orderby ((RaycastHit)(ref val)).distance
				select val)
			{
				RaycastHit h = item;
				if (((Component)((RaycastHit)(ref h)).collider).gameObject.layer != LayerMask.NameToLayer("Water") && !((Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<Player>() != (Object)null) && !((Object)(object)((Component)((RaycastHit)(ref h)).collider).GetComponentInParent<Item>() != (Object)null) && Rules.SurfaceAllowed(((RaycastHit)(ref h)).normal.y) && !(Vector3.Dot(((RaycastHit)(ref h)).normal, normalized) < 0.5f))
				{
					if (Current.Any((TurretData t) => t.deployed && t.serial != Kit.Serial(kit) && Vector3.Distance(t.position, ((RaycastHit)(ref h)).point) < 0.55f))
					{
						reason = "Another turret is too close to that point.";
						return false;
					}
					hit = h;
					return true;
				}
			}
			return false;
		}

		private void Execute(Player player, Command cmd, NetworkConnection connection)
		{
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Expected O, but got Unknown
			//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_0509: Unknown result type (might be due to invalid IL or missing references)
			//IL_050f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b9f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ba9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0baf: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05de: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0601: Unknown result type (might be due to invalid IL or missing references)
			//IL_0605: Unknown result type (might be due to invalid IL or missing references)
			//IL_061d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0628: Unknown result type (might be due to invalid IL or missing references)
			//IL_062d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0632: Unknown result type (might be due to invalid IL or missing references)
			//IL_063c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0641: Unknown result type (might be due to invalid IL or missing references)
			//IL_0646: Unknown result type (might be due to invalid IL or missing references)
			//IL_064b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0650: Unknown result type (might be due to invalid IL or missing references)
			//IL_0657: Unknown result type (might be due to invalid IL or missing references)
			//IL_065c: Unknown result type (might be due to invalid IL or missing references)
			//IL_06be: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e8a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e8f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e96: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ea8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0eb3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ec3: Expected O, but got Unknown
			if (cmd.action == "hello")
			{
				Broadcast();
				return;
			}
			if (!persistenceReady || world == null || (Object)(object)Kit.Prefab == (Object)null || player.Dying.IsDead)
			{
				Respond(cmd, connection, "Turret Mod is not ready. Check the host's mod and save status.");
				return;
			}
			ScanKits();
			try
			{
				if (cmd.action == "buykit")
				{
					int num = OpenSlot(player);
					if (num < 0)
					{
						Respond(cmd, connection, "Free an inventory slot first.");
						return;
					}
					int num2 = Current.Count((TurretData t) => t.available && t.owner == player.SteamID);
					if (num2 >= 8 || Current.Count((TurretData t) => t.available) >= 32)
					{
						Respond(cmd, connection, "Turret limit reached (8 per player, 32 per world).");
						return;
					}
					int num3 = Rules.TurretPrice(num2);
					if (!Wallet.CanAfford(player, num3))
					{
						Respond(cmd, connection, "Not enough money. Your next empty turret costs $" + num3.ToString("N0") + ".");
						return;
					}
					if (save.nextSerial >= 16000000)
					{
						throw new Exception("Turret serial limit reached.");
					}
					int num4 = save.nextSerial++;
					Item val = SpawnForInventory(Kit.Prefab, player, num, new SavedItem
					{
						Exists = true,
						ItemID = 250,
						BettingMultiplier = num4
					});
					if (!Wallet.Charge(player, num3))
					{
						InstanceFinder.ServerManager.Despawn(((Component)val).gameObject, (DespawnType?)null);
						Respond(cmd, connection, "Payment failed; purchase cancelled.");
						return;
					}
					Current.Add(new TurretData
					{
						serial = num4,
						owner = player.SteamID,
						ownerName = player.SteamName,
						purchasePrice = num3
					});
					Persist();
					Broadcast();
					Respond(cmd, connection, "Turret kit purchased for $" + num3.ToString("N0") + " and added to your inventory.", num4);
					return;
				}
				TurretData turretData = Find(cmd.serial);
				Item val2 = FindKit(cmd.serial);
				if (turretData == null || (Object)(object)val2 == (Object)null)
				{
					Respond(cmd, connection, "That turret is no longer available.");
					return;
				}
				bool flag = (Object)(object)val2.SyncedHolder == (Object)(object)player;
				bool flag2 = (Object)(object)player.Holding.HeldItem == (Object)(object)val2 || (Object)(object)player.Holding.UninitializedHeldItem == (Object)(object)val2;
				bool flag3 = turretData.owner == player.SteamID;
				bool flag4 = (cmd.action == "pickup" && (Object)(object)val2.SyncedHolder == (Object)null) || cmd.action == "deploy";
				if (!flag3 && !flag4 && cmd.action != "takeownership")
				{
					Respond(cmd, connection, "This turret belongs to " + (string.IsNullOrWhiteSpace(turretData.ownerName) ? turretData.owner.ToString() : turretData.ownerName) + ". Pick it up and use Take ownership in F2 first.");
					return;
				}
				float distance = ManagementDistance(turretData, player);
				if (cmd.action != "recall" && !flag && !Rules.InManagementRange(distance))
				{
					Respond(cmd, connection, "Move within " + 12f.ToString("