Decompiled source of Tactical Kit v1.0.0

BepInEx/plugins/TacticalKit.dll

Decompiled an hour ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.LowLevel;
using UnityEngine.PlayerLoop;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("TacticalKitTest")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyTitle("TacticalKit")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TacticalKit;

internal static class Case
{
	private class Place
	{
		internal int x;

		internal int y;

		internal int w;

		internal int h;

		internal bool overflow;
	}

	private class Visual
	{
		internal RectTransform rect;

		internal Image block;

		internal Image icon;

		internal Image mark;
	}

	internal const int Slots = 24;

	internal static bool Open;

	private static readonly Dictionary<GrabbableObject, Place> places = new Dictionary<GrabbableObject, Place>();

	private static int cols;

	private static int rows;

	private static float lastFullTip;

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

	private static GameObject panel;

	private static RectTransform grid;

	private static float cell;

	private static TextMeshProUGUI info;

	private static Image ghost;

	private static RectTransform menu;

	private static readonly List<RectTransform> optionRects = new List<RectTransform>();

	private static readonly List<TextMeshProUGUI> optionTexts = new List<TextMeshProUGUI>();

	private static readonly List<string> options = new List<string>();

	private static readonly Dictionary<GrabbableObject, Visual> visuals = new Dictionary<GrabbableObject, Visual>();

	private static GrabbableObject moving;

	private static GrabbableObject menuFor;

	private static GrabbableObject lastClicked;

	private static int moveW;

	private static int moveH;

	private static float lastClickTime;

	private static string message = "";

	private static readonly Color Lining = new Color(0.06f, 0.07f, 0.075f, 0.97f);

	private static readonly Color CellColour = new Color(0.12f, 0.14f, 0.15f, 1f);

	private static readonly Color BlockColour = new Color(0.2f, 0.26f, 0.3f, 0.95f);

	private static readonly Color HeldColour = new Color(0.2f, 0.42f, 0.27f, 0.97f);

	private static readonly Color HoverColour = new Color(0.32f, 0.4f, 0.46f, 0.97f);

	internal static void Size(GrabbableObject g, out int w, out int h)
	{
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)g.itemProperties != (Object)null && sizes.TryGetValue(g.itemProperties, out var value))
		{
			w = value / 100;
			h = value % 100;
		}
		else
		{
			Bounds val = Firearms.LocalBounds(g);
			Vector3 lossyScale = ((Component)g).transform.lossyScale;
			float[] array = new float[3]
			{
				Mathf.Abs(((Bounds)(ref val)).size.x * lossyScale.x),
				Mathf.Abs(((Bounds)(ref val)).size.y * lossyScale.y),
				Mathf.Abs(((Bounds)(ref val)).size.z * lossyScale.z)
			};
			Array.Sort(array);
			float num = Mathf.Max(0.05f, Plugin.CaseCellSize.Value);
			w = Mathf.Max(1, Mathf.CeilToInt(array[2] / num - 0.3f));
			h = Mathf.Max(1, Mathf.CeilToInt(array[1] / num - 0.3f));
			if ((Object)(object)g.itemProperties != (Object)null)
			{
				sizes[g.itemProperties] = Mathf.Min(w, 99) * 100 + Mathf.Min(h, 99);
			}
		}
		w = Mathf.Clamp(w, 1, Mathf.Max(cols, 1));
		h = Mathf.Clamp(h, 1, Mathf.Max(rows, 1));
		if (h > w && h <= cols && w <= rows)
		{
			int num2 = w;
			w = h;
			h = num2;
		}
	}

	private static bool InGrid(GrabbableObject g)
	{
		if (g.itemProperties.twoHanded)
		{
			return Plugin.CaseTwoHanded.Value;
		}
		return true;
	}

	private static bool Free(int x, int y, int w, int h, GrabbableObject ignore)
	{
		if (x < 0 || y < 0 || x + w > cols || y + h > rows)
		{
			return false;
		}
		foreach (KeyValuePair<GrabbableObject, Place> place in places)
		{
			Place value = place.Value;
			if (!((Object)(object)place.Key == (Object)(object)ignore) && !value.overflow && x < value.x + value.w && value.x < x + w && y < value.y + value.h && value.y < y + h)
			{
				return false;
			}
		}
		return true;
	}

	private static bool FindSpot(ref int w, ref int h, GrabbableObject ignore, out int x, out int y)
	{
		for (int i = 0; i < 2; i++)
		{
			y = 0;
			while (y + h <= rows)
			{
				x = 0;
				while (x + w <= cols)
				{
					if (Free(x, y, w, h, ignore))
					{
						return true;
					}
					x++;
				}
				y++;
			}
			int num = w;
			w = h;
			h = num;
		}
		x = (y = -1);
		return false;
	}

	internal static bool CanTake(PlayerControllerB me, GrabbableObject g)
	{
		Sync(me);
		int num = 0;
		GrabbableObject[] itemSlots = me.ItemSlots;
		foreach (GrabbableObject val in itemSlots)
		{
			if ((Object)(object)val != (Object)null)
			{
				num++;
			}
		}
		if (num >= me.ItemSlots.Length)
		{
			return false;
		}
		if (!InGrid(g))
		{
			return true;
		}
		Size(g, out var w, out var h);
		int x;
		int y;
		return FindSpot(ref w, ref h, null, out x, out y);
	}

	internal static void TellFull(GrabbableObject g)
	{
		if (!(Time.realtimeSinceStartup - lastFullTip < 2f))
		{
			lastFullTip = Time.realtimeSinceStartup;
			HUDManager.Instance.DisplayTip("Case full", "No room for the " + g.itemProperties.itemName + ". Open the case [" + Plugin.CaseKey.Value + "] to rearrange or drop something.", true, false, "LC_Tip1");
		}
	}

	internal static string CountText(PlayerControllerB me)
	{
		int num = 0;
		foreach (Place value in places.Values)
		{
			if (!value.overflow)
			{
				num += value.w * value.h;
			}
		}
		return num + "/" + cols * rows;
	}

	private static void Sync(PlayerControllerB me)
	{
		int num = Mathf.Clamp(Plugin.CaseColumns.Value, 4, 16);
		int num2 = Mathf.Clamp(Plugin.CaseRows.Value, 3, 12);
		if (num != cols || num2 != rows)
		{
			cols = num;
			rows = num2;
			places.Clear();
			sizes.Clear();
			DropUi();
		}
		List<GrabbableObject> list = null;
		foreach (GrabbableObject key in places.Keys)
		{
			if ((Object)(object)key == (Object)null || Array.IndexOf(me.ItemSlots, key) < 0)
			{
				if (list == null)
				{
					list = new List<GrabbableObject>();
				}
				list.Add(key);
			}
		}
		if (list != null)
		{
			foreach (GrabbableObject item in list)
			{
				places.Remove(item);
			}
		}
		GrabbableObject[] itemSlots = me.ItemSlots;
		foreach (GrabbableObject val in itemSlots)
		{
			if (!((Object)(object)val == (Object)null) && !places.ContainsKey(val) && !((Object)(object)val.itemProperties == (Object)null) && InGrid(val))
			{
				Place place = new Place();
				Size(val, out place.w, out place.h);
				if (!FindSpot(ref place.w, ref place.h, val, out place.x, out place.y))
				{
					place.overflow = true;
				}
				places[val] = place;
			}
		}
		foreach (KeyValuePair<GrabbableObject, Place> place2 in places)
		{
			Place value = place2.Value;
			if (value.overflow && FindSpot(ref value.w, ref value.h, place2.Key, out var x, out var y))
			{
				value.x = x;
				value.y = y;
				value.overflow = false;
			}
		}
	}

	internal static bool Equip(PlayerControllerB me, int slot)
	{
		if (slot < 0 || slot >= me.ItemSlots.Length)
		{
			return false;
		}
		if (slot == me.currentItemSlot)
		{
			return true;
		}
		if (me.isGrabbingObjectAnimation || me.inSpecialInteractAnimation || Util.Throwing(me) || me.activatingItem || me.jetpackControls)
		{
			return false;
		}
		if (me.twoHanded && !Plugin.CaseTwoHanded.Value)
		{
			return false;
		}
		me.playerBodyAnimator.SetBool("GrabValidated", false);
		Util.SwitchToItemSlot(me, slot);
		Net.Publish("TK.Slot", Net.IntInt(Util.IndexOf(me), slot));
		Util.ResetSwitchTimer(me);
		GrabbableObject currentlyHeldObjectServer = me.currentlyHeldObjectServer;
		if ((Object)(object)currentlyHeldObjectServer != (Object)null && (Object)(object)currentlyHeldObjectServer.itemProperties.grabSFX != (Object)null)
		{
			AudioSource component = ((Component)currentlyHeldObjectServer).GetComponent<AudioSource>();
			if ((Object)(object)component != (Object)null)
			{
				component.PlayOneShot(currentlyHeldObjectServer.itemProperties.grabSFX, 0.6f);
			}
		}
		return true;
	}

	internal static int EmptySlot(PlayerControllerB me)
	{
		if (me.currentItemSlot >= 0 && me.currentItemSlot < me.ItemSlots.Length && (Object)(object)me.ItemSlots[me.currentItemSlot] == (Object)null)
		{
			return me.currentItemSlot;
		}
		for (int i = 0; i < me.ItemSlots.Length; i++)
		{
			if ((Object)(object)me.ItemSlots[i] == (Object)null)
			{
				return i;
			}
		}
		return -1;
	}

	internal static void ApplyRemoteSlot(int player, int slot)
	{
		PlayerControllerB val = Util.Player(player);
		if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)Util.Me) && slot >= 0 && slot < val.ItemSlots.Length && val.currentItemSlot != slot)
		{
			Util.SwitchToItemSlot(val, slot);
		}
	}

	internal static void Drop(PlayerControllerB me, GrabbableObject g)
	{
		int num = Array.IndexOf(me.ItemSlots, g);
		if (num >= 0)
		{
			if (num != me.currentItemSlot && !Equip(me, num))
			{
				Say("Your hands are busy.");
			}
			else
			{
				((MonoBehaviour)Runner.Instance).StartCoroutine(DropSoon(me, g));
			}
		}
	}

	private static IEnumerator DropSoon(PlayerControllerB me, GrabbableObject g)
	{
		yield return (object)new WaitForSeconds(0.25f);
		if ((Object)(object)me != (Object)null && (Object)(object)me.currentlyHeldObjectServer == (Object)(object)g && !me.isGrabbingObjectAnimation)
		{
			me.DiscardHeldObject(false, (NetworkObject)null, default(Vector3), true);
		}
	}

	internal static int NextSlot(PlayerControllerB p, bool forward)
	{
		GrabbableObject[] itemSlots = p.ItemSlots;
		int currentItemSlot = p.currentItemSlot;
		List<int> list = new List<int>();
		for (int i = 0; i < itemSlots.Length; i++)
		{
			if ((Object)(object)itemSlots[i] != (Object)null)
			{
				list.Add(i);
			}
		}
		int num = -1;
		if (currentItemSlot >= 0 && currentItemSlot < itemSlots.Length && (Object)(object)itemSlots[currentItemSlot] == (Object)null)
		{
			num = currentItemSlot;
		}
		else
		{
			for (int j = 0; j < itemSlots.Length; j++)
			{
				if (num >= 0)
				{
					break;
				}
				if ((Object)(object)itemSlots[j] == (Object)null)
				{
					num = j;
				}
			}
		}
		if (num >= 0)
		{
			list.Add(num);
		}
		if (list.Count == 0)
		{
			return Mathf.Clamp(currentItemSlot, 0, itemSlots.Length - 1);
		}
		int num2 = list.IndexOf(currentItemSlot);
		if (num2 < 0)
		{
			num2 = list.Count - 1;
		}
		int index = (forward ? ((num2 + 1) % list.Count) : ((num2 - 1 + list.Count) % list.Count));
		return list[index];
	}

	internal static void Tick()
	{
		PlayerControllerB me = Util.Me;
		if ((Object)(object)me == (Object)null || me.ItemSlots == null)
		{
			if (Open)
			{
				Close(null);
			}
			places.Clear();
			return;
		}
		Sync(me);
		bool flag = me.isPlayerControlled && !me.isPlayerDead && !me.inTerminalMenu && Util.CanUseKeys(me);
		if (Open && (!flag || !me.inSpecialMenu))
		{
			Close(me);
			return;
		}
		if (Util.Pressed(Plugin.CaseKey.Value) && (Open || flag))
		{
			if (Open)
			{
				Close(me);
			}
			else if (!me.inSpecialMenu)
			{
				OpenCase(me);
			}
		}
		if (Open)
		{
			UpdateUi(me);
		}
	}

	internal static void OpenCase(PlayerControllerB me)
	{
		Hud.Tick();
		BuildUi();
		Open = true;
		moving = null;
		menuFor = null;
		message = "";
		me.inSpecialMenu = true;
		Cursor.lockState = (CursorLockMode)0;
		Cursor.visible = true;
		if ((Object)(object)me.cursorIcon != (Object)null)
		{
			((Behaviour)me.cursorIcon).enabled = false;
		}
		if ((Object)(object)me.cursorTip != (Object)null)
		{
			((TMP_Text)me.cursorTip).text = "";
		}
		panel.SetActive(true);
	}

	internal static void Close(PlayerControllerB me)
	{
		Open = false;
		moving = null;
		menuFor = null;
		if ((Object)(object)panel != (Object)null)
		{
			panel.SetActive(false);
		}
		if ((Object)(object)me != (Object)null && me.inSpecialMenu)
		{
			me.inSpecialMenu = false;
			Cursor.lockState = (CursorLockMode)1;
			Cursor.visible = false;
		}
	}

	private static void DropUi()
	{
		if ((Object)(object)panel != (Object)null)
		{
			Object.Destroy((Object)(object)panel);
		}
		panel = null;
		visuals.Clear();
		optionRects.Clear();
		optionTexts.Clear();
	}

	private static void BuildUi()
	{
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Expected O, but got Unknown
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Expected O, but got Unknown
		//IL_0235: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_023b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_0269: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_030b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0316: Unknown result type (might be due to invalid IL or missing references)
		//IL_0348: Unknown result type (might be due to invalid IL or missing references)
		//IL_0360: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03de: Unknown result type (might be due to invalid IL or missing references)
		//IL_0407: Unknown result type (might be due to invalid IL or missing references)
		//IL_040e: Expected O, but got Unknown
		//IL_0445: Unknown result type (might be due to invalid IL or missing references)
		//IL_044a: Unknown result type (might be due to invalid IL or missing references)
		//IL_044b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0452: Unknown result type (might be due to invalid IL or missing references)
		//IL_0454: Unknown result type (might be due to invalid IL or missing references)
		//IL_0455: Unknown result type (might be due to invalid IL or missing references)
		//IL_045c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0472: 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_04a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_050d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0528: Unknown result type (might be due to invalid IL or missing references)
		//IL_0537: Unknown result type (might be due to invalid IL or missing references)
		//IL_0546: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)panel != (Object)null)
		{
			return;
		}
		cell = Mathf.Floor(Mathf.Min(new float[3]
		{
			78f,
			1500f / (float)cols,
			720f / (float)rows
		}));
		float num = (float)cols * cell;
		float num2 = (float)rows * cell;
		panel = new GameObject("TacticalKitCase");
		panel.transform.SetParent((Transform)(object)Hud.Root, false);
		Hud.Stretch(panel.AddComponent<RectTransform>());
		Image val = panel.AddComponent<Image>();
		((Graphic)val).color = new Color(0f, 0f, 0f, 0.55f);
		((Graphic)val).raycastTarget = false;
		Hud.Panel(panel.transform, "Frame", new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), new Vector2(num + 64f, num2 + 175f), new Color(0.24f, 0.17f, 0.11f, 0.98f));
		Hud.Panel(panel.transform, "Lining", new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), new Vector2(num + 24f, num2 + 135f), Lining);
		TextMeshProUGUI val2 = Hud.Text(panel.transform, "Title", new Vector2(0.5f, 0.5f), new Vector2(0f, num2 / 2f + 52f), new Vector2(num, 40f), 30f, (TextAlignmentOptions)514);
		((TMP_Text)val2).text = "ATTACHE CASE";
		((Graphic)val2).color = new Color(0.86f, 0.78f, 0.6f, 1f);
		GameObject val3 = new GameObject("Grid");
		val3.transform.SetParent(panel.transform, false);
		grid = val3.AddComponent<RectTransform>();
		RectTransform obj = grid;
		Vector2 anchorMin = (grid.anchorMax = new Vector2(0.5f, 0.5f));
		obj.anchorMin = anchorMin;
		grid.pivot = new Vector2(0f, 1f);
		grid.sizeDelta = new Vector2(num, num2);
		grid.anchoredPosition = new Vector2((0f - num) / 2f, num2 / 2f + 20f);
		for (int i = 0; i < rows; i++)
		{
			for (int j = 0; j < cols; j++)
			{
				Cell(grid, j, i, 1, 1, CellColour, 2f);
			}
		}
		info = Hud.Text(panel.transform, "Info", new Vector2(0.5f, 0.5f), new Vector2(0f, (0f - num2) / 2f - 18f), new Vector2(num, 34f), 22f, (TextAlignmentOptions)514);
		TextMeshProUGUI val5 = Hud.Text(panel.transform, "Keys", new Vector2(0.5f, 0.5f), new Vector2(0f, (0f - num2) / 2f - 46f), new Vector2(num, 26f), 16f, (TextAlignmentOptions)514);
		((TMP_Text)val5).text = "[LMB] choose   double [LMB] move   [R] rotate   [RMB] cancel   [" + Plugin.CaseKey.Value + "] close";
		((Graphic)val5).color = new Color(0.62f, 0.66f, 0.66f, 1f);
		ghost = Cell(grid, 0, 0, 1, 1, new Color(0.3f, 0.9f, 0.4f, 0.35f), 0f);
		((Component)ghost).gameObject.SetActive(false);
		GameObject val6 = new GameObject("Menu");
		val6.transform.SetParent((Transform)(object)grid, false);
		menu = val6.AddComponent<RectTransform>();
		RectTransform obj2 = menu;
		RectTransform obj3 = menu;
		Vector2 val7 = (menu.pivot = new Vector2(0f, 1f));
		Vector2 anchorMin2 = (obj3.anchorMax = val7);
		obj2.anchorMin = anchorMin2;
		menu.sizeDelta = new Vector2(170f, 152f);
		for (int k = 0; k < 4; k++)
		{
			Image val10 = Hud.Panel((Transform)(object)menu, "Option" + k, new Vector2(0f, 1f), Vector2.zero, new Vector2(170f, 34f), new Color(0.1f, 0.12f, 0.13f, 0.97f));
			RectTransform rectTransform = ((Graphic)val10).rectTransform;
			rectTransform.pivot = new Vector2(0f, 1f);
			rectTransform.anchoredPosition = new Vector2(0f, (float)(-k) * 38f);
			TextMeshProUGUI item = Hud.Text((Transform)(object)rectTransform, "Text", new Vector2(0f, 0.5f), new Vector2(14f, 0f), new Vector2(150f, 30f), 20f, (TextAlignmentOptions)513);
			optionRects.Add(rectTransform);
			optionTexts.Add(item);
		}
		val6.SetActive(false);
		panel.SetActive(false);
	}

	private static Image Cell(RectTransform parent, int x, int y, int w, int h, Color colour, float gap)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		Image val = Hud.Panel((Transform)(object)parent, "Cell", new Vector2(0f, 1f), Vector2.zero, Vector2.zero, colour);
		RectTransform rectTransform = ((Graphic)val).rectTransform;
		rectTransform.pivot = new Vector2(0f, 1f);
		Lay(rectTransform, x, y, w, h, gap);
		return val;
	}

	private static void Lay(RectTransform r, float x, float y, float w, float h, float gap)
	{
		//IL_0022: 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)
		r.anchoredPosition = new Vector2(x * cell + gap / 2f, (0f - y) * cell - gap / 2f);
		r.sizeDelta = new Vector2(w * cell - gap, h * cell - gap);
	}

	private static Visual VisualFor(GrabbableObject g)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_009f: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		if (visuals.TryGetValue(g, out var value))
		{
			return value;
		}
		value = new Visual();
		value.block = Cell(grid, 0, 0, 1, 1, BlockColour, 4f);
		value.rect = ((Graphic)value.block).rectTransform;
		value.icon = Hud.Panel((Transform)(object)value.rect, "Icon", new Vector2(0.5f, 0.5f), Vector2.zero, Vector2.zero, Color.white);
		Hud.Stretch(((Graphic)value.icon).rectTransform);
		((Graphic)value.icon).rectTransform.offsetMin = new Vector2(4f, 4f);
		((Graphic)value.icon).rectTransform.offsetMax = new Vector2(-4f, -4f);
		value.icon.preserveAspect = true;
		value.mark = Hud.Panel((Transform)(object)value.rect, "Laser", new Vector2(1f, 1f), new Vector2(-9f, -9f), new Vector2(9f, 9f), new Color(1f, 0.2f, 0.12f, 1f));
		visuals[g] = value;
		((Transform)menu).SetAsLastSibling();
		((Component)ghost).transform.SetAsLastSibling();
		return value;
	}

	private static void Say(string text)
	{
		message = text;
	}

	private static void UpdateUi(PlayerControllerB me)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_024d: 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_02be: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e4: 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_029c: Unknown result type (might be due to invalid IL or missing references)
		//IL_05af: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
		Mouse current = Mouse.current;
		Keyboard current2 = Keyboard.current;
		if (current == null)
		{
			return;
		}
		Vector2 val = ((InputControl<Vector2>)(object)((Pointer)current).position).ReadValue();
		Vector2 val2 = default(Vector2);
		RectTransformUtility.ScreenPointToLocalPointInRectangle(grid, val, (Camera)null, ref val2);
		float num = val2.x / cell;
		float num2 = (0f - val2.y) / cell;
		List<GrabbableObject> list = null;
		foreach (GrabbableObject key2 in visuals.Keys)
		{
			if ((Object)(object)key2 == (Object)null || !places.ContainsKey(key2))
			{
				if (list == null)
				{
					list = new List<GrabbableObject>();
				}
				list.Add(key2);
			}
		}
		if (list != null)
		{
			foreach (GrabbableObject item in list)
			{
				Object.Destroy((Object)(object)((Component)visuals[item].rect).gameObject);
				visuals.Remove(item);
			}
			if ((Object)(object)moving != (Object)null && !places.ContainsKey(moving))
			{
				moving = null;
			}
			if ((Object)(object)menuFor != (Object)null && !places.ContainsKey(menuFor))
			{
				CloseMenu();
			}
		}
		GrabbableObject val3 = null;
		int num3 = 0;
		foreach (KeyValuePair<GrabbableObject, Place> place2 in places)
		{
			GrabbableObject key = place2.Key;
			Place value = place2.Value;
			Visual visual = VisualFor(key);
			if (value.overflow)
			{
				Lay(visual.rect, (float)num3++ * 1.1f, (float)rows + 0.35f, 1f, 1f, 4f);
			}
			else
			{
				Lay(visual.rect, value.x, value.y, value.w, value.h, 4f);
			}
			visual.icon.sprite = key.itemProperties.itemIcon;
			((Behaviour)visual.icon).enabled = (Object)(object)key.itemProperties.itemIcon != (Object)null;
			((Behaviour)visual.mark).enabled = Lasers.Has(key);
			bool flag = RectTransformUtility.RectangleContainsScreenPoint(visual.rect, val, (Camera)null);
			if (flag && (Object)(object)moving == (Object)null)
			{
				val3 = key;
			}
			((Graphic)visual.block).color = (Color)(((Object)(object)key == (Object)(object)me.currentlyHeldObjectServer) ? HeldColour : ((flag || (Object)(object)key == (Object)(object)menuFor) ? HoverColour : (value.overflow ? new Color(0.45f, 0.15f, 0.12f, 0.95f) : BlockColour)));
			((Graphic)visual.icon).color = (Color)(((Object)(object)key == (Object)(object)moving) ? new Color(1f, 1f, 1f, 0.3f) : Color.white);
		}
		GrabbableObject val4 = moving ?? val3 ?? menuFor;
		if ((Object)(object)val4 != (Object)null)
		{
			((TMP_Text)info).text = Describe(me, val4);
		}
		else
		{
			((TMP_Text)info).text = ((message.Length > 0) ? message : ("<color=#9aa4a8>" + CountText(me) + " cells used</color>"));
		}
		bool wasPressedThisFrame = current.leftButton.wasPressedThisFrame;
		bool wasPressedThisFrame2 = current.rightButton.wasPressedThisFrame;
		bool flag2 = current2 != null && ((ButtonControl)current2[(Key)32]).wasPressedThisFrame;
		if ((Object)(object)moving != (Object)null)
		{
			if (flag2)
			{
				int num4 = moveW;
				moveW = moveH;
				moveH = num4;
			}
			int num5 = Mathf.RoundToInt(num - (float)moveW / 2f);
			int num6 = Mathf.RoundToInt(num2 - (float)moveH / 2f);
			num5 = Mathf.Clamp(num5, 0, Mathf.Max(0, cols - moveW));
			num6 = Mathf.Clamp(num6, 0, Mathf.Max(0, rows - moveH));
			bool flag3 = moveW <= cols && moveH <= rows && Free(num5, num6, moveW, moveH, moving);
			((Component)ghost).gameObject.SetActive(true);
			Lay(((Graphic)ghost).rectTransform, num5, num6, moveW, moveH, 2f);
			((Graphic)ghost).color = (flag3 ? new Color(0.3f, 0.9f, 0.4f, 0.35f) : new Color(1f, 0.25f, 0.2f, 0.35f));
			if (wasPressedThisFrame)
			{
				if (flag3)
				{
					Place place = places[moving];
					place.x = num5;
					place.y = num6;
					place.w = moveW;
					place.h = moveH;
					place.overflow = false;
					moving = null;
					message = "";
				}
				else
				{
					Say("It does not fit there.");
				}
			}
			else if (wasPressedThisFrame2)
			{
				moving = null;
			}
		}
		else
		{
			((Component)ghost).gameObject.SetActive(false);
			if ((Object)(object)menuFor != (Object)null)
			{
				if (wasPressedThisFrame)
				{
					int num7 = -1;
					for (int i = 0; i < options.Count; i++)
					{
						if (RectTransformUtility.RectangleContainsScreenPoint(optionRects[i], val, (Camera)null))
						{
							num7 = i;
						}
					}
					GrabbableObject g = menuFor;
					CloseMenu();
					if (num7 >= 0)
					{
						Choose(me, g, options[num7]);
					}
					else if ((Object)(object)val3 != (Object)null)
					{
						Click(val3);
					}
				}
				else if (wasPressedThisFrame2)
				{
					CloseMenu();
				}
				else if (flag2)
				{
					Choose(me, menuFor, "Rotate");
				}
			}
			else if (wasPressedThisFrame && (Object)(object)val3 != (Object)null)
			{
				Click(val3);
			}
			else if (flag2 && (Object)(object)val3 != (Object)null)
			{
				Choose(me, val3, "Rotate");
			}
		}
		((Component)menu).gameObject.SetActive((Object)(object)menuFor != (Object)null);
	}

	private static void Click(GrabbableObject g)
	{
		if ((Object)(object)g == (Object)(object)lastClicked && Time.realtimeSinceStartup - lastClickTime < 0.35f)
		{
			StartMoving(g);
			lastClicked = null;
		}
		else
		{
			lastClicked = g;
			lastClickTime = Time.realtimeSinceStartup;
			OpenMenu(g);
		}
	}

	private static void StartMoving(GrabbableObject g)
	{
		if (places.TryGetValue(g, out var value))
		{
			CloseMenu();
			moving = g;
			moveW = value.w;
			moveH = value.h;
		}
	}

	private static void OpenMenu(GrabbableObject g)
	{
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB me = Util.Me;
		menuFor = g;
		options.Clear();
		options.Add(((Object)(object)g == (Object)(object)me.currentlyHeldObjectServer) ? "Put away" : "Equip");
		options.Add("Move");
		options.Add("Rotate");
		options.Add("Drop");
		for (int i = 0; i < optionRects.Count; i++)
		{
			((Component)optionRects[i]).gameObject.SetActive(i < options.Count);
			if (i < options.Count)
			{
				((TMP_Text)optionTexts[i]).text = options[i];
			}
		}
		Place place = places[g];
		float num = (place.overflow ? 1.2f : ((float)(place.x + place.w))) * cell + 6f;
		if (num + 170f > (float)cols * cell + 120f)
		{
			num = (place.overflow ? 0f : ((float)place.x)) * cell - 176f;
		}
		menu.anchoredPosition = new Vector2(num, (float)(-(place.overflow ? rows : place.y)) * cell);
		((Transform)menu).SetAsLastSibling();
	}

	private static void CloseMenu()
	{
		menuFor = null;
	}

	private static void Choose(PlayerControllerB me, GrabbableObject g, string option)
	{
		message = "";
		int slot = Array.IndexOf(me.ItemSlots, g);
		switch (option)
		{
		case "Equip":
			if (!Equip(me, slot))
			{
				Say("Your hands are busy.");
			}
			break;
		case "Put away":
		{
			int num = EmptySlot(me);
			if (num < 0 || !Equip(me, num))
			{
				Say("Cannot put it away right now.");
			}
			break;
		}
		case "Move":
			StartMoving(g);
			break;
		case "Rotate":
		{
			Place place = places[g];
			if (!place.overflow)
			{
				if (Free(place.x, place.y, place.h, place.w, g))
				{
					int w = place.w;
					place.w = place.h;
					place.h = w;
				}
				else
				{
					Say("No room to turn it here.");
				}
			}
			break;
		}
		case "Drop":
			Drop(me, g);
			break;
		}
	}

	private static string Describe(PlayerControllerB me, GrabbableObject g)
	{
		Item itemProperties = g.itemProperties;
		string text = itemProperties.itemName;
		if (Lasers.Has(g))
		{
			text += "  <color=#ff4433>laser sight</color>";
		}
		if (itemProperties.isScrap && g.scrapValue > 0)
		{
			object obj = text;
			text = string.Concat(obj, "   <color=#b9e08a>$", g.scrapValue, "</color>");
		}
		int num = Mathf.RoundToInt(Mathf.Clamp(itemProperties.weight - 1f, 0f, 10f) * 105f);
		if (num > 0)
		{
			object obj2 = text;
			text = string.Concat(obj2, "   <color=#9aa4a8>", num, " lb</color>");
		}
		if ((Object)(object)g == (Object)(object)me.currentlyHeldObjectServer)
		{
			text += "   <color=#7fd38f>in hand</color>";
		}
		if (places.TryGetValue(g, out var value) && value.overflow)
		{
			text += "   <color=#ff7766>no room - drop or rearrange</color>";
		}
		return text;
	}
}
internal static class Compat
{
	internal static bool HasMrapi;

	private static FieldInfo presentField;

	private static PropertyInfo presentProperty;

	private static Type bodyType;

	internal static void PatchModelReplacement(Harmony h)
	{
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Expected O, but got Unknown
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Expected O, but got Unknown
		Type type = Util.FindType("ModelReplacement.ViewStateManager");
		Type type2 = Util.FindType("ModelReplacement.ModelReplacementAPI");
		if (type == null || type2 == null)
		{
			Plugin.Log.LogInfo((object)"ModelReplacementAPI is not installed; third person handles the plain suits itself.");
			return;
		}
		MethodInfo methodInfo = AccessTools.Method(type, "Safe3rdPersonActive", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(type, "SafeFix3rdPerson", (Type[])null, (Type[])null);
		presentField = AccessTools.Field(type2, "thirdPersonPresent");
		if (presentField == null)
		{
			presentProperty = AccessTools.Property(type2, "thirdPersonPresent");
		}
		if (methodInfo == null || methodInfo2 == null || (presentField == null && presentProperty == null))
		{
			Plugin.Log.LogWarning((object)"This ModelReplacementAPI version is unknown to the mod; model suits stay first person.");
			return;
		}
		h.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Compat).GetMethod("ActivePrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		h.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(Compat).GetMethod("SkipPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		bodyType = Util.FindType("ModelReplacement.BodyReplacementBase");
		HasMrapi = true;
		Plugin.Log.LogInfo((object)"ModelReplacementAPI found: model suits follow the third-person view.");
	}

	internal static void Tick()
	{
		if (!HasMrapi)
		{
			return;
		}
		try
		{
			if (presentField != null)
			{
				if (!(bool)presentField.GetValue(null))
				{
					presentField.SetValue(null, true);
				}
			}
			else if (!(bool)presentProperty.GetValue(null, null))
			{
				presentProperty.SetValue(null, true, null);
			}
		}
		catch (Exception ex)
		{
			HasMrapi = false;
			Plugin.Log.LogWarning((object)("Could not talk to ModelReplacementAPI: " + ex.Message));
		}
	}

	private static bool ActivePrefix(ref bool __result)
	{
		__result = ThirdPerson.Active;
		return false;
	}

	private static bool SkipPrefix()
	{
		return false;
	}

	internal static bool HasReplacement(PlayerControllerB p)
	{
		if (bodyType == null || (Object)(object)p == (Object)null)
		{
			return false;
		}
		Component component = ((Component)p).GetComponent(bodyType);
		Behaviour val = (Behaviour)(object)((component is Behaviour) ? component : null);
		if ((Object)(object)val != (Object)null)
		{
			return val.isActiveAndEnabled;
		}
		return false;
	}
}
internal static class Firearms
{
	private static readonly Dictionary<Type, bool> armoryTypes = new Dictionary<Type, bool>();

	private static FieldInfo configId;

	private static PropertyInfo landmarks;

	private static MethodInfo tryGetBore;

	private static bool armoryLooked;

	private static readonly string[] notGuns = new string[3] { "chainsaw", "flame", "molotov" };

	private static readonly string[] notAGunWords = new string[11]
	{
		"shell", "ammo", "round", "bullet", "magazine", "box", "cartridge", "rocket", "fuel", "toy",
		"water"
	};

	private static readonly string[] gunWords = new string[11]
	{
		"shotgun", "rifle", "pistol", "revolver", "handgun", "gun", "smg", "carbine", "launcher", "magnum",
		"musket"
	};

	private static FieldInfo fpActive;

	private static FieldInfo fpRoot;

	private static FieldInfo fpMuzzle;

	private static FieldInfo fpHasMuzzle;

	private static PropertyInfo fpGrabbable;

	private static bool fpLooked;

	private static readonly Dictionary<Item, Bounds> boundsCache = new Dictionary<Item, Bounds>();

	internal static bool IsFirearm(GrabbableObject g)
	{
		if ((Object)(object)g == (Object)null || (Object)(object)g.itemProperties == (Object)null || g is LaserSightItem)
		{
			return false;
		}
		if (g is ShotgunItem)
		{
			return true;
		}
		string text = ArmoryId(g);
		if (text != null)
		{
			string text2 = text.ToLowerInvariant();
			if (text2 == "grenade")
			{
				return false;
			}
			string[] array = notGuns;
			foreach (string value in array)
			{
				if (text2.Contains(value))
				{
					return false;
				}
			}
			return true;
		}
		string text3 = (g.itemProperties.itemName ?? "").ToLowerInvariant();
		string[] array2 = notAGunWords;
		foreach (string value2 in array2)
		{
			if (text3.Contains(value2))
			{
				return false;
			}
		}
		string[] array3 = gunWords;
		foreach (string value3 in array3)
		{
			if (text3.Contains(value3))
			{
				return true;
			}
		}
		return false;
	}

	internal static string ArmoryId(GrabbableObject g)
	{
		Type type = ((object)g).GetType();
		if (!armoryTypes.TryGetValue(type, out var value))
		{
			value = false;
			Type type2 = type;
			while (type2 != null)
			{
				if (type2.Name == "Y4NGZWeaponBase")
				{
					value = true;
					Look(type2);
					break;
				}
				type2 = type2.BaseType;
			}
			armoryTypes[type] = value;
		}
		if (!value || configId == null)
		{
			return null;
		}
		return configId.GetValue(g) as string;
	}

	private static void Look(Type weaponBase)
	{
		if (!armoryLooked)
		{
			armoryLooked = true;
			configId = AccessTools.Field(weaponBase, "ConfigId");
			landmarks = AccessTools.Property(weaponBase, "Landmarks");
			Type type = weaponBase.Assembly.GetType("Y4NGZUpgrades.Weapons.WeaponLandmarkResolver");
			if (type != null)
			{
				tryGetBore = AccessTools.Method(type, "TryGetBore", (Type[])null, (Type[])null);
			}
			Plugin.Log.LogInfo((object)("BetterArmory found: its guns take the laser sight" + ((tryGetBore != null) ? ", muzzles from its own landmarks." : ".")));
		}
	}

	internal static void Muzzle(GrabbableObject g, out Vector3 position, out Vector3 forward)
	{
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: 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_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//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_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		ShotgunItem val = (ShotgunItem)(object)((g is ShotgunItem) ? g : null);
		if ((Object)(object)val != (Object)null && (Object)(object)val.shotgunRayPoint != (Object)null)
		{
			position = val.shotgunRayPoint.position;
			forward = val.shotgunRayPoint.forward;
		}
		else
		{
			if (ArmoryId(g) != null && (Object)(object)g.playerHeldBy != (Object)null && (Object)(object)g.playerHeldBy == (Object)(object)Util.Me && !ThirdPerson.Moved && ArmoryViewMuzzle(g, out position, out forward))
			{
				return;
			}
			if (tryGetBore != null && landmarks != null && ArmoryId(g) != null)
			{
				try
				{
					object[] array = new object[4]
					{
						((Component)g).gameObject,
						landmarks.GetValue(g, null),
						Vector3.zero,
						Vector3.zero
					};
					if ((bool)tryGetBore.Invoke(null, array))
					{
						position = (Vector3)array[2];
						forward = (Vector3)array[3];
						return;
					}
				}
				catch (Exception ex)
				{
					tryGetBore = null;
					Plugin.Log.LogWarning((object)("BetterArmory muzzle lookup failed, using the model's front end: " + ex.Message));
				}
			}
			Bounds val2 = LocalBounds(g);
			Vector3 val3 = ((((Bounds)(ref val2)).size.z >= ((Bounds)(ref val2)).size.x) ? Vector3.forward : Vector3.right);
			position = ((Component)g).transform.TransformPoint(((Bounds)(ref val2)).center + Vector3.Scale(val3, ((Bounds)(ref val2)).extents));
			forward = ((Component)g).transform.TransformDirection(val3);
		}
	}

	private static bool ArmoryViewMuzzle(GrabbableObject g, out Vector3 position, out Vector3 forward)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: 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_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		position = (forward = Vector3.zero);
		if (!fpLooked)
		{
			fpLooked = true;
			Type type = Util.FindType("Y4NGZUpgrades.Weapons.WeaponFirstPersonAnimation");
			Type type2 = Util.FindType("Y4NGZUpgrades.Weapons.IY4NGZFpWeapon");
			if (type != null && type2 != null)
			{
				fpActive = AccessTools.Field(type, "_activeWeapon");
				fpRoot = AccessTools.Field(type, "_propRoot");
				fpMuzzle = AccessTools.Field(type, "_propMuzzleLocal");
				fpHasMuzzle = AccessTools.Field(type, "_hasPropMuzzleLocal");
				fpGrabbable = type2.GetProperty("FpGrabbable");
			}
		}
		if (fpActive == null || fpRoot == null || fpMuzzle == null || fpHasMuzzle == null || fpGrabbable == null)
		{
			return false;
		}
		try
		{
			object value = fpActive.GetValue(null);
			if (value == null || (Object)/*isinst with value type is only supported in some contexts*/ != (Object)(object)g)
			{
				return false;
			}
			object? value2 = fpRoot.GetValue(null);
			Transform val = (Transform)((value2 is Transform) ? value2 : null);
			if ((Object)(object)val == (Object)null || !(bool)fpHasMuzzle.GetValue(null))
			{
				return false;
			}
			position = val.TransformPoint((Vector3)fpMuzzle.GetValue(null));
			forward = ((Component)g.playerHeldBy.gameplayCamera).transform.forward;
			return true;
		}
		catch (Exception ex)
		{
			fpActive = null;
			Plugin.Log.LogWarning((object)("BetterArmory first-person muzzle lookup failed: " + ex.Message));
			return false;
		}
	}

	internal static void ShotRay(GrabbableObject g, out Vector3 origin, out Vector3 direction)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: 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_0088: 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_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_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: 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_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		PlayerControllerB playerHeldBy = g.playerHeldBy;
		if ((Object)(object)playerHeldBy != (Object)null && (Object)(object)playerHeldBy.gameplayCamera != (Object)null && !g.isHeldByEnemy)
		{
			Vector3 val = ((Component)playerHeldBy.gameplayCamera).transform.position;
			Quaternion val2 = ((Component)playerHeldBy.gameplayCamera).transform.rotation;
			if ((Object)(object)playerHeldBy == (Object)(object)Util.Me && ThirdPerson.Moved)
			{
				val = ThirdPerson.HeadPosition;
				val2 = ThirdPerson.HeadRotation;
			}
			origin = val;
			if (g is ShotgunItem)
			{
				origin -= val2 * Vector3.up * 0.45f;
			}
			direction = val2 * Vector3.forward;
		}
		else
		{
			Muzzle(g, out origin, out direction);
		}
	}

	internal static Bounds LocalBounds(GrabbableObject g)
	{
		//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_0032: 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_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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: 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_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: 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_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_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)g.itemProperties != (Object)null && boundsCache.TryGetValue(g.itemProperties, out var value))
		{
			return value;
		}
		bool any = false;
		value = new Bounds(Vector3.zero, Vector3.zero);
		Matrix4x4 worldToLocalMatrix = ((Component)g).transform.worldToLocalMatrix;
		MeshFilter[] componentsInChildren = ((Component)g).GetComponentsInChildren<MeshFilter>(true);
		foreach (MeshFilter val in componentsInChildren)
		{
			if (!((Object)(object)val.sharedMesh == (Object)null) && !((Object)(object)((Component)val).GetComponent<Renderer>() == (Object)null))
			{
				Encapsulate(ref value, ref any, worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix, val.sharedMesh.bounds);
			}
		}
		SkinnedMeshRenderer[] componentsInChildren2 = ((Component)g).GetComponentsInChildren<SkinnedMeshRenderer>(true);
		foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
		{
			if (!((Object)(object)val2.sharedMesh == (Object)null))
			{
				Encapsulate(ref value, ref any, worldToLocalMatrix * ((Component)val2).transform.localToWorldMatrix, val2.sharedMesh.bounds);
			}
		}
		if (!any)
		{
			value = new Bounds(Vector3.zero, new Vector3(0.3f, 0.3f, 0.3f));
		}
		if ((Object)(object)g.itemProperties != (Object)null)
		{
			boundsCache[g.itemProperties] = value;
		}
		return value;
	}

	private static void Encapsulate(ref Bounds b, ref bool any, Matrix4x4 m, Bounds mesh)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: 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_0065: 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_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_007d: Unknown result type (might be due to invalid IL or missing references)
		Vector3 center = ((Bounds)(ref mesh)).center;
		Vector3 extents = ((Bounds)(ref mesh)).extents;
		for (int i = 0; i < 8; i++)
		{
			Vector3 val = center + new Vector3(((i & 1) == 0) ? (0f - extents.x) : extents.x, ((i & 2) == 0) ? (0f - extents.y) : extents.y, ((i & 4) == 0) ? (0f - extents.z) : extents.z);
			Vector3 val2 = ((Matrix4x4)(ref m)).MultiplyPoint3x4(val);
			if (!any)
			{
				b = new Bounds(val2, Vector3.zero);
				any = true;
			}
			else
			{
				((Bounds)(ref b)).Encapsulate(val2);
			}
		}
	}
}
internal static class Hud
{
	internal static Canvas Canvas;

	internal static RectTransform Root;

	private static GameObject crosshair;

	private static GameObject heldPanel;

	private static Image heldIcon;

	private static TextMeshProUGUI heldName;

	private static TextMeshProUGUI hint;

	internal static void Tick()
	{
		PlayerControllerB me = Util.Me;
		if ((Object)(object)me == (Object)null || (Object)(object)HUDManager.Instance == (Object)null)
		{
			if ((Object)(object)Root != (Object)null)
			{
				((Component)Root).gameObject.SetActive(false);
			}
			return;
		}
		Build();
		bool flag = me.isPlayerControlled && !me.isPlayerDead;
		((Component)Root).gameObject.SetActive(true);
		crosshair.SetActive(ThirdPerson.Active && Plugin.TpCrosshair.Value && !Case.Open);
		heldPanel.SetActive(flag && !me.inTerminalMenu);
		if (!flag)
		{
			return;
		}
		GrabbableObject currentlyHeldObjectServer = me.currentlyHeldObjectServer;
		if ((Object)(object)currentlyHeldObjectServer != (Object)null && (Object)(object)currentlyHeldObjectServer.itemProperties != (Object)null)
		{
			((Behaviour)heldIcon).enabled = (Object)(object)currentlyHeldObjectServer.itemProperties.itemIcon != (Object)null;
			heldIcon.sprite = currentlyHeldObjectServer.itemProperties.itemIcon;
			string text = currentlyHeldObjectServer.itemProperties.itemName;
			if (Lasers.Has(currentlyHeldObjectServer))
			{
				text += "  <color=#ff4433>+ laser</color>";
			}
			((TMP_Text)heldName).text = text;
		}
		else
		{
			((Behaviour)heldIcon).enabled = false;
			((TMP_Text)heldName).text = "<color=#9aa4a8>Hands free</color>";
		}
		((TMP_Text)hint).text = "[" + Plugin.CaseKey.Value + "] Case   " + Case.CountText(me) + "   [" + Plugin.LampKey.Value + "] Lamp" + (Lamp.IsOn(Util.IndexOf(me)) ? " on" : "") + "   [" + Plugin.TpKey.Value + "] View";
	}

	private static void Build()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Expected O, but got Unknown
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Expected O, but got Unknown
		//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_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Expected O, but got Unknown
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: 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_01c9: 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_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_0244: Unknown result type (might be due to invalid IL or missing references)
		//IL_0253: Unknown result type (might be due to invalid IL or missing references)
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_0267: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0308: Unknown result type (might be due to invalid IL or missing references)
		//IL_033a: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)Root != (Object)null))
		{
			GameObject val = new GameObject("TacticalKitHud");
			Object.DontDestroyOnLoad((Object)(object)val);
			Canvas = val.AddComponent<Canvas>();
			Canvas.renderMode = (RenderMode)0;
			Canvas.sortingOrder = 40;
			CanvasScaler val2 = val.AddComponent<CanvasScaler>();
			val2.uiScaleMode = (ScaleMode)1;
			val2.referenceResolution = new Vector2(1920f, 1080f);
			val2.matchWidthOrHeight = 1f;
			Root = val.GetComponent<RectTransform>();
			crosshair = new GameObject("Crosshair");
			crosshair.transform.SetParent((Transform)(object)Root, false);
			Stretch(crosshair.AddComponent<RectTransform>());
			Panel(crosshair.transform, "Ring", new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(9f, 9f), new Color(0f, 0f, 0f, 0.55f));
			Panel(crosshair.transform, "Dot", new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(4f, 4f), new Color(1f, 1f, 1f, 0.9f));
			heldPanel = new GameObject("Held");
			heldPanel.transform.SetParent((Transform)(object)Root, false);
			RectTransform val3 = heldPanel.AddComponent<RectTransform>();
			Vector2 val4 = (val3.pivot = new Vector2(1f, 0f));
			Vector2 anchorMin = (val3.anchorMax = val4);
			val3.anchorMin = anchorMin;
			val3.anchoredPosition = new Vector2(-28f, 26f);
			val3.sizeDelta = new Vector2(430f, 96f);
			Image val7 = Panel(heldPanel.transform, "Back", new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(430f, 96f), new Color(0.02f, 0.03f, 0.03f, 0.55f));
			((Graphic)val7).raycastTarget = false;
			heldIcon = Panel(heldPanel.transform, "Icon", new Vector2(0f, 0.5f), new Vector2(48f, 8f), new Vector2(64f, 64f), Color.white);
			heldIcon.preserveAspect = true;
			heldName = Text(heldPanel.transform, "Name", new Vector2(0f, 0.5f), new Vector2(92f, 18f), new Vector2(330f, 34f), 24f, (TextAlignmentOptions)513);
			hint = Text(heldPanel.transform, "Hint", new Vector2(0f, 0.5f), new Vector2(92f, -20f), new Vector2(330f, 28f), 15f, (TextAlignmentOptions)513);
			((Graphic)hint).color = new Color(0.7f, 0.76f, 0.78f, 1f);
		}
	}

	internal static void Stretch(RectTransform r)
	{
		//IL_0001: 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_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		r.anchorMin = Vector2.zero;
		r.anchorMax = Vector2.one;
		r.pivot = new Vector2(0.5f, 0.5f);
		r.offsetMin = Vector2.zero;
		r.offsetMax = Vector2.zero;
	}

	internal static Image Panel(Transform parent, string name, Vector2 anchor, Vector2 position, Vector2 size, Color colour)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0048: 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)
		GameObject val = new GameObject(name);
		val.transform.SetParent(parent, false);
		RectTransform val2 = val.AddComponent<RectTransform>();
		Vector2 anchorMin = (val2.anchorMax = anchor);
		val2.anchorMin = anchorMin;
		val2.pivot = new Vector2(0.5f, 0.5f);
		val2.anchoredPosition = position;
		val2.sizeDelta = size;
		Image val4 = val.AddComponent<Image>();
		((Graphic)val4).color = colour;
		((Graphic)val4).raycastTarget = false;
		return val4;
	}

	internal static TextMeshProUGUI Text(Transform parent, string name, Vector2 anchor, Vector2 position, Vector2 size, float fontSize, TextAlignmentOptions align)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Invalid comparison between Unknown and I4
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name);
		val.transform.SetParent(parent, false);
		RectTransform val2 = val.AddComponent<RectTransform>();
		Vector2 anchorMin = (val2.anchorMax = anchor);
		val2.anchorMin = anchorMin;
		val2.pivot = new Vector2(((int)align == 513) ? 0f : 0.5f, 0.5f);
		val2.anchoredPosition = position;
		val2.sizeDelta = size;
		TextMeshProUGUI val4 = val.AddComponent<TextMeshProUGUI>();
		if ((Object)(object)HUDManager.Instance != (Object)null && (Object)(object)HUDManager.Instance.chatText != (Object)null)
		{
			((TMP_Text)val4).font = ((TMP_Text)HUDManager.Instance.chatText).font;
		}
		((TMP_Text)val4).fontSize = fontSize;
		((TMP_Text)val4).alignment = align;
		((TMP_Text)val4).enableWordWrapping = false;
		((TMP_Text)val4).overflowMode = (TextOverflowModes)1;
		((TMP_Text)val4).richText = true;
		((Graphic)val4).raycastTarget = false;
		((Graphic)val4).color = Color.white;
		return val4;
	}
}
internal static class Lamp
{
	private static readonly HashSet<int> on = new HashSet<int>();

	private static readonly Dictionary<PlayerControllerB, Light> lights = new Dictionary<PlayerControllerB, Light>();

	internal static void Clear()
	{
		on.Clear();
	}

	internal static List<int> OnPlayers()
	{
		return new List<int>(on);
	}

	internal static bool IsOn(int player)
	{
		return on.Contains(player);
	}

	internal static void Toggle(PlayerControllerB me)
	{
		int num = Util.IndexOf(me);
		Set(num, !on.Contains(num), publish: true);
	}

	internal static void Set(int player, bool value, bool publish)
	{
		if (player >= 0)
		{
			if (value)
			{
				on.Add(player);
			}
			else
			{
				on.Remove(player);
			}
			if (publish)
			{
				Net.Publish("TK.Lamp", Net.IntBool(player, value));
			}
		}
	}

	internal static void Tick()
	{
		StartOfRound instance = StartOfRound.Instance;
		if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null)
		{
			return;
		}
		for (int i = 0; i < instance.allPlayerScripts.Length; i++)
		{
			PlayerControllerB val = instance.allPlayerScripts[i];
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			bool flag = on.Contains(i) && val.isPlayerControlled && !val.isPlayerDead;
			if (!lights.TryGetValue(val, out var value) || (Object)(object)value == (Object)null)
			{
				if (!flag)
				{
					continue;
				}
				value = Make(val);
				lights[val] = value;
				if ((Object)(object)value == (Object)null)
				{
					continue;
				}
			}
			if (((Behaviour)value).enabled != flag)
			{
				((Behaviour)value).enabled = flag;
			}
		}
	}

	private static Light Make(PlayerControllerB p)
	{
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Expected O, but got Unknown
		Light val = null;
		if (p.allHelmetLights != null)
		{
			Light[] allHelmetLights = p.allHelmetLights;
			foreach (Light val2 in allHelmetLights)
			{
				if ((Object)(object)val2 != (Object)null && ((Object)(object)val == (Object)null || val2.range > val.range))
				{
					val = val2;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Log.LogWarning((object)("Player " + p.playerUsername + " has no helmet light to copy; no lamp for them."));
			return null;
		}
		GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent);
		((Object)val3).name = "TacticalKitLamp";
		val3.transform.localPosition = ((Component)val).transform.localPosition;
		val3.transform.localRotation = ((Component)val).transform.localRotation;
		val3.transform.localScale = ((Component)val).transform.localScale;
		foreach (Transform item in val3.transform)
		{
			Transform val4 = item;
			Object.Destroy((Object)(object)((Component)val4).gameObject);
		}
		MonoBehaviour[] components = val3.GetComponents<MonoBehaviour>();
		foreach (MonoBehaviour val5 in components)
		{
			if (((object)val5).GetType().Namespace == null || !((object)val5).GetType().Namespace.StartsWith("UnityEngine"))
			{
				Object.Destroy((Object)(object)val5);
			}
		}
		Light component = val3.GetComponent<Light>();
		((Behaviour)component).enabled = false;
		val3.SetActive(true);
		Plugin.Log.LogInfo((object)("Lamp made for " + p.playerUsername + " from '" + ((Object)val).name + "' (range " + val.range.ToString("0") + ")."));
		return component;
	}
}
internal static class LaserAssets
{
	private const float Length = 0.13f;

	private const float Width = 0.034f;

	private const float Height = 0.038f;

	internal static Item Item;

	internal static GameObject Prefab;

	internal static Mesh Mesh;

	internal static Material BodyMaterial;

	internal static Material LensMaterial;

	internal static Material BeamMaterial;

	internal static Material DotMaterial;

	private static bool finished;

	internal static AudioClip Click;

	internal static void CreatePrefab()
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Expected O, but got Unknown
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Expected O, but got Unknown
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_0317: Unknown result type (might be due to invalid IL or missing references)
		//IL_031c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0332: Unknown result type (might be due to invalid IL or missing references)
		//IL_0337: Unknown result type (might be due to invalid IL or missing references)
		//IL_034d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0352: Unknown result type (might be due to invalid IL or missing references)
		Mesh = BuildMesh();
		GameObject val = NetworkPrefabs.CreateNetworkPrefab("TacticalKitLaserSight");
		val.layer = 6;
		val.tag = "PhysicsProp";
		NetworkObject component = val.GetComponent<NetworkObject>();
		component.AlwaysReplicateAsRoot = false;
		component.SynchronizeTransform = true;
		component.ActiveSceneSynchronization = false;
		component.SceneMigrationSynchronization = true;
		component.SpawnWithObservers = true;
		component.DontDestroyWithOwner = true;
		component.AutoObjectParentSync = false;
		GameObject val2 = new GameObject("Model");
		val2.layer = 6;
		val2.transform.SetParent(val.transform, false);
		val2.transform.localScale = new Vector3(1.6f, 1.6f, 1.6f);
		val2.AddComponent<MeshFilter>().sharedMesh = Mesh;
		MeshRenderer val3 = val2.AddComponent<MeshRenderer>();
		((Renderer)val3).shadowCastingMode = (ShadowCastingMode)1;
		((Renderer)val3).motionVectorGenerationMode = (MotionVectorGenerationMode)0;
		BoxCollider val4 = val.AddComponent<BoxCollider>();
		val4.center = Vector3.zero;
		val4.size = new Vector3(0.1144f, 0.120799996f, 0.248f);
		AudioSource val5 = val.AddComponent<AudioSource>();
		val5.playOnAwake = false;
		val5.spatialBlend = 1f;
		val5.rolloffMode = (AudioRolloffMode)1;
		val5.minDistance = 2f;
		val5.maxDistance = 14f;
		GameObject val6 = new GameObject("ScanNode");
		val6.layer = 22;
		val6.transform.SetParent(val.transform, false);
		val6.AddComponent<BoxCollider>().size = new Vector3(0.2f, 0.2f, 0.2f);
		ScanNodeProperties val7 = val6.AddComponent<ScanNodeProperties>();
		val7.headerText = "Laser sight";
		val7.subText = "Clips onto a gun";
		val7.minRange = 1;
		val7.maxRange = 10;
		val7.requiresLineOfSight = true;
		val7.creatureScanID = -1;
		val7.nodeType = 0;
		Item val8 = ScriptableObject.CreateInstance<Item>();
		((Object)val8).name = "TacticalKitLaserSight";
		((Object)val8).hideFlags = (HideFlags)61;
		val8.itemId = 684131;
		val8.itemName = "Laser sight";
		val8.spawnPositionTypes = new List<ItemGroup>();
		val8.twoHanded = false;
		val8.twoHandedAnimation = false;
		val8.canBeGrabbedBeforeGameStart = true;
		val8.disallowUtilitySlot = true;
		val8.weight = 1.01f;
		val8.itemSpawnsOnGround = true;
		val8.isConductiveMetal = true;
		val8.isScrap = false;
		val8.creditsWorth = Mathf.Max(0, Plugin.LaserPrice.Value);
		val8.highestSalePercentage = 80;
		val8.spawnPrefab = val;
		val8.requiresBattery = false;
		val8.grabAnim = "";
		val8.useAnim = "";
		val8.pocketAnim = "";
		val8.throwAnim = "";
		val8.syncGrabFunction = false;
		val8.syncUseFunction = false;
		val8.syncDiscardFunction = false;
		val8.syncInteractLRFunction = false;
		val8.saveItemVariable = false;
		val8.holdButtonUse = false;
		val8.toolTips = new string[1] { "Clip onto a gun : [LMB]" };
		val8.verticalOffset = 0.060399998f;
		val8.floorYOffset = 0;
		val8.positionOffset = new Vector3(0f, 0.06f, 0.02f);
		val8.rotationOffset = new Vector3(0f, 90f, 0f);
		val8.restingRotation = new Vector3(0f, 0f, 0f);
		val8.allowDroppingAheadOfPlayer = true;
		val8.meshVariants = (Mesh[])(object)new Mesh[0];
		val8.materialVariants = (Material[])(object)new Material[0];
		val8.clinkAudios = (AudioClip[])(object)new AudioClip[0];
		val8.itemIcon = BuildIcon();
		Item = val8;
		LaserSightItem laserSightItem = val.AddComponent<LaserSightItem>();
		((GrabbableObject)laserSightItem).itemProperties = val8;
		((GrabbableObject)laserSightItem).grabbable = true;
		((GrabbableObject)laserSightItem).grabbableToEnemies = true;
		((GrabbableObject)laserSightItem).mainObjectRenderer = val3;
		((GrabbableObject)laserSightItem).useCooldown = 0.5f;
		((GrabbableObject)laserSightItem).floorYRot = -1;
		((GrabbableObject)laserSightItem).customGrabTooltip = "";
		Prefab = val;
	}

	internal static void FinishWhenPossible()
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: 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_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Expected O, but got Unknown
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: 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)
		if ((Object)(object)Prefab == (Object)null)
		{
			return;
		}
		if (!finished)
		{
			Shader val = Shader.Find("HDRP/Lit");
			Shader val2 = Shader.Find("HDRP/Unlit");
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				return;
			}
			finished = true;
			Color val3 = Plugin.ParseColour(Plugin.LaserColor.Value, new Color(1f, 0.14f, 0.09f));
			BodyMaterial = new Material(val);
			((Object)BodyMaterial).name = "TacticalKitLaserBody";
			BodyMaterial.SetColor("_BaseColor", new Color(0.09f, 0.095f, 0.1f, 1f));
			BodyMaterial.SetFloat("_Metallic", 0.7f);
			BodyMaterial.SetFloat("_Smoothness", 0.45f);
			BodyMaterial.SetFloat("_DoubleSidedEnable", 1f);
			BodyMaterial.SetFloat("_CullMode", 0f);
			BodyMaterial.SetFloat("_CullModeForward", 0f);
			Validate(BodyMaterial);
			LensMaterial = Glow(val2, "TacticalKitLaserLens", val3 * 1.5f);
			BeamMaterial = Glow(val2, "TacticalKitLaserBeam", val3 * 2.2f);
			DotMaterial = Glow(val2, "TacticalKitLaserDot", val3 * 6f);
			((Renderer)Prefab.GetComponentInChildren<MeshRenderer>()).sharedMaterials = (Material[])(object)new Material[2] { BodyMaterial, LensMaterial };
			Plugin.Log.LogInfo((object)"Laser sight materials made.");
		}
		if (!((Object)(object)StartOfRound.Instance != (Object)null) || !((Object)(object)StartOfRound.Instance.allItemsList != (Object)null) || !((Object)(object)Item.grabSFX == (Object)null))
		{
			return;
		}
		foreach (Item items in StartOfRound.Instance.allItemsList.itemsList)
		{
			if (!((Object)(object)items == (Object)null) && !((Object)(object)items.spawnPrefab == (Object)null) && !((Object)(object)items.spawnPrefab.GetComponent<FlashlightItem>() == (Object)null))
			{
				Item.grabSFX = items.grabSFX;
				Item.dropSFX = items.dropSFX;
				Item.pocketSFX = items.pocketSFX;
				Item.throwSFX = items.throwSFX;
				AudioSource component = items.spawnPrefab.GetComponent<AudioSource>();
				if ((Object)(object)component != (Object)null)
				{
					Prefab.GetComponent<AudioSource>().outputAudioMixerGroup = component.outputAudioMixerGroup;
				}
				FlashlightItem component2 = items.spawnPrefab.GetComponent<FlashlightItem>();
				if ((Object)(object)component2 != (Object)null && component2.flashlightClips != null && component2.flashlightClips.Length > 0)
				{
					Click = component2.flashlightClips[0];
				}
				break;
			}
		}
	}

	private static Material Glow(Shader unlit, string name, Color colour)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected O, but got Unknown
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		Material val = new Material(unlit);
		((Object)val).name = name;
		val.SetFloat("_SurfaceType", 1f);
		val.SetFloat("_BlendMode", 1f);
		val.SetFloat("_ZWrite", 0f);
		val.SetFloat("_TransparentZWrite", 0f);
		val.SetFloat("_DoubleSidedEnable", 1f);
		val.SetFloat("_CullMode", 0f);
		val.SetFloat("_CullModeForward", 0f);
		val.SetColor("_UnlitColor", colour);
		try
		{
			Validate(val);
		}
		catch (Exception)
		{
			val.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
			val.EnableKeyword("_BLENDMODE_ADD");
			val.SetOverrideTag("RenderType", "Transparent");
		}
		val.SetFloat("_SrcBlend", 1f);
		val.SetFloat("_DstBlend", 1f);
		val.SetFloat("_AlphaSrcBlend", 1f);
		val.SetFloat("_AlphaDstBlend", 1f);
		val.renderQueue = 3000;
		return val;
	}

	private static void Validate(Material m)
	{
		try
		{
			HDMaterial.ValidateMaterial(m);
		}
		catch (Exception)
		{
		}
	}

	internal static GameObject AttachTo(GrabbableObject g)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		ShotgunItem val = (ShotgunItem)(object)((g is ShotgunItem) ? g : null);
		if ((Object)(object)val == (Object)null || (Object)(object)val.shotgunRayPoint == (Object)null || (Object)(object)BodyMaterial == (Object)null)
		{
			return null;
		}
		GameObject val2 = new GameObject("TacticalKitLaserClip");
		val2.layer = ((Component)g).gameObject.layer;
		Transform shotgunRayPoint = val.shotgunRayPoint;
		val2.transform.SetParent(shotgunRayPoint, false);
		Vector3 lossyScale = shotgunRayPoint.lossyScale;
		float num = 1f / Mathf.Max(0.0001f, (Mathf.Abs(lossyScale.x) + Mathf.Abs(lossyScale.y) + Mathf.Abs(lossyScale.z)) / 3f);
		val2.transform.localScale = new Vector3(num, num, num);
		val2.transform.localPosition = shotgunRayPoint.InverseTransformDirection(shotgunRayPoint.forward * -0.16f - shotgunRayPoint.up * 0.045f) * num;
		val2.transform.localRotation = Quaternion.identity;
		val2.AddComponent<MeshFilter>().sharedMesh = Mesh;
		MeshRenderer val3 = val2.AddComponent<MeshRenderer>();
		((Renderer)val3).sharedMaterials = (Material[])(object)new Material[2] { BodyMaterial, LensMaterial };
		((Renderer)val3).motionVectorGenerationMode = (MotionVectorGenerationMode)0;
		return val2;
	}

	private static Mesh BuildMesh()
	{
		//IL_002a: 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_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Expected O, but got Unknown
		List<Vector3> list = new List<Vector3>();
		List<Vector3> list2 = new List<Vector3>();
		List<int> list3 = new List<int>();
		List<int> list4 = new List<int>();
		Box(list, list2, list3, new Vector3(0f, 0f, 0f), new Vector3(0.034f, 0.038f, 0.13f));
		Box(list, list2, list3, new Vector3(0f, 0.023559999f, -0.012999999f), new Vector3(0.0238f, 0.0114f, 0.071499996f));
		Box(list, list2, list3, new Vector3(0f, 0f, 0.069f), new Vector3(0.031280003f, 0.034959998f, 0.008f));
		Box(list, list2, list4, new Vector3(0f, 0f, 0.0735f), new Vector3(0.017f, 0.019f, 0.002f));
		Mesh val = new Mesh();
		((Object)val).name = "TacticalKitLaserSight";
		((Object)val).hideFlags = (HideFlags)61;
		val.SetVertices(list);
		val.SetNormals(list2);
		val.subMeshCount = 2;
		val.SetTriangles(list3, 0);
		val.SetTriangles(list4, 1);
		val.RecalculateBounds();
		return val;
	}

	private static void Box(List<Vector3> v, List<Vector3> n, List<int> t, Vector3 c, Vector3 size)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: 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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: 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_0046: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: 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_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: 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_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: 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_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: 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_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: 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)
		Vector3 val = size * 0.5f;
		Vector3[] array = (Vector3[])(object)new Vector3[6]
		{
			Vector3.right,
			Vector3.left,
			Vector3.up,
			Vector3.down,
			Vector3.forward,
			Vector3.back
		};
		Vector3[] array2 = array;
		Vector3 val3 = default(Vector3);
		for (int i = 0; i < array2.Length; i++)
		{
			Vector3 val2 = array2[i];
			((Vector3)(ref val3))..ctor(val2.y, val2.z, val2.x);
			Vector3 val4 = Vector3.Cross(val2, val3);
			int count = v.Count;
			Vector3 val5 = c + Vector3.Scale(val2, val);
			Vector3 val6 = Vector3.Scale(val3, val);
			Vector3 val7 = Vector3.Scale(val4, val);
			v.Add(val5 - val6 - val7);
			v.Add(val5 + val6 - val7);
			v.Add(val5 + val6 + val7);
			v.Add(val5 - val6 + val7);
			for (int j = 0; j < 4; j++)
			{
				n.Add(val2);
			}
			t.Add(count);
			t.Add(count + 2);
			t.Add(count + 1);
			t.Add(count);
			t.Add(count + 3);
			t.Add(count + 2);
		}
	}

	private static Sprite BuildIcon()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected O, but got Unknown
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: 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_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false);
		((Object)val).name = "TacticalKitLaserIcon";
		((Object)val).hideFlags = (HideFlags)61;
		Color val2 = default(Color);
		((Color)(ref val2))..ctor(1f, 1f, 1f, 0f);
		Color val3 = default(Color);
		((Color)(ref val3))..ctor(0.86f, 0.86f, 0.86f, 1f);
		Color val4 = default(Color);
		((Color)(ref val4))..ctor(1f, 0.2f, 0.15f, 1f);
		Color[] array = (Color[])(object)new Color[16384];
		for (int i = 0; i < 128; i++)
		{
			for (int j = 0; j < 128; j++)
			{
				Color val5 = val2;
				bool flag = j >= 14 && j <= 78 && i >= 48 && i <= 80;
				bool flag2 = j >= 26 && j <= 58 && i > 80 && i <= 92;
				bool flag3 = j > 78 && j <= 86 && i >= 50 && i <= 78;
				float num = (float)j - 92f;
				float num2 = (float)i - 64f;
				bool flag4 = num * num + num2 * num2 <= 30f;
				bool flag5 = j > 92 && j < 126 && Mathf.Abs(i - 64) <= 1;
				if (flag || flag2 || flag3)
				{
					val5 = val3;
				}
				if (flag && (j < 17 || j > 75 || i < 51 || i > 77))
				{
					((Color)(ref val5))..ctor(0.6f, 0.6f, 0.6f, 1f);
				}
				if (flag4 || flag5)
				{
					val5 = val4;
				}
				array[i * 128 + j] = val5;
			}
		}
		val.SetPixels(array);
		val.Apply(false, false);
		Sprite val6 = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f);
		((Object)val6).name = "TacticalKitLaserIcon";
		((Object)val6).hideFlags = (HideFlags)61;
		return val6;
	}
}
internal static class Lasers
{
	private class Beam
	{
		internal GrabbableObject gun;

		internal GameObject root;

		internal LineRenderer line;

		internal Transform dot;

		internal GameObject clip;
	}

	private const string SaveKey = "TacticalKitLaserGuns";

	private static readonly HashSet<ulong> on = new HashSet<ulong>();

	private static readonly Dictionary<ulong, Beam> beams = new Dictionary<ulong, Beam>();

	private static int lastDrawnFrame = -1;

	private static int hitMask = -1;

	internal static void Clear()
	{
		on.Clear();
		foreach (Beam value in beams.Values)
		{
			Destroy(value);
		}
		beams.Clear();
	}

	internal static List<ulong> All()
	{
		return new List<ulong>(on);
	}

	internal static bool Has(GrabbableObject g)
	{
		if ((Object)(object)g != (Object)null && (Object)(object)((NetworkBehaviour)g).NetworkObject != (Object)null && ((NetworkBehaviour)g).NetworkObject.IsSpawned)
		{
			return on.Contains(((NetworkBehaviour)g).NetworkObjectId);
		}
		return false;
	}

	internal static void Set(ulong gun, bool value, bool publish)
	{
		if (value)
		{
			on.Add(gun);
		}
		else
		{
			on.Remove(gun);
		}
		if (publish)
		{
			Net.Publish("TK.Laser", Net.UlongBool(gun, value));
		}
	}

	internal static GrabbableObject FindGunFor(PlayerControllerB p)
	{
		GrabbableObject currentlyHeldObjectServer = p.currentlyHeldObjectServer;
		if (Firearms.IsFirearm(currentlyHeldObjectServer) && !Has(currentlyHeldObjectServer))
		{
			return currentlyHeldObjectServer;
		}
		GrabbableObject[] itemSlots = p.ItemSlots;
		foreach (GrabbableObject val in itemSlots)
		{
			if (Firearms.IsFirearm(val) && !Has(val))
			{
				return val;
			}
		}
		return null;
	}

	internal static void Tick()
	{
		NetworkManager singleton = NetworkManager.Singleton;
		if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.SpawnManager == null)
		{
			return;
		}
		foreach (ulong item in on)
		{
			if (!beams.ContainsKey(item) && singleton.SpawnManager.SpawnedObjects.TryGetValue(item, out var value) && !((Object)(object)value == (Object)null))
			{
				GrabbableObject componentInChildren = ((Component)value).GetComponentInChildren<GrabbableObject>();
				if (!((Object)(object)componentInChildren == (Object)null))
				{
					beams[item] = Make(componentInChildren);
				}
			}
		}
		List<ulong> list = null;
		foreach (KeyValuePair<ulong, Beam> beam in beams)
		{
			if ((Object)(object)beam.Value.gun == (Object)null || !on.Contains(beam.Key))
			{
				if (list == null)
				{
					list = new List<ulong>();
				}
				list.Add(beam.Key);
			}
		}
		if (list != null)
		{
			foreach (ulong item2 in list)
			{
				Destroy(beams[item2]);
				beams.Remove(item2);
				if (on.Contains(item2) && !singleton.SpawnManager.SpawnedObjects.TryGetValue(item2, out var _) && singleton.IsServer)
				{
					on.Remove(item2);
				}
			}
		}
		RenderPipelineManager.beginContextRendering -= BeforeRendering;
		RenderPipelineManager.beginContextRendering += BeforeRendering;
	}

	private static void BeforeRendering(ScriptableRenderContext context, List<Camera> cameras)
	{
		if (lastDrawnFrame != Time.frameCount)
		{
			lastDrawnFrame = Time.frameCount;
			Draw(null);
		}
	}

	internal static void Draw(GrabbableObject only)
	{
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_026b: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_0279: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0204: Unknown result type (might be due to invalid IL or missing references)
		if (beams.Count == 0)
		{
			return;
		}
		if (hitMask == -1 && (Object)(object)StartOfRound.Instance != (Object)null)
		{
			hitMask = StartOfRound.Instance.collidersAndRoomMaskAndDefault | 0x80000 | 8;
		}
		float num = Mathf.Max(2f, Plugin.LaserRange.Value);
		foreach (Beam value in beams.Values)
		{
			GrabbableObject gun = value.gun;
			if ((Object)(object)gun == (Object)null || ((Object)(object)only != (Object)null && (Object)(object)gun != (Object)(object)only))
			{
				continue;
			}
			bool flag = (gun.isHeld || gun.isHeldByEnemy) && !gun.isPocketed && ((Component)gun).gameObject.activeInHierarchy;
			if ((Object)(object)value.clip != (Object)null && value.clip.activeSelf != !gun.isPocketed)
			{
				value.clip.SetActive(!gun.isPocketed);
			}
			if (!flag)
			{
				if (value.root.activeSelf)
				{
					value.root.SetActive(false);
				}
				continue;
			}
			Firearms.Muzzle(gun, out var position, out var _);
			Firearms.ShotRay(gun, out var origin, out var direction);
			Vector3 val = origin + direction * num;
			bool flag2 = false;
			RaycastHit[] array = Physics.RaycastAll(origin, direction, num, hitMask, (QueryTriggerInteraction)2);
			float num2 = num;
			RaycastHit[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				RaycastHit val2 = array2[i];
				if (((RaycastHit)(ref val2)).distance >= num2 || (Object)(object)((RaycastHit)(ref val2)).collider == (Object)null)
				{
					continue;
				}
				int layer = ((Component)((RaycastHit)(ref val2)).collider).gameObject.layer;
				if (!((RaycastHit)(ref val2)).collider.isTrigger || layer == 19)
				{
					PlayerControllerB componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<PlayerControllerB>();
					if ((!((Object)(object)componentInParent != (Object)null) || !((Object)(object)componentInParent == (Object)(object)gun.playerHeldBy)) && !((Component)((RaycastHit)(ref val2)).collider).transform.IsChildOf(((Component)gun).transform))
					{
						num2 = ((RaycastHit)(ref val2)).distance;
						val = ((RaycastHit)(ref val2)).point;
						flag2 = true;
					}
				}
			}
			if (!value.root.activeSelf)
			{
				value.root.SetActive(true);
			}
			value.line.SetPosition(0, position);
			value.line.SetPosition(1, val);
			((Component)value.dot).gameObject.SetActive(flag2);
			if (flag2)
			{
				value.dot.position = val - direction * 0.01f;
				float num3 = Mathf.Clamp(num2 * 0.009f, 0.04f, 0.16f);
				value.dot.localScale = new Vector3(num3, num3, num3);
			}
		}
	}

	private static Beam Make(GrabbableObject g)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		Beam beam = new Beam();
		beam.gun = g;
		beam.root = new GameObject("TacticalKitLaser");
		Object.DontDestroyOnLoad((Object)(object)beam.root);
		GameObject val = new GameObject("Beam");
		val.transform.SetParent(beam.root.transform, false);
		beam.line = val.AddComponent<LineRenderer>();
		beam.line.useWorldSpace = true;
		beam.line.positionCount = 2;
		beam.line.widthMultiplier = Mathf.Clamp(Plugin.LaserWidth.Value, 0.001f, 0.05f);
		beam.line.numCapVertices = 2;
		((Renderer)beam.line).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)beam.line).receiveShadows = false;
		((Renderer)beam.line).sharedMaterial = LaserAssets.BeamMaterial;
		beam.line.alignment = (LineAlignment)0;
		GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)0);
		Object.Destroy((Object)(object)val2.GetComponent<Collider>());
		((Object)val2).name = "Dot";
		val2.transform.SetParent(beam.root.transform, false);
		MeshRenderer component = val2.GetComponent<MeshRenderer>();
		((Renderer)component).sharedMaterial = LaserAssets.DotMaterial;
		((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
		beam.dot = val2.transform;
		beam.clip = LaserAssets.AttachTo(g);
		beam.root.SetActive(false);
		Plugin.Log.LogInfo((object)("Laser sight on " + g.itemProperties.itemName + " (#" + ((NetworkBehaviour)g).NetworkObjectId + ")."));
		return beam;
	}

	private static void Destroy(Beam b)
	{
		if ((Object)(object)b.root != (Object)null)
		{
			Object.Destroy((Object)(object)b.root);
		}
		if ((Object)(object)b.clip != (Object)null)
		{
			Object.Destroy((Object)(object)b.clip);
		}
	}

	internal static void Save()
	{
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		if (!Net.IsServer || (Object)(object)GameNetworkManager.Instance == (Object)null)
		{
			return;
		}
		string currentSaveFileName = GameNetworkManager.Instance.currentSaveFileName;
		List<Vector3> list = new List<Vector3>();
		foreach (Beam value in beams.Values)
		{
			if ((Object)(object)value.gun != (Object)null && on.Contains(((NetworkBehaviour)value.gun).NetworkObjectId))
			{
				list.Add(((Component)value.gun).transform.position);
			}
		}
		if (list.Count > 0)
		{
			ES3.Save<Vector3[]>("TacticalKitLaserGuns", list.ToArray(), currentSaveFileName);
		}
		else if (ES3.KeyExists("TacticalKitLaserGuns", currentSaveFileName))
		{
			ES3.DeleteKey("TacticalKitLaserGuns", currentSaveFileName);
		}
		Plugin.Log.LogInfo((object)("Saved " + list.Count + " laser sights with the ship."));
	}

	internal static void Load()
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: 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_0099: 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)
		if (!Net.IsServer || (Object)(object)GameNetworkManager.Instance == (Object)null)
		{
			return;
		}
		string currentSaveFileName = GameNetworkManager.Instance.currentSaveFileName;
		if (!ES3.KeyExists("TacticalKitLaserGuns", currentSaveFileName))
		{
			return;
		}
		Vector3[] array = ES3.Load<Vector3[]>("TacticalKitLaserGuns", currentSaveFileName);
		int num = 0;
		GrabbableObject[] array2 = Object.FindObjectsOfType<GrabbableObject>();
		foreach (GrabbableObject val in array2)
		{
			if (!Firearms.IsFirearm(val) || (Object)(object)((NetworkBehaviour)val).NetworkObject == (Object)null || !((NetworkBehaviour)val).NetworkObject.IsSpawned)
			{
				continue;
			}
			Vector3[] array3 = array;
			foreach (Vector3 val2 in array3)
			{
				Vector3 val3 = ((Component)val).transform.position - val2;
				if (((Vector3)(ref val3)).sqrMagnitude < 0.0025f)
				{
					Set(((NetworkBehaviour)val).NetworkObjectId, value: true, publish: true);
					num++;
					break;
				}
			}
		}
		Plugin.Log.LogInfo((object)("Loaded the ship: " + num + " of " + array.Length + " laser sights back on their guns."));
	}
}
public class LaserSightItem : GrabbableObject
{
	private bool used;

	public override void ItemActivate(bool used, bool buttonDown = true)
	{
		((GrabbableObject)this).ItemActivate(used, buttonDown);
		if (!((NetworkBehaviour)this).IsOwner || (Object)(object)base.playerHeldBy == (Object)null || this.used)
		{
			return;
		}
		PlayerControllerB playerHeldBy = base.playerHeldBy;
		GrabbableObject val = Lasers.FindGunFor(playerHeldBy);
		if ((Object)(object)val == (Object)null