Decompiled source of GEARVISION v3.3.0

GearVision.dll

Decompiled 3 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BoneLib;
using BoneLib.BoneMenu;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.XR;
using WeaponInspector;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(WeaponInspectorMod), "GEARVISION", "3.3.0", "Cr4shers_inc", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonOptionalDependencies(new string[] { "BoneLib" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("GearVision")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("GearVision")]
[assembly: AssemblyTitle("GearVision")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WeaponInspector
{
	public class WeaponInspectorMod : MelonMod
	{
		private enum GearTag
		{
			None,
			Sidearm,
			Primary,
			Melee,
			Utility,
			Heavy,
			Experimental
		}

		private enum WeaponKind
		{
			Firearm,
			Melee,
			Unknown
		}

		private class WeaponInfo
		{
			public GameObject Anchor;

			public string Name;

			public WeaponKind Kind;

			public float Mass;

			public float Speed;

			public float Impact;

			public List<string> ExtraStats = new List<string>();

			public List<string> Components = new List<string>();
		}

		private GameObject inspectorRoot;

		private TextMesh inspectorText;

		private TextMesh hologramGlowText;

		private GameObject currentTarget;

		private WeaponInfo currentWeaponInfo;

		private string currentWeaponName;

		private float showUntil;

		private float currentAlpha;

		private bool visible;

		private bool manualInfoVisible;

		private bool supportSecondaryWasPressed;

		private GameObject trackedTwoHandWeapon;

		private bool primaryHandKnown;

		private bool primaryHandIsLeft;

		private GameObject circleDeckRoot;

		private LineRenderer outerCircle;

		private LineRenderer innerCircle;

		private LineRenderer circlePointer;

		private Material hologramLineMaterial;

		private float circleRotation;

		private GameObject coneRoot;

		private MeshFilter coneMeshFilter;

		private MeshRenderer coneRenderer;

		private bool swooshActive;

		private float swooshStartTime;

		private const float SwooshDuration = 0.28f;

		private AudioSource scanAudioSource;

		private AudioClip scanAudioClip;

		private float hologramPulseTimer;

		private float flickerCountdown;

		private float flickerEndTime;

		private float flickerMultiplier = 1f;

		private Quaternion lockedLocalRotation;

		private bool hasLockedRotation;

		private string fullInspectorText = "";

		private bool scanActive;

		private float scanStartTime;

		private float nextScanUpdate;

		private int lastScanCharacterCount = -1;

		private const float ScanDuration = 0.7f;

		private const float ScanRefreshRate = 1f / 30f;

		private MelonPreferences_Category settingsCategory;

		private MelonPreferences_Entry<bool> enabled;

		private MelonPreferences_Entry<float> displayDuration;

		private MelonPreferences_Entry<float> fadeDuration;

		private MelonPreferences_Entry<bool> fadeEnabled;

		private MelonPreferences_Entry<float> textSize;

		private MelonPreferences_Entry<float> offsetX;

		private MelonPreferences_Entry<float> offsetY;

		private MelonPreferences_Entry<float> offsetZ;

		private MelonPreferences_Entry<float> textRed;

		private MelonPreferences_Entry<float> textGreen;

		private MelonPreferences_Entry<float> textBlue;

		private MelonPreferences_Entry<bool> showSpeed;

		private MelonPreferences_Entry<bool> showImpact;

		private MelonPreferences_Entry<bool> showComponents;

		private MelonPreferences_Entry<float> fontIndex;

		private MelonPreferences_Entry<bool> panelLock;

		private MelonPreferences_Entry<bool> scanAnimation;

		private MelonPreferences_Entry<int> flickerStrength;

		private MelonPreferences_Entry<bool> circleDeckEnabled;

		private MelonPreferences_Entry<float> circleSpinSpeed;

		private MelonPreferences_Entry<bool> swooshAnimation;

		private MelonPreferences_Entry<bool> scanSound;

		private MelonPreferences_Entry<float> scanSoundVolume;

		private MelonPreferences_Entry<bool> twoHandInfoToggle;

		private MelonPreferences_Entry<bool> showFavoriteMarker;

		private MelonPreferences_Entry<bool> showTags;

		private MelonPreferences_Entry<string> favoritesData;

		private MelonPreferences_Entry<string> tagsData;

		private Font currentFont;

		private int loadedFontIndex = -1;

		private readonly string[][] availableFonts = new string[5][]
		{
			new string[3] { "Arial", "Liberation Sans", "Roboto" },
			new string[3] { "Roboto", "Arial", "Liberation Sans" },
			new string[3] { "Times New Roman", "Liberation Serif", "serif" },
			new string[3] { "Courier New", "Liberation Mono", "monospace" },
			new string[3] { "Verdana", "Arial", "Roboto" }
		};

		private readonly HashSet<string> favoriteWeapons = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private readonly Dictionary<string, GearTag> weaponTags = new Dictionary<string, GearTag>(StringComparer.OrdinalIgnoreCase);

		private readonly string[] firearmWords = new string[10] { "gun", "pistol", "rifle", "shotgun", "revolver", "smg", "carbine", "firearm", "blaster", "launcher" };

		private readonly string[] meleeWords = new string[14]
		{
			"knife", "blade", "sword", "katana", "axe", "hatchet", "machete", "bat", "club", "hammer",
			"crowbar", "spear", "dagger", "melee"
		};

		public override void OnInitializeMelon()
		{
			CreatePreferences();
			LoadFavorites();
			LoadTags();
			Hooking.OnGrabObject += OnGrabObject;
			Hooking.OnReleaseObject += OnReleaseObject;
			Hooking.OnUIRigCreated += OnUIRigCreated;
			Hooking.OnLevelLoaded += OnLevelLoaded;
			TryCreateBoneMenu();
			((MelonBase)this).LoggerInstance.Msg("GEARVISION 0.5.0 loaded.");
		}

		private void OnGrabObject(GameObject @object, Hand hand)
		{
			throw new NotImplementedException();
		}

		private void OnReleaseObject(Hand hand)
		{
			throw new NotImplementedException();
		}

		public override void OnUpdate()
		{
			UpdateTwoHandInfoToggle();
			UpdateInspector();
		}

		private void CreatePreferences()
		{
			settingsCategory = MelonPreferences.CreateCategory("GEARVISION", "GEARVISION");
			enabled = settingsCategory.CreateEntry<bool>("Enabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			displayDuration = settingsCategory.CreateEntry<float>("DisplayDuration", 3f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			fadeDuration = settingsCategory.CreateEntry<float>("FadeDuration", 0.45f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			fadeEnabled = settingsCategory.CreateEntry<bool>("FadeEnabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			textSize = settingsCategory.CreateEntry<float>("TextSize", 0.006f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			offsetX = settingsCategory.CreateEntry<float>("OffsetX", 0.12f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			offsetY = settingsCategory.CreateEntry<float>("OffsetY", 0.08f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			offsetZ = settingsCategory.CreateEntry<float>("OffsetZ", 0.04f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			textRed = settingsCategory.CreateEntry<float>("TextRed", 0.25f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			textGreen = settingsCategory.CreateEntry<float>("TextGreen", 0.95f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			textBlue = settingsCategory.CreateEntry<float>("TextBlue", 1f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			showSpeed = settingsCategory.CreateEntry<bool>("ShowSpeed", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			showImpact = settingsCategory.CreateEntry<bool>("ShowImpact", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			showComponents = settingsCategory.CreateEntry<bool>("ShowComponents", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			fontIndex = settingsCategory.CreateEntry<float>("FontIndex", 0f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			panelLock = settingsCategory.CreateEntry<bool>("PanelLock", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			scanAnimation = settingsCategory.CreateEntry<bool>("ScanAnimation", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			flickerStrength = settingsCategory.CreateEntry<int>("FlickerStrength", 1, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			circleDeckEnabled = settingsCategory.CreateEntry<bool>("CircleDeck", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			circleSpinSpeed = settingsCategory.CreateEntry<float>("CircleSpinSpeed", 90f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			swooshAnimation = settingsCategory.CreateEntry<bool>("SwooshAnimation", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			scanSound = settingsCategory.CreateEntry<bool>("ScanSound", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			scanSoundVolume = settingsCategory.CreateEntry<float>("ScanSoundVolume", 0.45f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			twoHandInfoToggle = settingsCategory.CreateEntry<bool>("TwoHandInfoToggle", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			showFavoriteMarker = settingsCategory.CreateEntry<bool>("ShowFavoriteMarker", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			showTags = settingsCategory.CreateEntry<bool>("ShowTags", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			favoritesData = settingsCategory.CreateEntry<string>("Favorites", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			tagsData = settingsCategory.CreateEntry<string>("Tags", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		}

		private void OnUIRigCreated()
		{
			TryCreateBoneMenu();
		}

		private void OnLevelLoaded(LevelInfo levelInfo)
		{
			TryCreateBoneMenu();
		}

		private void TryCreateBoneMenu()
		{
			//IL_0042: 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_0074: 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_00cb: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: 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_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: 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)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0401: Unknown result type (might be due to invalid IL or missing references)
			//IL_0419: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_0440: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0519: Unknown result type (might be due to invalid IL or missing references)
			//IL_054b: Unknown result type (might be due to invalid IL or missing references)
			//IL_057d: Unknown result type (might be due to invalid IL or missing references)
			//IL_058b: 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_05d2: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Page.Root == null || Page.Root.GetChildPage("GEARVISION") != null)
				{
					return;
				}
				Color val = default(Color);
				((Color)(ref val))..ctor(0.15f, 0.8f, 1f);
				Page obj = Page.Root.CreatePage("GEARVISION", val, 8, true);
				obj.CreateBool("Enabled", val, enabled.Value, (Action<bool>)delegate(bool value)
				{
					enabled.Value = value;
					if (!value)
					{
						manualInfoVisible = false;
						HideInspector(immediate: true);
					}
				});
				obj.CreateFloat("Display Time", val, displayDuration.Value, 0.25f, 0.5f, 10f, (Action<float>)delegate(float value)
				{
					displayDuration.Value = value;
				});
				obj.CreateBool("Fade Out", val, fadeEnabled.Value, (Action<bool>)delegate(bool value)
				{
					fadeEnabled.Value = value;
					if (!value && visible)
					{
						currentAlpha = 1f;
					}
				});
				obj.CreateFloat("Fade Time", val, fadeDuration.Value, 0.05f, 0.05f, 3f, (Action<float>)delegate(float value)
				{
					fadeDuration.Value = value;
				});
				obj.CreateFloat("Text Size", val, textSize.Value, 0.001f, 0.002f, 0.03f, (Action<float>)delegate(float value)
				{
					textSize.Value = value;
				});
				obj.CreateFloat("Font 0-4", val, fontIndex.Value, 1f, 0f, 4f, (Action<float>)delegate(float value)
				{
					fontIndex.Value = Mathf.Round(value);
					LoadSelectedFont();
				});
				obj.CreatePage("Controls", val, 0, true).CreateBool("Two-Hand Info Toggle", val, twoHandInfoToggle.Value, (Action<bool>)delegate(bool value)
				{
					twoHandInfoToggle.Value = value;
					supportSecondaryWasPressed = false;
					if (!value && manualInfoVisible)
					{
						manualInfoVisible = false;
						HideInspector(immediate: true);
					}
				});
				Page obj2 = obj.CreatePage("Hologram", val, 8, true);
				obj2.CreateBool("Panel Lock", val, panelLock.Value, (Action<bool>)delegate(bool value)
				{
					panelLock.Value = value;
					OnPanelLockChanged();
				});
				obj2.CreateBool("Scan Animation", val, scanAnimation.Value, (Action<bool>)delegate(bool value)
				{
					scanAnimation.Value = value;
				});
				obj2.CreateInt("Flicker 0-3", val, flickerStrength.Value, 1, 0, 3, (Action<int>)delegate(int value)
				{
					flickerStrength.Value = value;
					ResetFlicker();
				});
				obj2.CreateBool("Circle Deck", val, circleDeckEnabled.Value, (Action<bool>)delegate(bool value)
				{
					circleDeckEnabled.Value = value;
					UpdateCircleVisibility();
				});
				obj2.CreateFloat("Circle Spin Speed", val, circleSpinSpeed.Value, 15f, -360f, 360f, (Action<float>)delegate(float value)
				{
					circleSpinSpeed.Value = value;
				});
				obj2.CreateBool("Swoosh Animation", val, swooshAnimation.Value, (Action<bool>)delegate(bool value)
				{
					swooshAnimation.Value = value;
				});
				obj2.CreateBool("Scan Sound", val, scanSound.Value, (Action<bool>)delegate(bool value)
				{
					scanSound.Value = value;
				});
				obj2.CreateFloat("Scan Volume", val, scanSoundVolume.Value, 0.05f, 0f, 1f, (Action<float>)delegate(float value)
				{
					scanSoundVolume.Value = value;
					if ((Object)(object)scanAudioSource != (Object)null)
					{
						scanAudioSource.volume = value;
					}
				});
				Page obj3 = obj.CreatePage("Favorites & Tags", val, 7, true);
				obj3.CreateFunction("Toggle Favorite Held", val, (Action)ToggleFavoriteHeld);
				obj3.CreateBool("Show Favorite", val, showFavoriteMarker.Value, (Action<bool>)delegate(bool value)
				{
					showFavoriteMarker.Value = value;
					RefreshCurrentDisplay();
				});
				obj3.CreateBool("Show Tags", val, showTags.Value, (Action<bool>)delegate(bool value)
				{
					showTags.Value = value;
					RefreshCurrentDisplay();
				});
				obj3.CreateFunction("Tag: Sidearm", val, (Action)delegate
				{
					SetCurrentTag(GearTag.Sidearm);
				});
				obj3.CreateFunction("Tag: Primary", val, (Action)delegate
				{
					SetCurrentTag(GearTag.Primary);
				});
				obj3.CreateFunction("Tag: Melee", val, (Action)delegate
				{
					SetCurrentTag(GearTag.Melee);
				});
				obj3.CreateFunction("Tag: Utility", val, (Action)delegate
				{
					SetCurrentTag(GearTag.Utility);
				});
				obj3.CreateFunction("Tag: Heavy", val, (Action)delegate
				{
					SetCurrentTag(GearTag.Heavy);
				});
				obj3.CreateFunction("Tag: Experimental", val, (Action)delegate
				{
					SetCurrentTag(GearTag.Experimental);
				});
				obj3.CreateFunction("Clear Held Tag", val, (Action)delegate
				{
					SetCurrentTag(GearTag.None);
				});
				obj3.CreateFunction("Clear All Favorites", val, (Action)ClearAllFavorites);
				obj3.CreateFunction("Clear All Tags", val, (Action)ClearAllTags);
				Page obj4 = obj.CreatePage("Offset", val, 0, true);
				obj4.CreateFloat("X", val, offsetX.Value, 0.01f, -1f, 1f, (Action<float>)delegate(float value)
				{
					offsetX.Value = value;
				});
				obj4.CreateFloat("Y", val, offsetY.Value, 0.01f, -1f, 1f, (Action<float>)delegate(float value)
				{
					offsetY.Value = value;
				});
				obj4.CreateFloat("Z", val, offsetZ.Value, 0.01f, -1f, 1f, (Action<float>)delegate(float value)
				{
					offsetZ.Value = value;
				});
				Page obj5 = obj.CreatePage("Text Color", val, 0, true);
				obj5.CreateFloat("Red", val, textRed.Value, 0.05f, 0f, 1f, (Action<float>)delegate(float value)
				{
					textRed.Value = value;
					ApplyInspectorVisuals();
				});
				obj5.CreateFloat("Green", val, textGreen.Value, 0.05f, 0f, 1f, (Action<float>)delegate(float value)
				{
					textGreen.Value = value;
					ApplyInspectorVisuals();
				});
				obj5.CreateFloat("Blue", val, textBlue.Value, 0.05f, 0f, 1f, (Action<float>)delegate(float value)
				{
					textBlue.Value = value;
					ApplyInspectorVisuals();
				});
				Page obj6 = obj.CreatePage("Information", val, 0, true);
				obj6.CreateBool("Show Speed", val, showSpeed.Value, (Action<bool>)delegate(bool value)
				{
					showSpeed.Value = value;
					RefreshCurrentDisplay();
				});
				obj6.CreateBool("Show Impact", val, showImpact.Value, (Action<bool>)delegate(bool value)
				{
					showImpact.Value = value;
					RefreshCurrentDisplay();
				});
				obj6.CreateBool("Show Components", val, showComponents.Value, (Action<bool>)delegate(bool value)
				{
					showComponents.Value = value;
					RefreshCurrentDisplay();
				});
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Warning("BoneMenu setup failed: " + ex.Message);
			}
		}

		private void UpdateTwoHandInfoToggle()
		{
			if (!enabled.Value || !twoHandInfoToggle.Value)
			{
				supportSecondaryWasPressed = false;
				return;
			}
			GameObject objectInHand;
			GameObject objectInHand2;
			try
			{
				objectInHand = Player.GetObjectInHand(Player.LeftHand);
				objectInHand2 = Player.GetObjectInHand(Player.RightHand);
			}
			catch
			{
				return;
			}
			if ((Object)(object)objectInHand == (Object)null || (Object)(object)objectInHand2 == (Object)null)
			{
				supportSecondaryWasPressed = false;
				if (manualInfoVisible)
				{
					manualInfoVisible = false;
					HideInspector(immediate: true);
				}
				return;
			}
			GameObject val = FindWeaponRoot(objectInHand);
			GameObject val2 = FindWeaponRoot(objectInHand2);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				supportSecondaryWasPressed = false;
				return;
			}
			if ((Object)(object)val != (Object)(object)val2)
			{
				supportSecondaryWasPressed = false;
				if (manualInfoVisible)
				{
					manualInfoVisible = false;
					HideInspector(immediate: true);
				}
				return;
			}
			if ((Object)(object)trackedTwoHandWeapon != (Object)(object)val)
			{
				trackedTwoHandWeapon = val;
				primaryHandIsLeft = false;
				primaryHandKnown = true;
			}
			if (!primaryHandKnown)
			{
				return;
			}
			bool leftHand = !primaryHandIsLeft;
			bool secondaryFaceButton = GetSecondaryFaceButton(leftHand);
			if (secondaryFaceButton && !supportSecondaryWasPressed)
			{
				if (manualInfoVisible)
				{
					manualInfoVisible = false;
					HideInspector(immediate: true);
				}
				else
				{
					try
					{
						WeaponInfo weaponInfo = InspectWeapon(val);
						manualInfoVisible = true;
						ShowInspector(weaponInfo.Anchor, weaponInfo);
						manualInfoVisible = true;
					}
					catch (Exception ex)
					{
						((MelonBase)this).LoggerInstance.Warning("Two-hand GEARVISION toggle failed: " + ex.Message);
						manualInfoVisible = false;
					}
				}
			}
			supportSecondaryWasPressed = secondaryFaceButton;
		}

		private bool GetSecondaryFaceButton(bool leftHand)
		{
			//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)
			try
			{
				InputDevice deviceAtXRNode = InputDevices.GetDeviceAtXRNode((XRNode)(leftHand ? 4 : 5));
				if (!((InputDevice)(ref deviceAtXRNode)).isValid)
				{
					return false;
				}
				bool result = default(bool);
				if (((InputDevice)(ref deviceAtXRNode)).TryGetFeatureValue(CommonUsages.secondaryButton, ref result))
				{
					return result;
				}
			}
			catch
			{
			}
			return false;
		}

		private void ToggleFavoriteHeld()
		{
			if (!string.IsNullOrWhiteSpace(currentWeaponName))
			{
				if (favoriteWeapons.Contains(currentWeaponName))
				{
					favoriteWeapons.Remove(currentWeaponName);
				}
				else
				{
					favoriteWeapons.Add(currentWeaponName);
				}
				SaveFavorites();
				RefreshCurrentDisplay();
			}
		}

		private void ClearAllFavorites()
		{
			favoriteWeapons.Clear();
			SaveFavorites();
			RefreshCurrentDisplay();
		}

		private void SetCurrentTag(GearTag tag)
		{
			if (!string.IsNullOrWhiteSpace(currentWeaponName))
			{
				if (tag == GearTag.None)
				{
					weaponTags.Remove(currentWeaponName);
				}
				else
				{
					weaponTags[currentWeaponName] = tag;
				}
				SaveTags();
				RefreshCurrentDisplay();
			}
		}

		private void ClearAllTags()
		{
			weaponTags.Clear();
			SaveTags();
			RefreshCurrentDisplay();
		}

		private void SaveFavorites()
		{
			List<string> list = new List<string>();
			foreach (string favoriteWeapon in favoriteWeapons)
			{
				list.Add(EncodeString(favoriteWeapon));
			}
			favoritesData.Value = string.Join(",", list);
		}

		private void LoadFavorites()
		{
			favoriteWeapons.Clear();
			string value = favoritesData.Value;
			if (string.IsNullOrWhiteSpace(value))
			{
				return;
			}
			string[] array = value.Split(',');
			foreach (string value2 in array)
			{
				string text = DecodeString(value2);
				if (!string.IsNullOrWhiteSpace(text))
				{
					favoriteWeapons.Add(text);
				}
			}
		}

		private void SaveTags()
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, GearTag> weaponTag in weaponTags)
			{
				list.Add(EncodeString(weaponTag.Key) + ":" + (int)weaponTag.Value);
			}
			tagsData.Value = string.Join(",", list);
		}

		private void LoadTags()
		{
			weaponTags.Clear();
			string value = tagsData.Value;
			if (string.IsNullOrWhiteSpace(value))
			{
				return;
			}
			string[] array = value.Split(',');
			foreach (string text in array)
			{
				int num = text.LastIndexOf(':');
				if (num > 0)
				{
					string key = DecodeString(text.Substring(0, num));
					if (int.TryParse(text.Substring(num + 1), out var result) && result > 0 && result <= 6)
					{
						weaponTags[key] = (GearTag)result;
					}
				}
			}
		}

		private string EncodeString(string value)
		{
			try
			{
				return Convert.ToBase64String(Encoding.UTF8.GetBytes(value));
			}
			catch
			{
				return "";
			}
		}

		private string DecodeString(string value)
		{
			try
			{
				return Encoding.UTF8.GetString(Convert.FromBase64String(value));
			}
			catch
			{
				return "";
			}
		}

		private void OnGrabObject(GameObject grabbedObject, Hand hand)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (!enabled.Value || (Object)(object)grabbedObject == (Object)null)
			{
				return;
			}
			try
			{
				WeaponInfo weaponInfo = InspectWeapon(grabbedObject);
				if (weaponInfo.Kind != WeaponKind.Unknown || !(weaponInfo.Mass <= 0.01f))
				{
					bool flag = (object)hand == Player.LeftHand;
					if ((Object)(object)trackedTwoHandWeapon != (Object)(object)weaponInfo.Anchor)
					{
						trackedTwoHandWeapon = weaponInfo.Anchor;
						primaryHandIsLeft = flag;
						primaryHandKnown = true;
					}
					manualInfoVisible = false;
					ShowInspector(weaponInfo.Anchor, weaponInfo);
				}
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Warning("Weapon inspection failed: " + ex.Message);
			}
		}

		private void OnReleaseObject(Hand hand)
		{
			try
			{
				GameObject objectInHand = Player.GetObjectInHand(Player.LeftHand);
				GameObject objectInHand2 = Player.GetObjectInHand(Player.RightHand);
				GameObject val = (((Object)(object)objectInHand != (Object)null) ? FindWeaponRoot(objectInHand) : null);
				GameObject val2 = (((Object)(object)objectInHand2 != (Object)null) ? FindWeaponRoot(objectInHand2) : null);
				if ((Object)(object)trackedTwoHandWeapon != (Object)null && (Object)(object)val != (Object)(object)trackedTwoHandWeapon && (Object)(object)val2 != (Object)(object)trackedTwoHandWeapon)
				{
					trackedTwoHandWeapon = null;
					primaryHandKnown = false;
					supportSecondaryWasPressed = false;
				}
				if ((Object)(object)objectInHand == (Object)null && (Object)(object)objectInHand2 == (Object)null)
				{
					manualInfoVisible = false;
					HideInspector(immediate: false);
				}
			}
			catch
			{
			}
		}

		private WeaponInfo InspectWeapon(GameObject grabbedObject)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			WeaponInfo weaponInfo = new WeaponInfo();
			GameObject val = FindWeaponRoot(grabbedObject);
			if ((Object)(object)val == (Object)null)
			{
				val = grabbedObject;
			}
			weaponInfo.Anchor = val;
			weaponInfo.Name = CleanName(((Object)val).name);
			Rigidbody[] array = Il2CppArrayBase<Rigidbody>.op_Implicit(val.GetComponentsInChildren<Rigidbody>(true));
			float num = 0f;
			float num2 = 0f;
			if (array != null)
			{
				Rigidbody[] array2 = array;
				foreach (Rigidbody val2 in array2)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						num += Mathf.Max(0f, val2.mass);
						float num3 = num2;
						Vector3 velocity = val2.velocity;
						num2 = Mathf.Max(num3, ((Vector3)(ref velocity)).magnitude);
					}
				}
			}
			weaponInfo.Mass = num;
			weaponInfo.Speed = num2;
			weaponInfo.Impact = 0.5f * num * num2 * num2;
			bool flag = false;
			bool flag2 = ContainsWord(weaponInfo.Name, firearmWords);
			bool flag3 = ContainsWord(weaponInfo.Name, meleeWords);
			Component[] array3 = Il2CppArrayBase<Component>.op_Implicit(val.GetComponentsInChildren<Component>(true));
			HashSet<string> hashSet = new HashSet<string>();
			if (array3 != null)
			{
				int num4 = Mathf.Min(array3.Length, 48);
				for (int j = 0; j < num4; j++)
				{
					Component val3 = array3[j];
					if (!((Object)(object)val3 == (Object)null))
					{
						string name = ((object)val3).GetType().Name;
						if (val3 is Gun)
						{
							flag = true;
						}
						if (ContainsWord(name, firearmWords))
						{
							flag2 = true;
						}
						if (ContainsWord(name, meleeWords))
						{
							flag3 = true;
						}
						if (hashSet.Count < 8 && hashSet.Add(name))
						{
							weaponInfo.Components.Add(name);
						}
						if (weaponInfo.ExtraStats.Count < 5)
						{
							ExtractInterestingStats(val3, weaponInfo.ExtraStats);
						}
					}
				}
			}
			if (flag || flag2)
			{
				weaponInfo.Kind = WeaponKind.Firearm;
			}
			else if (flag3)
			{
				weaponInfo.Kind = WeaponKind.Melee;
			}
			else
			{
				weaponInfo.Kind = WeaponKind.Unknown;
			}
			return weaponInfo;
		}

		private GameObject FindWeaponRoot(GameObject grabbedObject)
		{
			if ((Object)(object)grabbedObject == (Object)null)
			{
				return null;
			}
			Transform val = grabbedObject.transform;
			Transform val2 = null;
			for (int i = 0; i < 10; i++)
			{
				if (!((Object)(object)val != (Object)null))
				{
					break;
				}
				if ((Object)(object)((Component)val).GetComponent<Gun>() != (Object)null)
				{
					return ((Component)val).gameObject;
				}
				if ((Object)(object)val2 == (Object)null && (Object)(object)((Component)val).GetComponent<Rigidbody>() != (Object)null)
				{
					val2 = val;
				}
				val = val.parent;
			}
			if ((Object)(object)val2 != (Object)null)
			{
				return ((Component)val2).gameObject;
			}
			return grabbedObject;
		}

		private void ExtractInterestingStats(Component component, List<string> output)
		{
			if ((Object)(object)component == (Object)null || output.Count >= 5)
			{
				return;
			}
			Type type = ((object)component).GetType();
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public;
			try
			{
				PropertyInfo[] properties = type.GetProperties(bindingAttr);
				int num = Math.Min(properties.Length, 40);
				for (int i = 0; i < num; i++)
				{
					if (output.Count >= 5)
					{
						break;
					}
					PropertyInfo propertyInfo = properties[i];
					if (!propertyInfo.CanRead || propertyInfo.GetIndexParameters().Length != 0)
					{
						continue;
					}
					string name = propertyInfo.Name.ToLowerInvariant();
					if (IsInterestingStat(name))
					{
						Type propertyType = propertyInfo.PropertyType;
						if (propertyType.IsPrimitive || !(propertyType != typeof(string)) || propertyType.IsEnum)
						{
							object value = propertyInfo.GetValue(component, null);
							AddStat(output, propertyInfo.Name, value);
						}
					}
				}
			}
			catch
			{
			}
			if (output.Count >= 5)
			{
				return;
			}
			try
			{
				FieldInfo[] fields = type.GetFields(bindingAttr);
				int num2 = Math.Min(fields.Length, 40);
				for (int j = 0; j < num2; j++)
				{
					if (output.Count >= 5)
					{
						break;
					}
					FieldInfo fieldInfo = fields[j];
					string name2 = fieldInfo.Name.ToLowerInvariant();
					if (IsInterestingStat(name2))
					{
						Type fieldType = fieldInfo.FieldType;
						if (fieldType.IsPrimitive || !(fieldType != typeof(string)) || fieldType.IsEnum)
						{
							object value2 = fieldInfo.GetValue(component);
							AddStat(output, fieldInfo.Name, value2);
						}
					}
				}
			}
			catch
			{
			}
		}

		private bool IsInterestingStat(string name)
		{
			if (!name.Contains("ammo") && !name.Contains("round") && !name.Contains("capacity") && !name.Contains("rpm") && !name.Contains("firerate") && !name.Contains("fire_rate") && !name.Contains("velocity") && !name.Contains("muzzle") && !name.Contains("firemode") && !name.Contains("fire_mode"))
			{
				return name.Contains("caliber");
			}
			return true;
		}

		private void AddStat(List<string> output, string name, object value)
		{
			if (value == null)
			{
				return;
			}
			string text = value.ToString();
			if (!string.IsNullOrWhiteSpace(text) && text.Length <= 24)
			{
				string item = name.Replace("_", " ") + ": " + text;
				if (!output.Contains(item))
				{
					output.Add(item);
				}
			}
		}

		private bool ContainsWord(string value, string[] words)
		{
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			string text = value.ToLowerInvariant();
			foreach (string value2 in words)
			{
				if (text.Contains(value2))
				{
					return true;
				}
			}
			return false;
		}

		private string CleanName(string name)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return "Unknown Item";
			}
			return name.Replace("(Clone)", "").Trim();
		}

		private void ShowInspector(GameObject target, WeaponInfo info)
		{
			EnsureInspectorExists();
			currentTarget = target;
			currentWeaponInfo = info;
			currentWeaponName = info.Name;
			fullInspectorText = BuildInspectorText(info);
			currentAlpha = 1f;
			hologramPulseTimer = 0f;
			circleRotation = 0f;
			ResetFlicker();
			showUntil = Time.unscaledTime + displayDuration.Value;
			visible = true;
			inspectorRoot.SetActive(true);
			UpdateCircleVisibility();
			if (swooshAnimation.Value)
			{
				swooshActive = true;
				swooshStartTime = Time.unscaledTime;
			}
			else
			{
				swooshActive = false;
			}
			UpdateInspectorPosition();
			FaceInspectorTowardsHead();
			CaptureLockedRotation();
			if (scanAnimation.Value)
			{
				StartScanAnimation();
			}
			else
			{
				SetDisplayedText(fullInspectorText);
				PlayScanSound();
			}
			ApplyInspectorVisuals();
		}

		private void EnsureInspectorExists()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)inspectorRoot != (Object)null))
			{
				inspectorRoot = new GameObject("GEARVISION_UI");
				Object.DontDestroyOnLoad((Object)(object)inspectorRoot);
				GameObject val = new GameObject("InspectorText");
				val.transform.SetParent(inspectorRoot.transform, false);
				inspectorText = val.AddComponent<TextMesh>();
				inspectorText.anchor = (TextAnchor)0;
				inspectorText.alignment = (TextAlignment)0;
				inspectorText.fontSize = 48;
				inspectorText.characterSize = textSize.Value;
				inspectorText.richText = false;
				val.transform.localPosition = new Vector3(0f, 0.055f, 0f);
				GameObject val2 = new GameObject("HologramGlow");
				val2.transform.SetParent(inspectorRoot.transform, false);
				val2.transform.localPosition = new Vector3(0.0015f, 0.0535f, 0.001f);
				hologramGlowText = val2.AddComponent<TextMesh>();
				hologramGlowText.anchor = (TextAnchor)0;
				hologramGlowText.alignment = (TextAlignment)0;
				hologramGlowText.fontSize = 48;
				hologramGlowText.characterSize = textSize.Value * 1.015f;
				hologramGlowText.richText = false;
				LoadSelectedFont();
				CreateCircleDeck();
				scanAudioSource = inspectorRoot.AddComponent<AudioSource>();
				scanAudioSource.playOnAwake = false;
				scanAudioSource.loop = false;
				scanAudioSource.spatialBlend = 0f;
				scanAudioSource.volume = scanSoundVolume.Value;
				CreateScanSound();
			}
		}

		private void CreateCircleDeck()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			circleDeckRoot = new GameObject("GEARVISION_CircleDeck");
			circleDeckRoot.transform.SetParent(inspectorRoot.transform, false);
			circleDeckRoot.transform.localPosition = new Vector3(0.085f, -0.075f, 0.004f);
			circleDeckRoot.transform.localRotation = Quaternion.identity;
			circleDeckRoot.transform.localScale = new Vector3(1.25f, 1.25f, 1.25f);
			Shader val = Shader.Find("Sprites/Default");
			if ((Object)(object)val == (Object)null)
			{
				val = Shader.Find("Unlit/Color");
			}
			if ((Object)(object)val != (Object)null)
			{
				hologramLineMaterial = new Material(val);
			}
			outerCircle = CreateRing("OuterRing", 0.075f, 32, 0.0018f);
			innerCircle = CreateRing("InnerRing", 0.052f, 24, 0.0013f);
			GameObject val2 = new GameObject("CirclePointer");
			val2.transform.SetParent(circleDeckRoot.transform, false);
			circlePointer = val2.AddComponent<LineRenderer>();
			circlePointer.useWorldSpace = false;
			circlePointer.positionCount = 2;
			circlePointer.startWidth = 0.0017f;
			circlePointer.endWidth = 0.001f;
			circlePointer.SetPosition(0, new Vector3(0.052f, 0f, 0f));
			circlePointer.SetPosition(1, new Vector3(0.075f, 0f, 0f));
			if ((Object)(object)hologramLineMaterial != (Object)null)
			{
				((Renderer)circlePointer).sharedMaterial = hologramLineMaterial;
			}
			CreateHologramCone();
			UpdateCircleVisibility();
		}

		private LineRenderer CreateRing(string name, float radius, int segments, float width)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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)
			GameObject val = new GameObject(name);
			val.transform.SetParent(circleDeckRoot.transform, false);
			LineRenderer val2 = val.AddComponent<LineRenderer>();
			val2.useWorldSpace = false;
			val2.loop = true;
			val2.positionCount = segments;
			val2.startWidth = width;
			val2.endWidth = width;
			for (int i = 0; i < segments; i++)
			{
				float num = (float)i / (float)segments * (float)Math.PI * 2f;
				float num2 = Mathf.Cos(num) * radius;
				float num3 = Mathf.Sin(num) * radius;
				val2.SetPosition(i, new Vector3(num2, num3, 0f));
			}
			if ((Object)(object)hologramLineMaterial != (Object)null)
			{
				((Renderer)val2).sharedMaterial = hologramLineMaterial;
			}
			return val2;
		}

		private void CreateHologramCone()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_00c1: Expected O, but got Unknown
			//IL_00e5: 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_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			coneRoot = new GameObject("GEARVISION_HologramCone");
			coneRoot.transform.SetParent(circleDeckRoot.transform, false);
			coneRoot.transform.localPosition = new Vector3(0f, -0.004f, 0.002f);
			coneRoot.transform.localRotation = Quaternion.identity;
			coneRoot.transform.localScale = Vector3.one;
			coneMeshFilter = coneRoot.AddComponent<MeshFilter>();
			coneRenderer = coneRoot.AddComponent<MeshRenderer>();
			if ((Object)(object)hologramLineMaterial != (Object)null)
			{
				((Renderer)coneRenderer).sharedMaterial = hologramLineMaterial;
			}
			Mesh val = new Mesh();
			((Object)val).name = "GEARVISION_ConeMesh";
			Vector3[] array = (Vector3[])(object)new Vector3[17]
			{
				new Vector3(0f, -0.045f, 0f),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3),
				default(Vector3)
			};
			for (int i = 0; i < 16; i++)
			{
				float num = (float)i / 16f * (float)Math.PI * 2f;
				array[i + 1] = new Vector3(Mathf.Cos(num) * 0.052f, 0f, Mathf.Sin(num) * 0.052f);
			}
			int[] array2 = new int[48];
			for (int j = 0; j < 16; j++)
			{
				int num2 = (j + 1) % 16;
				array2[j * 3] = 0;
				array2[j * 3 + 1] = j + 1;
				array2[j * 3 + 2] = num2 + 1;
			}
			val.vertices = Il2CppStructArray<Vector3>.op_Implicit(array);
			val.triangles = Il2CppStructArray<int>.op_Implicit(array2);
			val.RecalculateNormals();
			val.RecalculateBounds();
			coneMeshFilter.sharedMesh = val;
		}

		private void UpdateCircleVisibility()
		{
			if ((Object)(object)circleDeckRoot != (Object)null)
			{
				circleDeckRoot.SetActive(circleDeckEnabled.Value && visible);
			}
		}

		private void UpdateCircleDeck()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)circleDeckRoot == (Object)null) && circleDeckEnabled.Value)
			{
				circleRotation += circleSpinSpeed.Value * Time.unscaledDeltaTime;
				if ((Object)(object)outerCircle != (Object)null)
				{
					((Component)outerCircle).transform.localRotation = Quaternion.Euler(0f, 0f, circleRotation);
				}
				if ((Object)(object)circlePointer != (Object)null)
				{
					((Component)circlePointer).transform.localRotation = Quaternion.Euler(0f, 0f, circleRotation);
				}
				if ((Object)(object)innerCircle != (Object)null)
				{
					((Component)innerCircle).transform.localRotation = Quaternion.Euler(0f, 0f, (0f - circleRotation) * 0.65f);
				}
			}
		}

		private void CreateScanSound()
		{
			try
			{
				int num = Mathf.RoundToInt(5292f);
				float[] array = new float[num];
				float num2 = 0f;
				for (int i = 0; i < num; i++)
				{
					float num3 = (float)i / 22050f / 0.24f;
					float num4 = Mathf.Lerp(520f, 1050f, num3);
					num2 += (float)Math.PI * 2f * num4 / 22050f;
					float num5 = Mathf.Sin((float)Math.PI * num3);
					float num6 = Mathf.Sin(num2);
					float num7 = Mathf.Sin(num2 * 2f) * 0.18f;
					array[i] = (num6 + num7) * num5 * 0.22f;
				}
				scanAudioClip = AudioClip.Create("GEARVISION_Scan", num, 1, 22050, false);
				scanAudioClip.SetData(Il2CppStructArray<float>.op_Implicit(array), 0);
				scanAudioSource.clip = scanAudioClip;
			}
			catch
			{
			}
		}

		private void PlayScanSound()
		{
			if (scanSound.Value && !((Object)(object)scanAudioSource == (Object)null) && !((Object)(object)scanAudioClip == (Object)null))
			{
				scanAudioSource.Stop();
				scanAudioSource.volume = Mathf.Clamp01(scanSoundVolume.Value);
				scanAudioSource.PlayOneShot(scanAudioClip);
			}
		}

		private void LoadSelectedFont()
		{
			if ((Object)(object)inspectorText == (Object)null)
			{
				return;
			}
			int num = Mathf.Clamp(Mathf.RoundToInt(fontIndex.Value), 0, availableFonts.Length - 1);
			if (num == loadedFontIndex && (Object)(object)currentFont != (Object)null)
			{
				return;
			}
			try
			{
				Font val = Font.CreateDynamicFontFromOSFont(Il2CppStringArray.op_Implicit(availableFonts[num]), 48);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				currentFont = val;
				inspectorText.font = currentFont;
				hologramGlowText.font = currentFont;
				Renderer component = ((Component)inspectorText).GetComponent<Renderer>();
				Renderer component2 = ((Component)hologramGlowText).GetComponent<Renderer>();
				if ((Object)(object)currentFont.material != (Object)null)
				{
					if ((Object)(object)component != (Object)null)
					{
						component.sharedMaterial = currentFont.material;
					}
					if ((Object)(object)component2 != (Object)null)
					{
						component2.sharedMaterial = currentFont.material;
					}
				}
				loadedFontIndex = num;
			}
			catch
			{
			}
		}

		private void StartScanAnimation()
		{
			scanActive = true;
			scanStartTime = Time.unscaledTime;
			nextScanUpdate = 0f;
			lastScanCharacterCount = -1;
			SetDisplayedText("SCANNING...");
			PlayScanSound();
		}

		private void UpdateScanAnimation()
		{
			if (!scanActive)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime < nextScanUpdate)
			{
				return;
			}
			nextScanUpdate = unscaledTime + 1f / 30f;
			float num = Mathf.Clamp01((unscaledTime - scanStartTime) / 0.7f);
			int num2 = Mathf.FloorToInt((float)fullInspectorText.Length * num);
			if (num2 == lastScanCharacterCount)
			{
				return;
			}
			lastScanCharacterCount = num2;
			if (num >= 1f)
			{
				scanActive = false;
				SetDisplayedText(fullInspectorText);
				return;
			}
			string text = "";
			if (num2 > 0)
			{
				text = fullInspectorText.Substring(0, Mathf.Min(num2, fullInspectorText.Length));
			}
			SetDisplayedText("SCANNING...\n\n" + text);
		}

		private void SetDisplayedText(string text)
		{
			if ((Object)(object)inspectorText != (Object)null)
			{
				inspectorText.text = text;
			}
			if ((Object)(object)hologramGlowText != (Object)null)
			{
				hologramGlowText.text = text;
			}
		}

		private void OnPanelLockChanged()
		{
			if (visible && !((Object)(object)currentTarget == (Object)null))
			{
				if (panelLock.Value)
				{
					CaptureLockedRotation();
					return;
				}
				hasLockedRotation = false;
				FaceInspectorTowardsHead();
			}
		}

		private void CaptureLockedRotation()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)currentTarget == (Object)null) && !((Object)(object)inspectorRoot == (Object)null))
			{
				lockedLocalRotation = Quaternion.Inverse(currentTarget.transform.rotation) * inspectorRoot.transform.rotation;
				hasLockedRotation = true;
			}
		}

		private void ApplyPanelRotation()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (panelLock.Value && hasLockedRotation)
			{
				inspectorRoot.transform.rotation = currentTarget.transform.rotation * lockedLocalRotation;
			}
			else
			{
				FaceInspectorTowardsHead();
			}
		}

		private void FaceInspectorTowardsHead()
		{
			//IL_0029: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			Transform head = Player.Head;
			if (!((Object)(object)head == (Object)null) && !((Object)(object)inspectorRoot == (Object)null))
			{
				Vector3 val = inspectorRoot.transform.position - head.position;
				if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
				{
					inspectorRoot.transform.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up);
				}
			}
		}

		private void ResetFlicker()
		{
			flickerCountdown = GetNextFlickerDelay();
			flickerMultiplier = 1f;
			flickerEndTime = 0f;
		}

		private float GetNextFlickerDelay()
		{
			return Mathf.Clamp(flickerStrength.Value, 0, 3) switch
			{
				1 => Random.Range(1.2f, 2.4f), 
				2 => Random.Range(0.6f, 1.3f), 
				3 => Random.Range(0.25f, 0.7f), 
				_ => 9999f, 
			};
		}

		private void UpdateFlicker()
		{
			int num = Mathf.Clamp(flickerStrength.Value, 0, 3);
			if (num <= 0)
			{
				flickerMultiplier = 1f;
				return;
			}
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime < flickerEndTime)
			{
				return;
			}
			flickerMultiplier = 1f;
			flickerCountdown -= Time.unscaledDeltaTime;
			if (!(flickerCountdown > 0f))
			{
				switch (num)
				{
				case 1:
					flickerMultiplier = 0.78f;
					flickerEndTime = unscaledTime + 0.025f;
					break;
				case 2:
					flickerMultiplier = 0.58f;
					flickerEndTime = unscaledTime + 0.04f;
					break;
				default:
					flickerMultiplier = 0.35f;
					flickerEndTime = unscaledTime + 0.055f;
					break;
				}
				flickerCountdown = GetNextFlickerDelay();
			}
		}

		private void UpdateInspector()
		{
			if (!visible || (Object)(object)inspectorRoot == (Object)null)
			{
				return;
			}
			if (!enabled.Value || (Object)(object)currentTarget == (Object)null)
			{
				manualInfoVisible = false;
				HideInspector(immediate: true);
				return;
			}
			UpdateInspectorPosition();
			ApplyPanelRotation();
			UpdateScanAnimation();
			UpdateFlicker();
			UpdateCircleDeck();
			if (manualInfoVisible)
			{
				currentAlpha = 1f;
			}
			else if (fadeEnabled.Value)
			{
				if (Time.unscaledTime > showUntil)
				{
					float num = Mathf.Max(0.05f, fadeDuration.Value);
					currentAlpha = Mathf.MoveTowards(currentAlpha, 0f, Time.unscaledDeltaTime / num);
					if (currentAlpha <= 0.001f)
					{
						HideInspector(immediate: true);
						return;
					}
				}
			}
			else
			{
				currentAlpha = 1f;
			}
			ApplyInspectorVisuals();
		}

		private void UpdateInspectorPosition()
		{
			//IL_0045: 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_0121: 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_008c: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_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)
			if ((Object)(object)currentTarget == (Object)null || (Object)(object)inspectorRoot == (Object)null)
			{
				return;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(offsetX.Value, offsetY.Value, offsetZ.Value);
			Vector3 val2 = val;
			if (swooshActive && swooshAnimation.Value)
			{
				float num = Mathf.Clamp01((Time.unscaledTime - swooshStartTime) / 0.28f);
				float num2 = num * num * (3f - 2f * num);
				Vector3 val3 = new Vector3(val.x * 0.12f, val.y * 0.55f, val.z * 0.55f);
				float num3 = Mathf.Sin(num * (float)Math.PI) * 0.018f;
				float num4 = ((val.x >= 0f) ? 1f : (-1f));
				val2 = Vector3.Lerp(val3, val, num2);
				val2.x += num3 * num4;
				if (num >= 1f)
				{
					swooshActive = false;
				}
			}
			inspectorRoot.transform.position = currentTarget.transform.TransformPoint(val2);
		}

		private void ApplyInspectorVisuals()
		{
			if (!((Object)(object)inspectorText == (Object)null))
			{
				inspectorText.characterSize = textSize.Value;
				hologramGlowText.characterSize = textSize.Value * 1.015f;
				hologramPulseTimer += Time.unscaledDeltaTime;
				float num = hologramPulseTimer % 1.6f;
				float num2 = ((!(num < 0.8f)) ? Mathf.Lerp(1f, 0.82f, (num - 0.8f) / 0.8f) : Mathf.Lerp(0.82f, 1f, num / 0.8f));
				float inspectorColor = currentAlpha * num2 * flickerMultiplier;
				SetInspectorColor(inspectorColor);
			}
		}

		private void SetInspectorColor(float alpha)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: 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_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp01(alpha);
			Color color = default(Color);
			((Color)(ref color))..ctor(textRed.Value, textGreen.Value, textBlue.Value, num);
			inspectorText.color = color;
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(Mathf.Clamp01(textRed.Value * 0.7f + 0.15f), Mathf.Clamp01(textGreen.Value * 0.7f + 0.15f), Mathf.Clamp01(textBlue.Value * 0.9f + 0.1f), num * 0.22f);
			hologramGlowText.color = color2;
			Color val = default(Color);
			((Color)(ref val))..ctor(textRed.Value, textGreen.Value, textBlue.Value, num * 0.55f);
			if ((Object)(object)outerCircle != (Object)null)
			{
				outerCircle.startColor = val;
				outerCircle.endColor = val;
			}
			if ((Object)(object)innerCircle != (Object)null)
			{
				Color val2 = val;
				val2.a = num * 0.3f;
				innerCircle.startColor = val2;
				innerCircle.endColor = val2;
			}
			if ((Object)(object)circlePointer != (Object)null)
			{
				Color val3 = val;
				val3.a = num * 0.8f;
				circlePointer.startColor = val3;
				circlePointer.endColor = val3;
			}
			if ((Object)(object)coneRenderer != (Object)null && (Object)(object)((Renderer)coneRenderer).sharedMaterial != (Object)null)
			{
				Color color3 = default(Color);
				((Color)(ref color3))..ctor(textRed.Value, textGreen.Value, textBlue.Value, num * 0.16f);
				((Renderer)coneRenderer).sharedMaterial.color = color3;
			}
		}

		private void RefreshCurrentDisplay()
		{
			if (currentWeaponInfo != null && visible)
			{
				fullInspectorText = BuildInspectorText(currentWeaponInfo);
				scanActive = false;
				SetDisplayedText(fullInspectorText);
			}
		}

		private void HideInspector(bool immediate)
		{
			if ((Object)(object)inspectorRoot == (Object)null)
			{
				return;
			}
			if (immediate)
			{
				visible = false;
				currentAlpha = 0f;
				currentTarget = null;
				currentWeaponInfo = null;
				currentWeaponName = null;
				scanActive = false;
				swooshActive = false;
				hasLockedRotation = false;
				manualInfoVisible = false;
				if ((Object)(object)scanAudioSource != (Object)null)
				{
					scanAudioSource.Stop();
				}
				if ((Object)(object)circleDeckRoot != (Object)null)
				{
					circleDeckRoot.SetActive(false);
				}
				inspectorRoot.SetActive(false);
			}
			else if (manualInfoVisible)
			{
				manualInfoVisible = false;
				HideInspector(immediate: true);
			}
			else if (!fadeEnabled.Value)
			{
				HideInspector(immediate: true);
			}
			else
			{
				showUntil = Time.unscaledTime;
			}
		}

		private string BuildInspectorText(WeaponInfo info)
		{
			StringBuilder stringBuilder = new StringBuilder(320);
			bool num = favoriteWeapons.Contains(info.Name);
			GearTag value = GearTag.None;
			weaponTags.TryGetValue(info.Name, out value);
			if (num && showFavoriteMarker.Value)
			{
				stringBuilder.AppendLine("[ FAVORITE ]");
			}
			stringBuilder.AppendLine(info.Name.ToUpperInvariant());
			stringBuilder.AppendLine(info.Kind.ToString().ToUpperInvariant());
			if (value != GearTag.None && showTags.Value)
			{
				stringBuilder.Append("TAG: ");
				stringBuilder.AppendLine(value.ToString().ToUpperInvariant());
			}
			stringBuilder.AppendLine();
			stringBuilder.Append("Mass: ");
			stringBuilder.Append(info.Mass.ToString("0.00"));
			stringBuilder.AppendLine(" kg");
			if (showSpeed.Value)
			{
				stringBuilder.Append("Speed: ");
				stringBuilder.Append(info.Speed.ToString("0.0"));
				stringBuilder.AppendLine(" m/s");
			}
			if (showImpact.Value && info.Kind != WeaponKind.Firearm)
			{
				stringBuilder.Append("Impact: ");
				stringBuilder.Append(info.Impact.ToString("0.0"));
				stringBuilder.AppendLine(" J");
			}
			foreach (string extraStat in info.ExtraStats)
			{
				stringBuilder.AppendLine(extraStat);
			}
			if (showComponents.Value && info.Components.Count > 0)
			{
				stringBuilder.AppendLine();
				stringBuilder.AppendLine("COMPONENTS");
				foreach (string component in info.Components)
				{
					stringBuilder.AppendLine(component);
				}
			}
			return stringBuilder.ToString().TrimEnd();
		}
	}
}