Decompiled source of UltimateLethal ScannerSystem v2.2.2

BepInEx/plugins/UltimateLethal_ScannerSystem/UltimateLethal.ScannerSystem.dll

Decompiled a month ago
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("UltimateLethal.ScannerSystem")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("UltimateLethal.ScannerSystem")]
[assembly: AssemblyTitle("UltimateLethal.ScannerSystem")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace UltimateLethal.ScannerSystem
{
	[BepInPlugin("ultimatelethal.scannersystem", "Ultimate Lethal Scanner System", "2.2.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class ScannerSystemPlugin : BaseUnityPlugin
	{
		public const string Guid = "ultimatelethal.scannersystem";

		public const string Name = "Ultimate Lethal Scanner System";

		public const string Version = "2.2.2";

		internal static ScannerSystemPlugin Instance;

		internal static ConfigEntry<float> CooldownBase;

		internal static ConfigEntry<float> CooldownL1;

		internal static ConfigEntry<float> CooldownL2;

		internal static ConfigEntry<float> CooldownL3;

		internal static ConfigEntry<float> DurationBase;

		internal static ConfigEntry<float> DurationL1;

		internal static ConfigEntry<float> DurationL2;

		internal static ConfigEntry<float> DurationL3;

		internal static ConfigEntry<bool> ShowRechargeBar;

		internal static ConfigEntry<float> HudX;

		internal static ConfigEntry<float> HudY;

		internal static ConfigEntry<float> BarWidth;

		internal static ConfigEntry<float> BarHeight;

		internal static ConfigEntry<float> HudScale;

		internal static ConfigEntry<string> BarColorHex;

		internal static ConfigEntry<bool> ShowStatusText;

		internal static ConfigEntry<float> ReadyHoldSeconds;

		internal static ConfigEntry<float> ReadyFadeSeconds;

		internal static ConfigEntry<bool> HideHudOnSpectatorRightClick;

		internal static ConfigEntry<bool> HudCameraSwayEnabled;

		internal static ConfigEntry<float> HudCameraSwayStrength;

		internal static ConfigEntry<float> HudCameraSwayMaxPixels;

		internal static ConfigEntry<float> HudCameraSwayReturnSpeed;

		internal static float LastSuccessfulScan = -999f;

		internal static float NextAllowedScan = -999f;

		internal static float ActiveDuration = 2f;

		internal static float ActiveCooldown = 5f;

		internal static int ActiveScannerLevel;

		internal static bool SpectatorHudHidden;

		private Harmony _harmony;

		private Vector2 _hudCameraSwayOffset = Vector2.zero;

		private Vector3 _hudCameraSwayLastEuler;

		private bool _hudCameraSwayInitialized;

		private bool _wasDeadOrSpectating;

		internal static Vector2 HudCameraSwayOffset => Instance?._hudCameraSwayOffset ?? Vector2.zero;

		internal static float RemainingCooldown => Mathf.Max(0f, NextAllowedScan - Time.unscaledTime);

		internal static float RechargeProgress
		{
			get
			{
				if (!(ActiveCooldown <= 0.01f))
				{
					return Mathf.Clamp01(1f - RemainingCooldown / ActiveCooldown);
				}
				return 1f;
			}
		}

		private void Awake()
		{
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Expected O, but got Unknown
			Instance = this;
			CooldownBase = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "Cooldown Base", 5f, "Scanner cooldown with no Y4 Field Optics upgrade.");
			CooldownL1 = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "Cooldown Level 1", 4.25f, "Scanner cooldown with Y4 Field Optics tier 1.");
			CooldownL2 = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "Cooldown Level 2", 3.5f, "Scanner cooldown with Y4 Field Optics tier 2.");
			CooldownL3 = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "Cooldown Level 3", 2.75f, "Scanner cooldown with Y4 Field Optics tier 3.");
			DurationBase = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "Vision Duration Base", 2f, "Scanner illumination duration with no Y4 Field Optics upgrade.");
			DurationL1 = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "Vision Duration Level 1", 2.5f, "Scanner illumination duration with Y4 Field Optics tier 1.");
			DurationL2 = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "Vision Duration Level 2", 3f, "Scanner illumination duration with Y4 Field Optics tier 2.");
			DurationL3 = ((BaseUnityPlugin)this).Config.Bind<float>("Progression", "Vision Duration Level 3", 3.5f, "Scanner illumination duration with Y4 Field Optics tier 3.");
			ShowRechargeBar = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "Show Scanner HUD", true, "Show the independent Ultimate Lethal scanner HUD.");
			HudX = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "X", 60f, "Scanner HUD X position in pixels at 1920x1080. Default aligns with the compact Ultimate Lethal HUD stack.");
			HudY = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Y", 225f, "Scanner HUD Y position in pixels at 1920x1080. Scales with resolution.");
			BarWidth = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Bar Width", 360f, "Compact scanner HUD row width in pixels at 1920x1080.");
			BarHeight = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Bar Height", 28f, "Compact scanner HUD row height in pixels at 1920x1080.");
			HudScale = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Scale", 1f, "Additional scanner HUD scale multiplier.");
			BarColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("HUD", "Bar Color", "33BFF2", "Scanner recharge fill color. Default matches the blue Crew Morale bar.");
			ShowStatusText = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "Show Status Text", true, "Show contextual Scan Ready / Scan Recharging text.");
			ReadyHoldSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Ready Hold Seconds", 1.25f, "How long the completed scanner HUD stays fully visible after recharge.");
			ReadyFadeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Ready Fade Seconds", 0.75f, "How long the scanner HUD takes to fade out after the ready hold.");
			HideHudOnSpectatorRightClick = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "Hide HUD On Spectator Right Click", true, "Hide the scanner HUD after right-clicking while spectating; it restores automatically when alive.");
			HudCameraSwayEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "Camera Sway Enabled", true, "Give the scanner row the same subtle helmet-style camera inertia as the Crew Morale HUD stack.");
			HudCameraSwayStrength = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Camera Sway Strength", 0.28f, "Camera sway impulse in HUD pixels per degree of camera rotation at 1920x1080.");
			HudCameraSwayMaxPixels = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Camera Sway Max Pixels", 6f, "Maximum camera-sway offset from the configured scanner anchor at 1920x1080.");
			HudCameraSwayReturnSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "Camera Sway Return Speed", 10.5f, "How quickly camera sway glides back to the normal scanner anchor.");
			_harmony = new Harmony("ultimatelethal.scannersystem");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} loaded | BetterScanVision compatibility mode | base {2:0.00}s cooldown / {3:0.00}s vision", "Ultimate Lethal Scanner System", "2.2.2", CooldownBase.Value, DurationBase.Value));
		}

		private void Update()
		{
			try
			{
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)(object)val == (Object)null || val.isPlayerDead)
				{
					if (!_wasDeadOrSpectating)
					{
						ResetLocalScannerState();
					}
					_wasDeadOrSpectating = true;
					if (HideHudOnSpectatorRightClick.Value && Input.GetMouseButtonDown(1))
					{
						SpectatorHudHidden = true;
					}
				}
				else
				{
					if (_wasDeadOrSpectating)
					{
						ResetLocalScannerState();
						_wasDeadOrSpectating = false;
					}
					SpectatorHudHidden = false;
				}
			}
			catch
			{
			}
		}

		private void LateUpdate()
		{
			UpdateHudCameraSway();
		}

		private static void ResetLocalScannerState()
		{
			LastSuccessfulScan = -999f;
			NextAllowedScan = -999f;
			SpectatorHudHidden = false;
			ScannerHallucinationApi.ClearFakeSignal();
			BetterScanVisionBridge.EndActiveVision();
		}

		private void UpdateHudCameraSway()
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_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)
			//IL_0129: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<bool> hudCameraSwayEnabled = HudCameraSwayEnabled;
			if (hudCameraSwayEnabled == null || !hudCameraSwayEnabled.Value)
			{
				_hudCameraSwayInitialized = false;
				_hudCameraSwayOffset = Vector2.zero;
				return;
			}
			PlayerControllerB val = null;
			Camera val2 = null;
			try
			{
				val = GameNetworkManager.Instance?.localPlayerController;
				val2 = val?.gameplayCamera;
			}
			catch
			{
			}
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				_hudCameraSwayInitialized = false;
				_hudCameraSwayOffset = Vector2.zero;
				return;
			}
			Vector3 eulerAngles = ((Component)val2).transform.eulerAngles;
			if (!_hudCameraSwayInitialized)
			{
				_hudCameraSwayLastEuler = eulerAngles;
				_hudCameraSwayInitialized = true;
				_hudCameraSwayOffset = Vector2.zero;
				return;
			}
			float num = Mathf.DeltaAngle(_hudCameraSwayLastEuler.y, eulerAngles.y);
			float num2 = Mathf.DeltaAngle(_hudCameraSwayLastEuler.x, eulerAngles.x);
			_hudCameraSwayLastEuler = eulerAngles;
			float num3 = Mathf.Max(0.5f, Mathf.Min((float)Screen.width / 1920f, (float)Screen.height / 1080f));
			float num4 = Mathf.Max(0f, HudCameraSwayStrength?.Value ?? 0.28f) * num3;
			_hudCameraSwayOffset += new Vector2((0f - num) * num4, (0f - num2) * num4 * 0.75f);
			float num5 = Mathf.Max(0f, HudCameraSwayMaxPixels?.Value ?? 6f) * num3;
			if (num5 > 0.001f)
			{
				_hudCameraSwayOffset = Vector2.ClampMagnitude(_hudCameraSwayOffset, num5);
			}
			else
			{
				_hudCameraSwayOffset = Vector2.zero;
			}
			float num6 = Mathf.Max(0.01f, HudCameraSwayReturnSpeed?.Value ?? 10.5f);
			float num7 = Mathf.Max(0f, Time.unscaledDeltaTime);
			float num8 = 1f - Mathf.Exp((0f - num6) * num7);
			_hudCameraSwayOffset = Vector2.Lerp(_hudCameraSwayOffset, Vector2.zero, num8);
		}

		private void OnGUI()
		{
			try
			{
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)(object)val != (Object)null && (Object)(object)val.quickMenuManager != (Object)null && val.quickMenuManager.isMenuOpen)
				{
					return;
				}
			}
			catch
			{
			}
			try
			{
				PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)(object)val2 == (Object)null || val2.isPlayerDead)
				{
					ScannerHallucinationApi.ClearFakeSignal();
					return;
				}
			}
			catch
			{
				return;
			}
			if (!SpectatorHudHidden)
			{
				IndependentScannerHud.Draw(RechargeProgress, RemainingCooldown <= 0.001f, ShowRechargeBar.Value);
			}
		}

		private void OnDestroy()
		{
			BetterScanVisionBridge.Reset();
			ScannerHallucinationApi.ClearFakeSignal();
			IndependentScannerHud.Destroy();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			SpectatorHudHidden = false;
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		internal static void RefreshProgression()
		{
			ActiveScannerLevel = Mathf.Clamp(Y4Compat.GetFieldOpticsTier(), 0, 3);
			switch (ActiveScannerLevel)
			{
			case 1:
				ActiveCooldown = CooldownL1.Value;
				ActiveDuration = DurationL1.Value;
				break;
			case 2:
				ActiveCooldown = CooldownL2.Value;
				ActiveDuration = DurationL2.Value;
				break;
			case 3:
				ActiveCooldown = CooldownL3.Value;
				ActiveDuration = DurationL3.Value;
				break;
			default:
				ActiveCooldown = CooldownBase.Value;
				ActiveDuration = DurationBase.Value;
				break;
			}
		}
	}
	[HarmonyPatch(typeof(HUDManager), "PingScan_performed")]
	internal static class ScanInputPatch
	{
		[HarmonyPrefix]
		private static bool Prefix()
		{
			ScannerSystemPlugin.RefreshProgression();
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime < ScannerSystemPlugin.NextAllowedScan)
			{
				return false;
			}
			ScannerSystemPlugin.LastSuccessfulScan = unscaledTime;
			ScannerSystemPlugin.NextAllowedScan = unscaledTime + ScannerSystemPlugin.ActiveCooldown;
			BetterScanVisionBridge.Begin();
			return true;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")]
	[HarmonyAfter(new string[] { "DBJ.BetterScanVision" })]
	internal static class VisionUpdatePatch
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(PlayerControllerB __instance)
		{
			if (!((Object)(object)GameNetworkManager.Instance?.localPlayerController != (Object)(object)__instance))
			{
				BetterScanVisionBridge.Update(__instance);
			}
		}
	}
	internal static class BetterScanVisionBridge
	{
		private const float BaseIntensity = 366.9317f;

		private const float BaseRange = 12f;

		private static bool _resolved;

		private static Type _patchType;

		private static Type _baseType;

		private static FieldInfo _nightVisionField;

		private static FieldInfo _configValuesField;

		private static object _configValues;

		private static float _lastResolveAttempt = -999f;

		internal static void Begin()
		{
			Resolve();
		}

		internal static void Update(PlayerControllerB player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return;
			}
			Resolve();
			if (_nightVisionField == null)
			{
				return;
			}
			Light val = null;
			try
			{
				object? value = _nightVisionField.GetValue(null);
				val = (Light)((value is Light) ? value : null);
			}
			catch
			{
				return;
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			float num = Time.unscaledTime - ScannerSystemPlugin.LastSuccessfulScan;
			float num2 = Mathf.Max(0.05f, ScannerSystemPlugin.ActiveDuration);
			if (!(num < 0f) && !(num > num2))
			{
				float num3 = ScanEnvelope(Mathf.Clamp01(num / num2));
				float num4 = ReadSyncedFloat("visionRangeMaxScalar", 2.8f);
				float num5 = ReadSyncedFloat("visionIntensityMaxScalar", 10f);
				if (!player.isInsideFactory && !player.isInHangarShipRoom)
				{
					num4 *= ReadSyncedFloat("outdoorsVisionRangeScalar", 150f);
					num5 *= ReadSyncedFloat("outdoorsVisionIntensityScalar", 12f);
				}
				val.intensity = Mathf.Lerp(0f, 366.9317f * num5, num3);
				val.range = Mathf.Lerp(0f, 12f * num4, num3);
				((Behaviour)val).enabled = true;
			}
		}

		private static float ScanEnvelope(float t)
		{
			if (t <= 0f || t >= 1f)
			{
				return 0f;
			}
			if (t < 0.43f)
			{
				return Mathf.SmoothStep(0f, 1f, t / 0.43f);
			}
			if (t <= 0.72f)
			{
				return 1f;
			}
			return Mathf.SmoothStep(1f, 0f, (t - 0.72f) / 0.28f);
		}

		private static void Resolve()
		{
			if ((_resolved && _nightVisionField != null) || Time.unscaledTime - _lastResolveAttempt < 2f)
			{
				return;
			}
			_lastResolveAttempt = Time.unscaledTime;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type type = null;
				Type type2 = null;
				try
				{
					type = assembly.GetType("BetterScanVision.PlayerControllerBPatches", throwOnError: false);
					type2 = assembly.GetType("BetterScanVision.BetterScanVisionBase", throwOnError: false);
				}
				catch
				{
				}
				if (!(type == null) && !(type2 == null))
				{
					_patchType = type;
					_baseType = type2;
					_nightVisionField = type.GetField("nightVision", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					_configValuesField = type2.GetField("configValues", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					try
					{
						_configValues = _configValuesField?.GetValue(null);
					}
					catch
					{
						_configValues = null;
					}
					_resolved = _nightVisionField != null;
					break;
				}
			}
		}

		private static float ReadSyncedFloat(string fieldName, float fallback)
		{
			try
			{
				if (_configValues == null && _configValuesField != null)
				{
					_configValues = _configValuesField.GetValue(null);
				}
				if (_configValues == null)
				{
					return fallback;
				}
				object obj = _configValues.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(_configValues);
				if (obj == null)
				{
					return fallback;
				}
				object obj2 = obj.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj);
				return (obj2 == null) ? fallback : Convert.ToSingle(obj2);
			}
			catch
			{
				return fallback;
			}
		}

		internal static void EndActiveVision()
		{
			try
			{
				Resolve();
				object? obj = _nightVisionField?.GetValue(null);
				Light val = (Light)((obj is Light) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					val.intensity = 0f;
					val.range = 0f;
					((Behaviour)val).enabled = false;
				}
			}
			catch
			{
			}
		}

		internal static void Reset()
		{
			_resolved = false;
			_patchType = null;
			_baseType = null;
			_nightVisionField = null;
			_configValuesField = null;
			_configValues = null;
		}
	}
	internal static class Y4Compat
	{
		private static MethodInfo _getTier;

		private static bool _searched;

		internal static int GetFieldOpticsTier()
		{
			Resolve();
			if (_getTier == null)
			{
				return 0;
			}
			try
			{
				return Mathf.Clamp(Convert.ToInt32(_getTier.Invoke(null, new object[1] { "better_scanner" })), 0, 3);
			}
			catch
			{
				return 0;
			}
		}

		private static void Resolve()
		{
			if (_searched)
			{
				return;
			}
			_searched = true;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type[] source;
				try
				{
					source = assembly.GetTypes();
				}
				catch (ReflectionTypeLoadException ex)
				{
					source = ex.Types.Where((Type t) => t != null).ToArray();
				}
				catch
				{
					continue;
				}
				MethodInfo methodInfo = source.FirstOrDefault((Type type) => type != null && type.FullName == "Y4NGZUpgrades.Upgrades.Y4NGZUpgradeState")?.GetMethod("GetTier", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
				if (!(methodInfo == null))
				{
					_getTier = methodInfo;
					break;
				}
			}
		}
	}
	public static class ScannerHallucinationApi
	{
		private static float _until;

		private static float _severity;

		private static string _label = "SIGNAL ANOMALY";

		private static int _seed;

		public static bool Active => Time.unscaledTime < _until;

		internal static float Severity
		{
			get
			{
				if (!Active)
				{
					return 0f;
				}
				return Mathf.Clamp01(_severity);
			}
		}

		internal static string Label
		{
			get
			{
				if (!Active)
				{
					return string.Empty;
				}
				return _label;
			}
		}

		internal static int Seed => _seed;

		public static void TriggerFakeSignal(string label, float durationSeconds = 1.2f, float severity = 1f)
		{
			_label = (string.IsNullOrWhiteSpace(label) ? "SIGNAL ANOMALY" : label.Trim());
			_severity = Mathf.Clamp01(severity);
			_until = Time.unscaledTime + Mathf.Clamp(durationSeconds, 0.2f, 3f);
			_seed = Random.Range(1, int.MaxValue);
		}

		public static void ClearFakeSignal()
		{
			_until = 0f;
			_severity = 0f;
			_label = string.Empty;
		}
	}
	internal static class IndependentScannerHud
	{
		private static Texture2D _pixel;

		private static GUIStyle _labelStyle;

		private static GUIStyle _statusStyle;

		private static bool _wasReady;

		private static float _readySince = -999f;

		internal static void Draw(float progress, bool ready, bool show)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_0418: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: 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_0496: Unknown result type (might be due to invalid IL or missing references)
			if (!show || (Object)(object)GameNetworkManager.Instance?.localPlayerController == (Object)null)
			{
				return;
			}
			EnsureGui();
			bool active = ScannerHallucinationApi.Active;
			if (ready && !_wasReady)
			{
				_readySince = Time.unscaledTime;
			}
			else if (!ready)
			{
				_readySince = -999f;
			}
			_wasReady = ready;
			float num = 1f;
			if (ready && !active)
			{
				float num2 = Time.unscaledTime - _readySince;
				float num3 = Mathf.Max(0f, ScannerSystemPlugin.ReadyHoldSeconds.Value);
				float num4 = Mathf.Max(0.05f, ScannerSystemPlugin.ReadyFadeSeconds.Value);
				if (num2 > num3)
				{
					num = 1f - Mathf.Clamp01((num2 - num3) / num4);
				}
				if (num <= 0.001f)
				{
					return;
				}
			}
			float num5 = Mathf.Min((float)Screen.width / 1920f, (float)Screen.height / 1080f);
			float num6 = Mathf.Max(0.25f, num5 * ScannerSystemPlugin.HudScale.Value);
			Vector2 hudCameraSwayOffset = ScannerSystemPlugin.HudCameraSwayOffset;
			float num7 = ScannerSystemPlugin.HudX.Value * num6 + hudCameraSwayOffset.x;
			float num8 = (ScannerSystemPlugin.HudY.Value + 24f) * num6 + hudCameraSwayOffset.y;
			float num9 = Mathf.Max(300f * num6, ScannerSystemPlugin.BarWidth.Value * num6);
			float num10 = Mathf.Max(24f * num6, ScannerSystemPlugin.BarHeight.Value * num6);
			Color val = ParseColor(ScannerSystemPlugin.BarColorHex.Value, new Color(0.2f, 0.75f, 0.95f, 0.98f));
			if (active)
			{
				float severity = ScannerHallucinationApi.Severity;
				float num11 = Time.unscaledTime * 34f + (float)(ScannerHallucinationApi.Seed % 97);
				num7 += Mathf.Sin(num11 * 1.7f) * 4f * severity * num6;
				num8 += Mathf.Cos(num11 * 2.3f) * 2f * severity * num6;
				val = Color.Lerp(val, new Color(1f, 0.28f, 0.1f, 0.98f), 0.72f * severity);
				progress = Mathf.Clamp01(0.12f + Mathf.Abs(Mathf.Sin(num11 * 0.83f)) * 0.86f);
			}
			val.a *= num;
			DrawShell(new Rect(num7, num8, num9, num10), val, num6, num);
			float num12 = 68f * num6;
			float num13 = 132f * num6;
			float num14 = num7 + num12 + 7f * num6;
			float num15 = Mathf.Clamp(num9 - num12 - num13 - 28f * num6, 88f * num6, 128f * num6);
			float num16 = Mathf.Max(6f * num6, 8f * num6);
			float num17 = num8 + (num10 - num16) * 0.5f;
			_labelStyle.fontSize = Mathf.Max(9, Mathf.RoundToInt(11f * num6));
			_labelStyle.normal.textColor = val;
			GUI.Label(new Rect(num7 + 8f * num6, num8, num12, num10), active ? "SCAN?" : "SCAN", _labelStyle);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(num14, num17, num15, num16);
			GUI.color = new Color(0.1f, 0.12f, 0.13f, 0.96f * num);
			GUI.DrawTexture(val2, (Texture)(object)_pixel);
			float num18 = Mathf.Max(1f, num6);
			GUI.color = val;
			GUI.DrawTexture(new Rect(((Rect)(ref val2)).x + num18, ((Rect)(ref val2)).y + num18, Mathf.Max(0f, (((Rect)(ref val2)).width - num18 * 2f) * Mathf.Clamp01(progress)), Mathf.Max(1f, ((Rect)(ref val2)).height - num18 * 2f)), (Texture)(object)_pixel);
			GUI.color = Color.white;
			if (ScannerSystemPlugin.ShowStatusText.Value)
			{
				_statusStyle.fontSize = Mathf.Max(9, Mathf.RoundToInt(10f * num6));
				Color textColor = (ready ? new Color(0.35f, 0.95f, 0.4f, num) : new Color(val.r, val.g, val.b, num));
				_statusStyle.normal.textColor = textColor;
				string text = (active ? ScannerHallucinationApi.Label : (ready ? "READY" : $"RECHARGING {ScannerSystemPlugin.RemainingCooldown:0.0}s"));
				float num19 = num14 + num15 + 8f * num6;
				GUI.Label(new Rect(num19, num8, num7 + num9 - num19 - 8f * num6, num10), text, _statusStyle);
			}
		}

		private static void DrawShell(Rect rect, Color accent, float scale, float alpha)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: 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_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			GUI.color = new Color(0.015f, 0.025f, 0.035f, 0.74f * alpha);
			GUI.DrawTexture(rect, (Texture)(object)_pixel);
			GUI.color = new Color(accent.r, accent.g, accent.b, 0.88f * alpha);
			float num = Mathf.Max(1f, scale);
			float num2 = Mathf.Max(6f * scale, 8f * scale);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num2, num), (Texture)(object)_pixel);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num, num2), (Texture)(object)_pixel);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - num2, ((Rect)(ref rect)).y, num2, num), (Texture)(object)_pixel);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - num, ((Rect)(ref rect)).y, num, num2), (Texture)(object)_pixel);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - num, num2, num), (Texture)(object)_pixel);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - num2, num, num2), (Texture)(object)_pixel);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - num2, ((Rect)(ref rect)).yMax - num, num2, num), (Texture)(object)_pixel);
			GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - num, ((Rect)(ref rect)).yMax - num2, num, num2), (Texture)(object)_pixel);
			GUI.color = Color.white;
		}

		private static void EnsureGui()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0020: 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_004a: 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_0064: Expected O, but got Unknown
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: 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_0094: Expected O, but got Unknown
			if ((Object)(object)_pixel == (Object)null)
			{
				_pixel = new Texture2D(1, 1);
				_pixel.SetPixel(0, 0, Color.white);
				_pixel.Apply();
			}
			if (_labelStyle == null)
			{
				_labelStyle = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)3,
					fontStyle = (FontStyle)1,
					clipping = (TextClipping)1
				};
			}
			if (_statusStyle == null)
			{
				_statusStyle = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)3,
					fontStyle = (FontStyle)1,
					clipping = (TextClipping)1
				};
			}
		}

		private static Color ParseColor(string value, Color fallback)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0020: 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)
			try
			{
				string text = (value ?? string.Empty).Trim().TrimStart('#');
				if (text.Length != 6)
				{
					return fallback;
				}
				int num = Convert.ToInt32(text.Substring(0, 2), 16);
				int num2 = Convert.ToInt32(text.Substring(2, 2), 16);
				int num3 = Convert.ToInt32(text.Substring(4, 2), 16);
				return new Color((float)num / 255f, (float)num2 / 255f, (float)num3 / 255f, fallback.a);
			}
			catch
			{
				return fallback;
			}
		}

		internal static void Destroy()
		{
			if ((Object)(object)_pixel != (Object)null)
			{
				Object.Destroy((Object)(object)_pixel);
			}
			_pixel = null;
			_labelStyle = null;
			_statusStyle = null;
			_wasReady = false;
			_readySince = -999f;
		}
	}
}