Decompiled source of MapperTracker v2.4.20

BepInEx\plugins\Hikaria.MapperTracker\Hikaria.MapperTracker.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using AK;
using Agents;
using Enemies;
using GameData;
using Gear;
using Hikaria.Core;
using Hikaria.Core.SNetworkExt;
using Hikaria.MapperTracker.Controllers;
using Hikaria.MapperTracker.Features;
using Hikaria.MapperTracker.Managers;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using TMPro;
using TheArchive.Core;
using TheArchive.Core.Attributes;
using TheArchive.Core.Attributes.Feature;
using TheArchive.Core.Attributes.Feature.Members;
using TheArchive.Core.Attributes.Feature.Patches;
using TheArchive.Core.Attributes.Feature.Settings;
using TheArchive.Core.FeaturesAPI;
using TheArchive.Core.Localization;
using TheArchive.Core.Models;
using TheArchive.Interfaces;
using TheArchive.Loader;
using TheArchive.Utilities;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.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 Hikaria.MapperTracker
{
	[ArchiveDependency(/*Could not decode attribute arguments.*/)]
	[ArchiveModule("Hikaria.MapperTracker", "MapperTracker", "2.4.20")]
	public class EntryPoint : IArchiveModule
	{
		public ILocalizationService LocalizationService { get; set; }

		public IArchiveLogger Logger { get; set; }

		public void Init()
		{
			Logs.Setup(Logger);
			Logs.LogMessage("OK");
		}
	}
	internal static class Logs
	{
		private static IArchiveLogger _logger;

		public static void Setup(IArchiveLogger logger)
		{
			_logger = logger;
		}

		public static void LogDebug(object data)
		{
			IArchiveLogger logger = _logger;
			if (logger != null)
			{
				logger.Debug(data.ToString());
			}
		}

		public static void LogError(object data)
		{
			IArchiveLogger logger = _logger;
			if (logger != null)
			{
				logger.Error(data.ToString());
			}
		}

		public static void LogInfo(object data)
		{
			IArchiveLogger logger = _logger;
			if (logger != null)
			{
				logger.Info(data.ToString());
			}
		}

		public static void LogMessage(object data)
		{
			IArchiveLogger logger = _logger;
			if (logger != null)
			{
				logger.Msg(ConsoleColor.White, data.ToString());
			}
		}

		public static void LogWarning(object data)
		{
			IArchiveLogger logger = _logger;
			if (logger != null)
			{
				logger.Warning(data.ToString());
			}
		}

		public static void LogNotice(object data)
		{
			IArchiveLogger logger = _logger;
			if (logger != null)
			{
				logger.Notice(data.ToString());
			}
		}

		public static void LogSuccess(object data)
		{
			IArchiveLogger logger = _logger;
			if (logger != null)
			{
				logger.Success(data.ToString());
			}
		}

		public static void LogException(Exception ex)
		{
			IArchiveLogger logger = _logger;
			if (logger != null)
			{
				logger.Exception(ex);
			}
		}
	}
	public struct pMapperTrackerXRayStatus
	{
		public bool enabled;

		public bool focus;

		public pPlayer player;

		public pMapperTrackerXRayStatus(SNet_Player owner)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			player = default(pPlayer);
			((pPlayer)(ref player)).SetPlayer(owner);
			enabled = false;
			focus = false;
		}
	}
	public struct pMapperTrackerXRayData
	{
		public pPlayer player;

		public float fieldOfView;

		public float fieldOfViewFocused;

		public float maxDistanceDefault;

		public float maxDistanceFocused;

		public int raysPerSecondDefault;

		public int raysPerSecondFocused;

		public pMapperTrackerXRayData(SNet_Player owner)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			player = default(pPlayer);
			((pPlayer)(ref player)).SetPlayer(owner);
			fieldOfView = 84f;
			fieldOfViewFocused = 28f;
			maxDistanceDefault = 18f;
			maxDistanceFocused = 32f;
			raysPerSecondDefault = 28000;
			raysPerSecondFocused = 18000;
		}
	}
	public static class PluginInfo
	{
		public const string GUID = "Hikaria.MapperTracker";

		public const string NAME = "MapperTracker";

		public const string VERSION = "2.4.20";
	}
}
namespace Hikaria.MapperTracker.Managers
{
	internal static class MapperTrackerManager
	{
		private static readonly VersionRange VersionRange = VersionRange.op_Implicit("2.x.x");

		public static SNetExt_BroadcastAction<pMapperTrackerXRayData> s_MapperTrackerXRayDataAction;

		public static SNetExt_BroadcastAction<pMapperTrackerXRayStatus> s_MapperTrackerXRayStatusAction;

		public static Dictionary<ulong, MapperTrackerController> MapperTrackerControllerLookup = new Dictionary<ulong, MapperTrackerController>();

		public static Dictionary<int, MapperTrackerController> MapperTrackerXRaysInstanceIDLookup = new Dictionary<int, MapperTrackerController>();

		public static Dictionary<int, MapperTrackerController> MapperTrackerGraphicsInstanceIDLookup = new Dictionary<int, MapperTrackerController>();

		public static void RegisterController(MapperTrackerController controller, EnemyScanner scanner, XRays xRays)
		{
			if (!((Object)(object)controller == (Object)null))
			{
				MapperTrackerControllerLookup[controller.OwnerLookupPublic] = controller;
				if ((Object)(object)xRays != (Object)null)
				{
					MapperTrackerXRaysInstanceIDLookup[((Object)xRays).GetInstanceID()] = controller;
				}
				if ((Object)(object)((scanner != null) ? scanner.m_graphics : null) != (Object)null)
				{
					MapperTrackerGraphicsInstanceIDLookup[((Object)scanner.m_graphics).GetInstanceID()] = controller;
				}
			}
		}

		public static void UnregisterController(MapperTrackerController controller, EnemyScanner scanner, XRays xRays)
		{
			if (!((Object)(object)controller == (Object)null))
			{
				MapperTrackerControllerLookup.Remove(controller.OwnerLookupPublic);
				if ((Object)(object)xRays != (Object)null)
				{
					MapperTrackerXRaysInstanceIDLookup.Remove(((Object)xRays).GetInstanceID());
				}
				if ((Object)(object)((scanner != null) ? scanner.m_graphics : null) != (Object)null)
				{
					MapperTrackerGraphicsInstanceIDLookup.Remove(((Object)scanner.m_graphics).GetInstanceID());
				}
			}
		}

		public static bool TryGetControllerForGraphics(EnemyScannerGraphics graphics, out MapperTrackerController controller)
		{
			controller = null;
			if ((Object)(object)graphics == (Object)null)
			{
				return false;
			}
			if (MapperTrackerGraphicsInstanceIDLookup.TryGetValue(((Object)graphics).GetInstanceID(), out controller) && (Object)(object)controller != (Object)null)
			{
				return true;
			}
			EnemyScanner val = FindScanner(((Component)graphics).transform);
			object obj;
			if (val == null)
			{
				obj = null;
			}
			else
			{
				PlayerAgent owner = ((Item)val).Owner;
				obj = ((owner != null) ? owner.Owner : null);
			}
			if ((Object)obj != (Object)null && MapperTrackerControllerLookup.TryGetValue(((Item)val).Owner.Owner.Lookup, out controller) && (Object)(object)controller != (Object)null)
			{
				MapperTrackerGraphicsInstanceIDLookup[((Object)graphics).GetInstanceID()] = controller;
				return true;
			}
			return false;
		}

		public static bool TryGetControllerForScanner(EnemyScanner scanner, out MapperTrackerController controller)
		{
			controller = null;
			object obj;
			if (scanner == null)
			{
				obj = null;
			}
			else
			{
				PlayerAgent owner = ((Item)scanner).Owner;
				obj = ((owner != null) ? owner.Owner : null);
			}
			if ((Object)obj == (Object)null)
			{
				return false;
			}
			if (MapperTrackerControllerLookup.TryGetValue(((Item)scanner).Owner.Owner.Lookup, out controller))
			{
				return (Object)(object)controller != (Object)null;
			}
			return false;
		}

		private static EnemyScanner FindScanner(Transform t)
		{
			while ((Object)(object)t != (Object)null)
			{
				EnemyScanner component = ((Component)t).GetComponent<EnemyScanner>();
				if ((Object)(object)component != (Object)null)
				{
					return component;
				}
				t = t.parent;
			}
			return null;
		}

		private static bool MapperTrackerListenerFilter(SNet_Player player)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return CoreAPI.IsPlayerInstalledMod(player, "Hikaria.MapperTracker", VersionRange);
		}

		public static void Setup()
		{
			s_MapperTrackerXRayDataAction = SNetExt_BroadcastAction<pMapperTrackerXRayData>.Create(typeof(pMapperTrackerXRayData).FullName, (Action<SNet_Player, pMapperTrackerXRayData>)ReceiveMapperXRayData, (Func<SNet_Player, bool>)MapperTrackerListenerFilter, (SNet_ChannelType)2);
			s_MapperTrackerXRayStatusAction = SNetExt_BroadcastAction<pMapperTrackerXRayStatus>.Create(typeof(pMapperTrackerXRayStatus).FullName, (Action<SNet_Player, pMapperTrackerXRayStatus>)ReceiveMapperXRayStatus, (Func<SNet_Player, bool>)MapperTrackerListenerFilter, (SNet_ChannelType)2);
		}

		private static void ReceiveMapperXRayStatus(SNet_Player sender, pMapperTrackerXRayStatus data)
		{
			SNet_Player val = default(SNet_Player);
			if (!((Object)(object)sender == (Object)null) && ((pPlayer)(ref data.player)).TryGetPlayer(ref val) && val.Lookup == sender.Lookup && MapperTrackerControllerLookup.TryGetValue(sender.Lookup, out var value))
			{
				value.SyncSetXRayStatus(data);
			}
		}

		private static void ReceiveMapperXRayData(SNet_Player sender, pMapperTrackerXRayData data)
		{
			SNet_Player val = default(SNet_Player);
			if (!((Object)(object)sender == (Object)null) && ((pPlayer)(ref data.player)).TryGetPlayer(ref val) && val.Lookup == sender.Lookup && MapperTrackerControllerLookup.TryGetValue(sender.Lookup, out var value))
			{
				value.SyncSetXRayData(data);
			}
		}
	}
}
namespace Hikaria.MapperTracker.Features
{
	[DisallowInGameToggle]
	[DoNotSaveToConfig]
	[EnableFeatureByDefault]
	public class MapperTracker : Feature
	{
		public class MapperTrackerSettings
		{
			[FSHeader("General", true)]
			[FSDisplayName("Enabled")]
			[FSDescription("Local toggle only. Does not affect other players.")]
			public bool EnableMapperTracker { get; set; } = true;

			[FSDisplayName("Toggle Key")]
			public KeyCode ToggleKey { get; set; } = (KeyCode)120;

			[FSHeader("Scan", true)]
			[FSDisplayName("FOV (Normal)")]
			[FSDescription("Synced. Default/max 84.")]
			public float FieldOfView { get; set; } = 84f;

			[FSDisplayName("FOV (Focused)")]
			[FSDescription("Synced. Hold RMB while scanning.")]
			public float FieldOfViewFocused { get; set; } = 28f;

			[FSDisplayName("Max Distance (Normal)")]
			[FSDescription("Synced.")]
			public float MaxDistanceDefault { get; set; } = 18f;

			[FSDisplayName("Max Distance (Focused)")]
			[FSDescription("Synced.")]
			public float MaxDistanceFocused { get; set; } = 32f;

			[FSDisplayName("Rays / Sec (Normal)")]
			[FSDescription("Main cost driver. 20k–40k is usually enough.")]
			public int RaysPerSecondDefault { get; set; } = 28000;

			[FSDisplayName("Rays / Sec (Focused)")]
			[FSDescription("Lower than normal; narrow FOV keeps density.")]
			public int RaysPerSecondFocused { get; set; } = 18000;

			[FSHeader("Appearance", true)]
			[FSDisplayName("Terrain Color")]
			[FSDescription("Your own mapper wash. Default HSV 0/0/5.")]
			public SColor DefaultColor { get; set; } = new SColor(0.05f, 0.05f, 0.05f, (float?)1f);

			[FSDisplayName("Other Players Terrain")]
			[FSDescription("How other players' mapper wash looks to you. Default HSV 0/0/0 (black).")]
			public SColor OtherPlayersTerrainColor { get; set; } = new SColor(0f, 0f, 0f, (float?)1f);

			[FSDisplayName("Terrain Size")]
			public float DefaultSize { get; set; } = 0.5f;

			[FSDisplayName("Enemy Color")]
			public SColor EnemyColor { get; set; } = new SColor(1f, 0f, 0f, (float?)1f);

			[FSDisplayName("Enemy Size")]
			public float EnemySize { get; set; } = 2f;

			[FSDisplayName("Interactable Color")]
			public SColor InteractionColor { get; set; } = new SColor(1f, 0.6f, 0f, (float?)1f);

			[FSDisplayName("Interactable Size")]
			public float InteractionSize { get; set; } = 1f;

			[FSHeader("Battery", true)]
			[FSDisplayName("Enable Battery")]
			[FSDescription("Mapper drains battery while active. Empty battery short-circuits the screen.")]
			public bool EnableBattery { get; set; } = true;

			[FSDisplayName("Battery Duration (s)")]
			[FSDescription("Seconds of continuous mapper use from full charge.")]
			public float BatteryDurationSeconds { get; set; } = 30f;

			[FSDisplayName("Recharge % / Sec")]
			[FSDescription("Battery regain per second while mapper is off or shorted. Screen returns at 100%.")]
			public float BatteryRechargePercentPerSecond { get; set; } = 1f;

			[FSDisplayName("Glitch Duration (s)")]
			[FSDescription("Old-bulb flicker length when battery dies / comes back (~2–3s). Soft minimum around the pattern length.")]
			public float GlitchDurationSeconds { get; set; } = 2.5f;

			[FSDisplayName("Short-Circuit Sound")]
			[FSDescription("Play a short spark/zap on each flicker during the battery glitch.")]
			public bool EnableShortCircuitSound { get; set; } = true;
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class EnemyScanner__UpdateTagProgress__Patch
		{
			private static bool Prefix(EnemyScanner __instance)
			{
				if ((Object)(object)__instance == (Object)null || (Object)(object)((Item)__instance).Owner == (Object)null || (Object)(object)((Item)__instance).Owner.Owner == (Object)null || !((Item)__instance).Owner.Owner.IsLocal)
				{
					return true;
				}
				if (MapperTrackerManager.MapperTrackerControllerLookup.TryGetValue(((Item)__instance).Owner.Owner.Lookup, out var value) && value.IsShortCircuited)
				{
					return false;
				}
				return true;
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class EnemyScanner__UpdateAndRenderScannerData__Patch
		{
			private static void Postfix(EnemyScanner __instance, EnemyAgent enemyAgent, EnemyScannerDataObject scannerData)
			{
				if ((Object)(object)__instance != (Object)null)
				{
					BatteryScreenUI.ApplyDotColorIfOffline(__instance, enemyAgent, scannerData);
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class XRayRenderer__ctor__Patch
		{
			private static void Postfix(XRayRenderer __instance)
			{
				if (__instance.instanceCount < 24000)
				{
					__instance.instanceCount = 24000;
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class XRays__Update__Patch
		{
			private static bool Prefix(XRays __instance)
			{
				if (!MapperTrackerManager.MapperTrackerXRaysInstanceIDLookup.TryGetValue(((Object)__instance).GetInstanceID(), out var value))
				{
					return true;
				}
				try
				{
					float num = Mathf.Min(0.05f, Time.deltaTime);
					int num2 = Mathf.CeilToInt((float)__instance.raysPerSecond * num);
					if (num2 > 1800)
					{
						num2 = 1800;
					}
					__instance.Cast(num2);
					if ((Object)(object)__instance.m_renderer != (Object)null)
					{
						__instance.m_renderer.range = __instance.maxDistance;
						__instance.m_renderer.mode = (value.IsSyncFocused ? 1 : 0);
					}
					return false;
				}
				catch
				{
					return false;
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class EnemyScanner__OnWield__Patch
		{
			private static void Postfix(EnemyScanner __instance)
			{
				if (!((Object)(object)__instance == (Object)null))
				{
					GameObject gameObject = ((Component)__instance).gameObject;
					MapperTrackerController mapperTrackerController = gameObject.GetComponent<MapperTrackerController>();
					if ((Object)(object)mapperTrackerController == (Object)null)
					{
						mapperTrackerController = gameObject.AddComponent<MapperTrackerController>();
						mapperTrackerController.Setup((ItemEquippable)(object)__instance, ((Item)__instance).Owner);
					}
					mapperTrackerController.OnWield();
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class EnemyScanner__OnUnWield__Patch
		{
			private static void Prefix(EnemyScanner __instance)
			{
				MapperTrackerController component = ((Component)__instance).gameObject.GetComponent<MapperTrackerController>();
				if ((Object)(object)component != (Object)null)
				{
					component.OnUnWield();
				}
			}
		}

		[ArchivePatch(/*Could not decode attribute arguments.*/)]
		private class PlayerInventorySynced__SyncWieldItem__Patch
		{
			private static void Prefix(PlayerInventorySynced __instance, ItemEquippable item)
			{
				if (!((Object)(object)item == (Object)null) && !((PlayerInventoryBase)__instance).Owner.Owner.IsLocal && !((Object)(object)((PlayerInventoryBase)__instance).WieldedItem == (Object)null))
				{
					MapperTrackerController component = ((Component)((PlayerInventoryBase)__instance).WieldedItem).gameObject.GetComponent<MapperTrackerController>();
					if (!CanDoMapper(item) && (Object)(object)component != (Object)null)
					{
						component.OnUnWield();
					}
				}
			}

			private static void Postfix(PlayerInventorySynced __instance, ItemEquippable item)
			{
				if (!((Object)(object)item == (Object)null) && !((PlayerInventoryBase)__instance).Owner.Owner.IsLocal && CanDoMapper(item))
				{
					GameObject gameObject = ((Component)item).gameObject;
					MapperTrackerController mapperTrackerController = gameObject.GetComponent<MapperTrackerController>();
					if ((Object)(object)mapperTrackerController == (Object)null)
					{
						mapperTrackerController = gameObject.AddComponent<MapperTrackerController>();
					}
					mapperTrackerController.Setup(item, ((PlayerInventoryBase)__instance).Owner);
					mapperTrackerController.OnWield();
				}
			}
		}

		private const uint BiotrackerGearCategoryId = 9u;

		private const int MaxRaysPerFrame = 1800;

		private const int RendererInstanceCount = 24000;

		public override string Name => "Mapper Tracker";

		public override bool InlineSettingsIntoParentMenu => true;

		public static ILocalizationService Localization { get; set; }

		[FeatureConfig]
		public static MapperTrackerSettings Settings { get; set; }

		public override void Init()
		{
			ClassInjector.RegisterTypeInIl2Cpp<MapperTrackerController>(false);
			MapperTrackerManager.Setup();
		}

		public override void Update()
		{
			MapperTrackerController.TickLocalBatteryFromFeature();
		}

		private static bool CanDoMapper(ItemEquippable itemEquippable)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			if ((Object)(object)itemEquippable == (Object)null || ((Item)itemEquippable).ItemDataBlock == null || itemEquippable.GearCategoryData == null)
			{
				return false;
			}
			if ((int)((Item)itemEquippable).ItemDataBlock.inventorySlot == 3)
			{
				return ((GameDataBlockBase<GearCategoryDataBlock>)(object)itemEquippable.GearCategoryData).persistentID == 9;
			}
			return false;
		}
	}
}
namespace Hikaria.MapperTracker.Controllers
{
	internal static class BatteryScreenUI
	{
		private class ScreenFx
		{
			public bool OfflineVisualActive;

			public bool RestoreGlitchActive;

			public bool CleanedLegacy;

			public int RestoreFramesLeft;

			public bool SavedCols;

			public Color SavedColEnemy;

			public Color SavedPulseStart;

			public Color SavedPulseEnd;

			public float SavedScanConeDotMin = 0.5f;

			public float GlitchStartUnscaled;

			public float RestoreGlitchStartUnscaled;

			public int LastGlitchSoundBit = -1;

			public bool PlayedInitialShortSound;
		}

		private const string DepleteGlitchPattern = "10101010100101001010000000";

		private const string RestoreGlitchPattern = "0010010100101010010111111";

		private const float GlitchBitSeconds = 0.09f;

		private static readonly Color Hidden = new Color(0f, 0f, 0f, 0f);

		private static readonly Dictionary<int, ScreenFx> s_fx = new Dictionary<int, ScreenFx>();

		public static float DepleteGlitchDuration => (float)"10101010100101001010000000".Length * 0.09f;

		public static float RestoreGlitchDuration => (float)"0010010100101010010111111".Length * 0.09f;

		public static void Update(EnemyScanner scanner, BatterySystem.State state)
		{
			if ((Object)(object)((scanner != null) ? scanner.m_screen : null) == (Object)null)
			{
				return;
			}
			ScreenFx screenFx = Ensure(scanner);
			if (!screenFx.CleanedLegacy)
			{
				DestroyLegacyOverlays(scanner);
				screenFx.CleanedLegacy = true;
			}
			ForceScreenAssemblyOn(scanner);
			float normalized = Mathf.Clamp01(state.Charge / 100f);
			bool isOffline = state.IsOffline;
			bool flag = isOffline && state.GlitchRemaining > 0f;
			bool flag2 = !isOffline && screenFx.RestoreGlitchActive;
			bool glitching = flag || flag2;
			ApplyBatteryReadout(scanner, normalized, glitching, isOffline && !flag, state.Charge);
			if (isOffline)
			{
				if (!screenFx.OfflineVisualActive)
				{
					SaveScannerColors(scanner, screenFx);
					screenFx.GlitchStartUnscaled = Time.unscaledTime;
					screenFx.OfflineVisualActive = true;
					screenFx.RestoreGlitchActive = false;
					screenFx.LastGlitchSoundBit = -1;
					TryPlayDepleteSting(scanner, state);
				}
				bool flag3 = flag && IsGlitchBitOn(screenFx.GlitchStartUnscaled, "10101010100101001010000000");
				ApplyTempColEnemy(scanner, screenFx, flag3);
				if (flag)
				{
					TickGlitchSound(scanner, screenFx, screenFx.GlitchStartUnscaled, "10101010100101001010000000");
				}
				if (flag && flag3)
				{
					ShowHologram(scanner);
				}
				else if (!flag)
				{
					HideHologram(scanner);
				}
			}
			else if (screenFx.OfflineVisualActive)
			{
				screenFx.OfflineVisualActive = false;
				StartRestoreGlitch(scanner, screenFx);
			}
			else if (screenFx.RestoreGlitchActive)
			{
				bool flag4 = IsGlitchBitOn(screenFx.RestoreGlitchStartUnscaled, "0010010100101010010111111");
				ApplyTempColEnemy(scanner, screenFx, flag4);
				TickGlitchSound(scanner, screenFx, screenFx.RestoreGlitchStartUnscaled, "0010010100101010010111111");
				if (flag4)
				{
					ShowHologram(scanner);
				}
				if (IsGlitchPatternDone(screenFx.RestoreGlitchStartUnscaled, "0010010100101010010111111"))
				{
					screenFx.RestoreGlitchActive = false;
					screenFx.RestoreFramesLeft = 90;
					BeginRestore(scanner, screenFx);
					ForceRescan(scanner);
				}
			}
			else if (screenFx.RestoreFramesLeft > 0)
			{
				ForceRescan(scanner);
				screenFx.RestoreFramesLeft--;
				if (screenFx.RestoreFramesLeft <= 0)
				{
					FinishRestore(scanner, screenFx);
				}
			}
		}

		public static void ApplyDotColorIfOffline(EnemyScanner scanner, EnemyAgent enemy, EnemyScannerDataObject data)
		{
			//IL_00ac: 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)
			if ((Object)(object)enemy == (Object)null)
			{
				return;
			}
			object obj;
			if (scanner == null)
			{
				obj = null;
			}
			else
			{
				PlayerAgent owner = ((Item)scanner).Owner;
				obj = ((owner != null) ? owner.Owner : null);
			}
			if ((Object)obj == (Object)null || !((Item)scanner).Owner.Owner.IsLocal)
			{
				return;
			}
			ScreenFx screenFx = Ensure(scanner);
			BatterySystem.State state = BatterySystem.Get(((Item)scanner).Owner.Owner.Lookup);
			bool flag;
			if (state.IsOffline)
			{
				flag = state.GlitchRemaining > 0f && IsGlitchBitOn(screenFx.GlitchStartUnscaled, "10101010100101001010000000");
			}
			else
			{
				if (!screenFx.RestoreGlitchActive)
				{
					return;
				}
				flag = IsGlitchBitOn(screenFx.RestoreGlitchStartUnscaled, "0010010100101010010111111");
			}
			PaintMatOnly(data, flag ? enemy.m_scannerColor : Hidden);
		}

		public static void ClearShortCircuitVisual(EnemyScanner scanner)
		{
			if (!((Object)(object)scanner == (Object)null))
			{
				ScreenFx screenFx = Ensure(scanner);
				ForceScreenAssemblyOn(scanner);
				screenFx.OfflineVisualActive = false;
				if (!screenFx.SavedCols)
				{
					SaveScannerColors(scanner, screenFx);
				}
				StartRestoreGlitch(scanner, screenFx);
			}
		}

		public static void DestroyFor(EnemyScanner scanner)
		{
			if ((Object)(object)scanner == (Object)null)
			{
				return;
			}
			PlayerAgent owner = ((Item)scanner).Owner;
			SNet_Player val = ((owner != null) ? owner.Owner : null);
			if ((Object)(object)val != (Object)null && val.IsLocal && BatterySystem.IsOffline(val.Lookup))
			{
				DestroyLegacyOverlays(scanner);
				return;
			}
			int instanceID = ((Object)scanner).GetInstanceID();
			if (s_fx.TryGetValue(instanceID, out var value))
			{
				FinishRestore(scanner, value);
				ShowHologram(scanner);
				s_fx.Remove(instanceID);
			}
			DestroyLegacyOverlays(scanner);
		}

		private static void StartRestoreGlitch(EnemyScanner scanner, ScreenFx fx)
		{
			fx.RestoreGlitchActive = true;
			fx.RestoreGlitchStartUnscaled = Time.unscaledTime;
			fx.RestoreFramesLeft = 0;
			fx.LastGlitchSoundBit = -1;
			fx.PlayedInitialShortSound = true;
			ShowHologram(scanner);
		}

		private static void TryPlayDepleteSting(EnemyScanner scanner, BatterySystem.State state)
		{
			ScreenFx screenFx = Ensure(scanner);
			if (state.DepleteStingPlayed)
			{
				screenFx.PlayedInitialShortSound = true;
				return;
			}
			PlayInitialShortCircuit(scanner);
			screenFx.PlayedInitialShortSound = true;
			state.DepleteStingPlayed = true;
			object obj;
			if (scanner == null)
			{
				obj = null;
			}
			else
			{
				PlayerAgent owner = ((Item)scanner).Owner;
				obj = ((owner != null) ? owner.Owner : null);
			}
			SNet_Player val = (SNet_Player)obj;
			if ((Object)(object)val != (Object)null)
			{
				BatterySystem.Set(val.Lookup, state);
			}
		}

		private static void TickGlitchSound(EnemyScanner scanner, ScreenFx fx, float startUnscaled, string pattern)
		{
			if (Hikaria.MapperTracker.Features.MapperTracker.Settings == null || !Hikaria.MapperTracker.Features.MapperTracker.Settings.EnableShortCircuitSound)
			{
				return;
			}
			int num = Mathf.FloorToInt((Time.unscaledTime - startUnscaled) / 0.09f);
			if (num >= 0 && num < pattern.Length && num != fx.LastGlitchSoundBit)
			{
				fx.LastGlitchSoundBit = num;
				if (pattern[num] == '1' && (num <= 0 || pattern[num - 1] != '1'))
				{
					PlaySpark(scanner);
				}
			}
		}

		private static void PlayInitialShortCircuit(EnemyScanner scanner)
		{
			if (Hikaria.MapperTracker.Features.MapperTracker.Settings == null || !Hikaria.MapperTracker.Features.MapperTracker.Settings.EnableShortCircuitSound)
			{
				return;
			}
			try
			{
				CellSoundPlayer localSound = GetLocalSound(scanner);
				if (localSound != null)
				{
					SharedUtils.SafePost(localSound, EVENTS.BATTERY_STATION_POWERDOWN_FAILURE, true);
				}
			}
			catch
			{
			}
		}

		private static void PlaySpark(EnemyScanner scanner)
		{
			try
			{
				CellSoundPlayer localSound = GetLocalSound(scanner);
				if (localSound != null)
				{
					SharedUtils.SafePost(localSound, EVENTS.WELD_SPARK, true);
				}
			}
			catch
			{
			}
		}

		private static CellSoundPlayer GetLocalSound(EnemyScanner scanner)
		{
			PlayerAgent val = ((scanner != null) ? ((Item)scanner).Owner : null);
			if (((val != null) ? val.Sound : null) != null)
			{
				return val.Sound;
			}
			PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
			if (localPlayerAgent == null)
			{
				return null;
			}
			return localPlayerAgent.Sound;
		}

		private static void ApplyTempColEnemy(EnemyScanner scanner, ScreenFx fx, bool show)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			if (fx.SavedCols)
			{
				scanner.m_colEnemy = (show ? fx.SavedColEnemy : Hidden);
				scanner.m_colPulseStart = (show ? fx.SavedPulseStart : Hidden);
				scanner.m_colPulseEnd = (show ? fx.SavedPulseEnd : Hidden);
			}
		}

		private static bool IsGlitchBitOn(float startUnscaled, string pattern)
		{
			int num = Mathf.FloorToInt((Time.unscaledTime - startUnscaled) / 0.09f);
			if (num < 0 || num >= pattern.Length)
			{
				return false;
			}
			return pattern[num] == '1';
		}

		private static bool IsGlitchPatternDone(float startUnscaled, string pattern)
		{
			return Time.unscaledTime - startUnscaled >= (float)pattern.Length * 0.09f;
		}

		private static ScreenFx Ensure(EnemyScanner scanner)
		{
			int instanceID = ((Object)scanner).GetInstanceID();
			if (!s_fx.TryGetValue(instanceID, out var value))
			{
				value = new ScreenFx();
				s_fx[instanceID] = value;
			}
			return value;
		}

		private static void SaveScannerColors(EnemyScanner scanner, ScreenFx fx)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!fx.SavedCols)
			{
				fx.SavedColEnemy = scanner.m_colEnemy;
				fx.SavedPulseStart = scanner.m_colPulseStart;
				fx.SavedPulseEnd = scanner.m_colPulseEnd;
				fx.SavedScanConeDotMin = scanner.m_scanConeDotMin;
				fx.SavedCols = true;
			}
		}

		private static void PaintMatOnly(EnemyScannerDataObject data, Color color)
		{
			//IL_0033: 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)
			try
			{
				if (((data != null) ? data.m_matProp : null) != null)
				{
					int color2 = EnemyScannerGraphics._Color;
					if (color2 != 0)
					{
						data.m_matProp.SetColor(color2, color);
					}
					else
					{
						data.m_matProp.SetColor("_Color", color);
					}
				}
			}
			catch
			{
			}
		}

		private static void BeginRestore(EnemyScanner scanner, ScreenFx fx)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			ShowHologram(scanner);
			ForceScreenAssemblyOn(scanner);
			scanner.m_scanConeDotMin = -1f;
			if (fx.SavedCols)
			{
				scanner.m_colEnemy = fx.SavedColEnemy;
				scanner.m_colPulseStart = fx.SavedPulseStart;
				scanner.m_colPulseEnd = fx.SavedPulseEnd;
			}
		}

		private static void FinishRestore(EnemyScanner scanner, ScreenFx fx)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			fx.RestoreGlitchActive = false;
			if (fx.SavedCols)
			{
				scanner.m_scanConeDotMin = fx.SavedScanConeDotMin;
				scanner.m_colEnemy = fx.SavedColEnemy;
				scanner.m_colPulseStart = fx.SavedPulseStart;
				scanner.m_colPulseEnd = fx.SavedPulseEnd;
				fx.SavedCols = false;
			}
			DirtyAllEnemyColors(scanner);
		}

		private static void ForceRescan(EnemyScanner scanner)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				PlayerAgent owner = ((Item)scanner).Owner;
				scanner.m_scanConeDotMin = -1f;
				scanner.m_detectedListIndex = 0;
				scanner.m_nodeListIndex = 0;
				scanner.m_nodeListStepsLeft = 1024;
				scanner.RefreshUpdateID();
				scanner.RefreshNodeEnemyList();
				if (((owner != null) ? ((Agent)owner).CourseNode : null) != null)
				{
					List<EnemyAgent> val = new List<EnemyAgent>();
					EnemyScanner.BotGetScanResult(((Agent)owner).CourseNode, ((Agent)owner).Position, val);
					int count = val.Count;
					for (int i = 0; i < count; i++)
					{
						EnemyAgent val2 = val[i];
						if ((Object)(object)val2 == (Object)null)
						{
							continue;
						}
						val2.m_hasDirtyScannerColor = true;
						EnemyScannerDataObject scannerData = val2.ScannerData;
						if (scannerData != null)
						{
							scannerData.m_updateID = scanner.m_updateID - 1;
						}
						try
						{
							val2.UpdateScannerData();
						}
						catch
						{
						}
						if (scannerData != null)
						{
							try
							{
								scanner.UpdateAndRenderScannerData(val2, scannerData);
							}
							catch
							{
							}
						}
					}
				}
				DirtyAllEnemyColors(scanner);
				scanner.UpdateDetectedEnemies(1024);
				EnemyScannerGraphics graphics = scanner.m_graphics;
				if (graphics != null)
				{
					graphics.ResetTargetsCmd();
				}
				scanner.UpdateDetectedEnemies(1024);
				EnemyScannerGraphics graphics2 = scanner.m_graphics;
				if (graphics2 != null)
				{
					graphics2.Render();
				}
			}
			catch
			{
			}
		}

		private static void DirtyAllEnemyColors(EnemyScanner scanner)
		{
			DirtyList(scanner.m_enemiesDetected);
			DirtyList(scanner.m_enemiesInNodes);
		}

		private static void DirtyList(List<EnemyAgent> list)
		{
			if (list == null)
			{
				return;
			}
			int count = list.Count;
			for (int i = 0; i < count; i++)
			{
				EnemyAgent val = list[i];
				if (!((Object)(object)val == (Object)null))
				{
					val.m_hasDirtyScannerColor = true;
					try
					{
						val.UpdateScannerData();
					}
					catch
					{
					}
				}
			}
		}

		private static void ApplyBatteryReadout(EnemyScanner scanner, float normalized, bool glitching, bool rebooting, float charge)
		{
			EnemyScannerScreen screen = scanner.m_screen;
			if (!((Object)(object)screen == (Object)null))
			{
				string text;
				if (glitching)
				{
					text = "<#FF3333>BAT ERR</color>";
				}
				else if (rebooting)
				{
					text = $"<#888>REBOOT {charge:0}%</color>";
				}
				else
				{
					string value = ((normalized > 0.35f) ? "#3FF28C" : ((normalized > 0.15f) ? "#FFBF26" : "#FF4433"));
					text = $"<{value}>BAT {charge:0}%</color>";
				}
				try
				{
					screen.SetStatusText(text);
				}
				catch
				{
				}
				if ((Object)(object)screen.m_statusTextCharge != (Object)null)
				{
					((TMP_Text)screen.m_statusTextCharge).SetText(text, true);
				}
			}
		}

		private static void HideHologram(EnemyScanner scanner)
		{
			HologramGraphics hologramGraphics = scanner.m_hologramGraphics;
			SetActiveSafe((hologramGraphics != null) ? ((Component)hologramGraphics).gameObject : null, active: false);
			HologramGraphics hologramGraphics2 = scanner.m_hologramGraphics;
			if (((hologramGraphics2 != null) ? hologramGraphics2.m_holoParts : null) == null)
			{
				return;
			}
			Enumerator<HologramGraphicsPart> enumerator = scanner.m_hologramGraphics.m_holoParts.GetEnumerator();
			while (enumerator.MoveNext())
			{
				HologramGraphicsPart current = enumerator.Current;
				if ((Object)(object)current != (Object)null)
				{
					SetActiveSafe(((Component)current).gameObject, active: false);
				}
			}
		}

		private static void ShowHologram(EnemyScanner scanner)
		{
			HologramGraphics hologramGraphics = scanner.m_hologramGraphics;
			SetActiveSafe((hologramGraphics != null) ? ((Component)hologramGraphics).gameObject : null, active: true);
			HologramGraphics hologramGraphics2 = scanner.m_hologramGraphics;
			if (((hologramGraphics2 != null) ? hologramGraphics2.m_holoParts : null) == null)
			{
				return;
			}
			Enumerator<HologramGraphicsPart> enumerator = scanner.m_hologramGraphics.m_holoParts.GetEnumerator();
			while (enumerator.MoveNext())
			{
				HologramGraphicsPart current = enumerator.Current;
				if ((Object)(object)current != (Object)null)
				{
					SetActiveSafe(((Component)current).gameObject, active: true);
				}
			}
		}

		private static void ForceScreenAssemblyOn(EnemyScanner scanner)
		{
			Transform scannerObjRoot = scanner.m_scannerObjRoot;
			SetActiveSafe((scannerObjRoot != null) ? ((Component)scannerObjRoot).gameObject : null, active: true);
			if ((Object)(object)scanner.m_screen != (Object)null)
			{
				SetActiveSafe(((Component)scanner.m_screen).gameObject, active: true);
			}
			EnemyScannerScreen screen = scanner.m_screen;
			if ((Object)(object)((screen != null) ? screen.m_guixRoot : null) != (Object)null)
			{
				SetActiveSafe(((Component)scanner.m_screen.m_guixRoot).gameObject, active: true);
			}
			if ((Object)(object)scanner.m_graphics != (Object)null)
			{
				SetActiveSafe(((Component)scanner.m_graphics).gameObject, active: true);
			}
			EnemyScannerGraphics graphics = scanner.m_graphics;
			if ((Object)(object)((graphics != null) ? graphics.m_display : null) != (Object)null)
			{
				SetActiveSafe(((Component)scanner.m_graphics.m_display).gameObject, active: true);
				scanner.m_graphics.m_display.enabled = true;
			}
		}

		private static void DestroyLegacyOverlays(EnemyScanner scanner)
		{
			if ((Object)(object)scanner == (Object)null)
			{
				return;
			}
			Il2CppArrayBase<Transform> componentsInChildren = ((Component)scanner).GetComponentsInChildren<Transform>(true);
			List<GameObject> list = new List<GameObject>();
			foreach (Transform item in componentsInChildren)
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				string text = ((Object)item).name ?? string.Empty;
				if (!text.StartsWith("MapperTracker_"))
				{
					switch (text)
					{
					case "MT_LcdBlackPlate":
					case "BatteryPanel":
					case "BatteryBg":
					case "BatteryFill":
					case "BatteryValue":
					case "BatteryTitle":
					case "ScreenBlackout":
						break;
					default:
						continue;
					}
				}
				list.Add(((Component)item).gameObject);
			}
			foreach (GameObject item2 in list)
			{
				if ((Object)(object)item2 != (Object)null)
				{
					Object.Destroy((Object)(object)item2);
				}
			}
		}

		private static void SetActiveSafe(GameObject go, bool active)
		{
			if ((Object)(object)go != (Object)null && go.activeSelf != active)
			{
				go.SetActive(active);
			}
		}
	}
	internal static class BatterySystem
	{
		public struct State
		{
			public float Charge;

			public bool IsOffline;

			public float GlitchRemaining;

			public bool DepleteStingPlayed;
		}

		public const float MaxCharge = 100f;

		private static readonly Dictionary<ulong, State> s_states = new Dictionary<ulong, State>();

		public static State Get(ulong lookup)
		{
			if (!s_states.TryGetValue(lookup, out var value))
			{
				value = new State
				{
					Charge = 100f
				};
				s_states[lookup] = value;
			}
			return value;
		}

		public static void Set(ulong lookup, State state)
		{
			s_states[lookup] = state;
		}

		public static void Clear(ulong lookup)
		{
			s_states.Remove(lookup);
		}

		public static void Tick(ulong lookup, bool mapperActive, float drainPerSecond, float rechargePerSecond, float glitchDuration, float dt, out State state, out bool justWentOffline)
		{
			justWentOffline = false;
			state = Get(lookup);
			if (state.IsOffline)
			{
				if (state.GlitchRemaining > 0f)
				{
					state.GlitchRemaining = Mathf.Max(0f, state.GlitchRemaining - dt);
				}
				state.Charge = Mathf.Min(100f, state.Charge + rechargePerSecond * dt);
				if (state.Charge >= 99.99f)
				{
					state.Charge = 100f;
					state.IsOffline = false;
					state.GlitchRemaining = 0f;
					state.DepleteStingPlayed = false;
				}
				Set(lookup, state);
				return;
			}
			if (mapperActive)
			{
				state.Charge = Mathf.Max(0f, state.Charge - drainPerSecond * dt);
				if (state.Charge <= 0f)
				{
					state.Charge = 0f;
					state.IsOffline = true;
					state.GlitchRemaining = Mathf.Max(BatteryScreenUI.DepleteGlitchDuration, glitchDuration);
					state.DepleteStingPlayed = false;
					justWentOffline = true;
				}
			}
			else
			{
				state.Charge = Mathf.Min(100f, state.Charge + rechargePerSecond * dt);
			}
			Set(lookup, state);
		}

		public static bool IsOffline(ulong lookup)
		{
			return Get(lookup).IsOffline;
		}

		public static bool IsGlitching(ulong lookup)
		{
			State state = Get(lookup);
			if (state.IsOffline)
			{
				return state.GlitchRemaining > 0f;
			}
			return false;
		}
	}
	public class MapperTrackerController : MonoBehaviour
	{
		public bool IsLocallyOwned;

		private ItemEquippable m_tool;

		private EnemyScanner m_scanner;

		private ulong OwnerLookup;

		private PlayerAgent m_owner;

		private pMapperTrackerXRayData m_mapperTrackerXRayDataSynced;

		private pMapperTrackerXRayStatus m_mapperTrackerXRayStatusSynced;

		public static KeyCode ToggleKey = (KeyCode)120;

		private XRays m_xRays;

		private bool m_isValid;

		private bool m_statusNeedSync;

		private bool m_statusNeedUpdate;

		private bool m_statusFocusChanged;

		private bool m_wasShortCircuited;

		public const float MaxFieldOfViewNormal = 84f;

		internal EnemyScanner Scanner => m_scanner;

		internal ulong OwnerLookupPublic => OwnerLookup;

		internal bool WasShortCircuited
		{
			get
			{
				return m_wasShortCircuited;
			}
			set
			{
				m_wasShortCircuited = value;
			}
		}

		internal bool AllowDotsBlinkFrame { get; set; }

		public bool IsWielded
		{
			get
			{
				if ((Object)(object)m_tool != (Object)null)
				{
					return m_tool.m_isWielded;
				}
				return false;
			}
		}

		public bool IsLocalFireButtonHold => Input.GetKey((KeyCode)324);

		public bool IsSyncEnabled => m_mapperTrackerXRayStatusSynced.enabled;

		public bool IsSyncFocused => m_mapperTrackerXRayStatusSynced.focus;

		private bool IsXRayEnabled
		{
			get
			{
				if ((Object)(object)m_xRays != (Object)null)
				{
					return ((Component)m_xRays).gameObject.active;
				}
				return false;
			}
		}

		public bool IsShortCircuited
		{
			get
			{
				if (IsLocallyOwned)
				{
					return BatterySystem.IsOffline(OwnerLookup);
				}
				return false;
			}
		}

		public void Setup(ItemEquippable itemEquippable, PlayerAgent owner)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			m_tool = itemEquippable;
			m_scanner = (EnemyScanner)(object)((itemEquippable is EnemyScanner) ? itemEquippable : null);
			if ((Object)(object)m_scanner == (Object)null)
			{
				m_scanner = ((Component)itemEquippable).GetComponent<EnemyScanner>();
			}
			m_xRays = ((Component)m_tool).GetComponentInChildren<XRays>(true);
			ToggleKey = Hikaria.MapperTracker.Features.MapperTracker.Settings.ToggleKey;
			m_owner = owner;
			m_isValid = (Object)(object)m_xRays != (Object)null && (Object)(object)m_owner != (Object)null && (Object)(object)m_owner.Owner != (Object)null;
			if (m_isValid)
			{
				IsLocallyOwned = m_owner.Owner.IsLocal;
				OwnerLookup = m_owner.Owner.Lookup;
				m_mapperTrackerXRayStatusSynced = new pMapperTrackerXRayStatus(m_owner.Owner);
				m_mapperTrackerXRayDataSynced = new pMapperTrackerXRayData(m_owner.Owner)
				{
					fieldOfView = ClampFovNormal(Hikaria.MapperTracker.Features.MapperTracker.Settings.FieldOfView),
					fieldOfViewFocused = Hikaria.MapperTracker.Features.MapperTracker.Settings.FieldOfViewFocused,
					maxDistanceDefault = Hikaria.MapperTracker.Features.MapperTracker.Settings.MaxDistanceDefault,
					maxDistanceFocused = Hikaria.MapperTracker.Features.MapperTracker.Settings.MaxDistanceFocused,
					raysPerSecondDefault = Hikaria.MapperTracker.Features.MapperTracker.Settings.RaysPerSecondDefault,
					raysPerSecondFocused = Hikaria.MapperTracker.Features.MapperTracker.Settings.RaysPerSecondFocused
				};
				SetupXRays();
				MapperTrackerManager.RegisterController(this, m_scanner, m_xRays);
			}
		}

		public void SetupXRays()
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			((Component)m_xRays).gameObject.SetActive(false);
			m_xRays.fieldOfView = ClampFovNormal(Hikaria.MapperTracker.Features.MapperTracker.Settings.FieldOfView);
			m_xRays.fieldOfViewFocused = Hikaria.MapperTracker.Features.MapperTracker.Settings.FieldOfViewFocused;
			m_xRays.maxDistance = Hikaria.MapperTracker.Features.MapperTracker.Settings.MaxDistanceDefault;
			m_xRays.raysPerSecond = Hikaria.MapperTracker.Features.MapperTracker.Settings.RaysPerSecondDefault;
			ApplyTerrainColor();
			m_xRays.defaultSize = Hikaria.MapperTracker.Features.MapperTracker.Settings.DefaultSize;
			m_xRays.enemyColor = SColorExtensions.ToUnityColor(Hikaria.MapperTracker.Features.MapperTracker.Settings.EnemyColor);
			m_xRays.enemySize = Hikaria.MapperTracker.Features.MapperTracker.Settings.EnemySize;
			m_xRays.interactionColor = SColorExtensions.ToUnityColor(Hikaria.MapperTracker.Features.MapperTracker.Settings.InteractionColor);
			m_xRays.interactionSize = Hikaria.MapperTracker.Features.MapperTracker.Settings.InteractionSize;
			m_xRays.forwardStepSize = 2.5f;
			if ((Object)(object)m_xRays.m_renderer == (Object)null)
			{
				m_xRays.m_renderer = ((Component)m_xRays).gameObject.GetComponent<XRayRenderer>();
			}
		}

		private void ApplyTerrainColor()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!((Object)(object)m_xRays == (Object)null) && Hikaria.MapperTracker.Features.MapperTracker.Settings != null)
			{
				m_xRays.defaultColor = (IsLocallyOwned ? SColorExtensions.ToUnityColor(Hikaria.MapperTracker.Features.MapperTracker.Settings.DefaultColor) : SColorExtensions.ToUnityColor(Hikaria.MapperTracker.Features.MapperTracker.Settings.OtherPlayersTerrainColor));
			}
		}

		private static float ClampFovNormal(float fov)
		{
			return Mathf.Clamp(fov, 1f, 84f);
		}

		public void UpdateXRaysStatus()
		{
			bool active = m_mapperTrackerXRayStatusSynced.enabled && !IsShortCircuited;
			((Component)m_xRays).gameObject.SetActive(active);
			m_xRays.fieldOfView = (IsSyncFocused ? m_mapperTrackerXRayDataSynced.fieldOfViewFocused : ClampFovNormal(m_mapperTrackerXRayDataSynced.fieldOfView));
			m_xRays.maxDistance = (IsSyncFocused ? m_mapperTrackerXRayDataSynced.maxDistanceFocused : m_mapperTrackerXRayDataSynced.maxDistanceDefault);
			m_xRays.raysPerSecond = (IsSyncFocused ? m_mapperTrackerXRayDataSynced.raysPerSecondFocused : m_mapperTrackerXRayDataSynced.raysPerSecondDefault);
			ApplyTerrainColor();
			m_statusNeedUpdate = false;
		}

		public void UpdateXRaysData()
		{
			m_xRays.fieldOfView = (IsSyncFocused ? m_mapperTrackerXRayDataSynced.fieldOfViewFocused : m_mapperTrackerXRayDataSynced.fieldOfView);
			m_xRays.fieldOfViewFocused = m_mapperTrackerXRayDataSynced.fieldOfViewFocused;
			m_xRays.maxDistance = (IsSyncFocused ? m_mapperTrackerXRayDataSynced.maxDistanceFocused : m_mapperTrackerXRayDataSynced.maxDistanceDefault);
			m_xRays.raysPerSecond = (IsSyncFocused ? m_mapperTrackerXRayDataSynced.raysPerSecondFocused : m_mapperTrackerXRayDataSynced.raysPerSecondDefault);
		}

		private void OnDestroy()
		{
			if ((Object)(object)m_scanner != (Object)null)
			{
				BatteryScreenUI.DestroyFor(m_scanner);
			}
			MapperTrackerManager.UnregisterController(this, m_scanner, m_xRays);
		}

		public void OnWield()
		{
			if (m_isValid)
			{
				SetupXRays();
				((Behaviour)this).enabled = true;
				WasShortCircuited = BatterySystem.IsOffline(OwnerLookup);
				MapperTrackerManager.RegisterController(this, m_scanner, m_xRays);
				if (IsLocallyOwned)
				{
					SendMapperTrackerXRayStatus(enable: false, focus: false);
					SendMapperTrackerXRayData(ClampFovNormal(Hikaria.MapperTracker.Features.MapperTracker.Settings.FieldOfView), Hikaria.MapperTracker.Features.MapperTracker.Settings.FieldOfViewFocused, Hikaria.MapperTracker.Features.MapperTracker.Settings.MaxDistanceDefault, Hikaria.MapperTracker.Features.MapperTracker.Settings.MaxDistanceFocused, Hikaria.MapperTracker.Features.MapperTracker.Settings.RaysPerSecondDefault, Hikaria.MapperTracker.Features.MapperTracker.Settings.RaysPerSecondFocused);
				}
			}
		}

		public void OnUnWield()
		{
			if (m_isValid)
			{
				ForceMapperOff(sync: true);
			}
		}

		public void ForceMapperOff(bool sync)
		{
			if ((Object)(object)m_xRays != (Object)null)
			{
				((Component)m_xRays).gameObject.SetActive(false);
			}
			bool num = m_mapperTrackerXRayStatusSynced.enabled || m_mapperTrackerXRayStatusSynced.focus;
			m_mapperTrackerXRayStatusSynced.enabled = false;
			m_mapperTrackerXRayStatusSynced.focus = false;
			if (num)
			{
				m_statusNeedUpdate = true;
				m_statusFocusChanged = true;
				TryClearXRays();
			}
			if (sync && IsLocallyOwned)
			{
				SendMapperTrackerXRayStatus(enable: false, focus: false);
			}
		}

		private void Update()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (!m_isValid || !IsLocallyOwned || !Hikaria.MapperTracker.Features.MapperTracker.Settings.EnableMapperTracker || !IsWielded)
			{
				return;
			}
			if (IsShortCircuited)
			{
				if (m_mapperTrackerXRayStatusSynced.enabled || m_mapperTrackerXRayStatusSynced.focus)
				{
					ForceMapperOff(sync: true);
				}
				return;
			}
			if (IsSyncFocused != IsLocalFireButtonHold)
			{
				m_mapperTrackerXRayStatusSynced.focus = !m_mapperTrackerXRayStatusSynced.focus;
				m_statusNeedUpdate = true;
				m_statusNeedSync = true;
				m_statusFocusChanged = true;
			}
			if (Input.GetKeyDown(ToggleKey) && (m_mapperTrackerXRayStatusSynced.enabled || !BatterySystem.IsOffline(OwnerLookup)))
			{
				m_mapperTrackerXRayStatusSynced.enabled = !m_mapperTrackerXRayStatusSynced.enabled;
				m_statusNeedUpdate = true;
				m_statusNeedSync = true;
			}
		}

		private void LateUpdate()
		{
			if (m_isValid && IsWielded && IsLocallyOwned && Hikaria.MapperTracker.Features.MapperTracker.Settings.EnableMapperTracker && Hikaria.MapperTracker.Features.MapperTracker.Settings.EnableBattery && !((Object)(object)m_scanner == (Object)null))
			{
				BatteryScreenUI.Update(m_scanner, BatterySystem.Get(OwnerLookup));
			}
		}

		public static void TickLocalBatteryFromFeature()
		{
			if (!Hikaria.MapperTracker.Features.MapperTracker.Settings.EnableBattery)
			{
				return;
			}
			SNet_Player localPlayer = SNet.LocalPlayer;
			if ((Object)(object)localPlayer == (Object)null || !localPlayer.IsInSlot)
			{
				return;
			}
			ulong lookup = localPlayer.Lookup;
			bool mapperActive = false;
			MapperTrackerController value = null;
			if (MapperTrackerManager.MapperTrackerControllerLookup.TryGetValue(lookup, out value) && (Object)(object)value != (Object)null)
			{
				mapperActive = value.IsWielded && value.IsSyncEnabled;
			}
			float drainPerSecond = 100f / Mathf.Max(1f, Hikaria.MapperTracker.Features.MapperTracker.Settings.BatteryDurationSeconds);
			BatterySystem.Tick(lookup, mapperActive, drainPerSecond, Hikaria.MapperTracker.Features.MapperTracker.Settings.BatteryRechargePercentPerSecond, Hikaria.MapperTracker.Features.MapperTracker.Settings.GlitchDurationSeconds, Time.deltaTime, out var state, out var justWentOffline);
			if (justWentOffline && (Object)(object)value != (Object)null)
			{
				value.ForceMapperOff(sync: true);
			}
			if ((Object)(object)value != (Object)null)
			{
				if (value.WasShortCircuited && !state.IsOffline && (Object)(object)value.Scanner != (Object)null)
				{
					BatteryScreenUI.ClearShortCircuitVisual(value.Scanner);
				}
				else if (!value.WasShortCircuited && state.IsOffline && state.GlitchRemaining > 0f && (Object)(object)value.Scanner != (Object)null)
				{
					BatteryScreenUI.Update(value.Scanner, state);
				}
				value.WasShortCircuited = state.IsOffline;
			}
		}

		private void FixedUpdate()
		{
			if (m_isValid)
			{
				if (m_statusFocusChanged)
				{
					TryClearXRays();
					m_statusFocusChanged = false;
				}
				if (m_statusNeedUpdate)
				{
					UpdateXRaysStatus();
				}
				if (Hikaria.MapperTracker.Features.MapperTracker.Settings.EnableMapperTracker && IsLocallyOwned && m_statusNeedSync)
				{
					m_statusNeedSync = false;
					SendMapperTrackerXRayStatus(IsXRayEnabled && !IsShortCircuited, IsLocalFireButtonHold && !IsShortCircuited);
				}
			}
		}

		private void OnDisable()
		{
			SharedUtils.SafeDestroy((Component)(object)this);
		}

		private void TryClearXRays()
		{
			XRays xRays = m_xRays;
			if ((Object)(object)((xRays != null) ? xRays.m_renderer : null) != (Object)null)
			{
				m_xRays.m_renderer.DeallocateResources();
			}
		}

		public void SendMapperTrackerXRayStatus(bool enable, bool focus)
		{
			m_mapperTrackerXRayStatusSynced.enabled = enable;
			m_mapperTrackerXRayStatusSynced.focus = focus;
			MapperTrackerManager.s_MapperTrackerXRayStatusAction.Do(m_mapperTrackerXRayStatusSynced);
		}

		public void SendMapperTrackerXRayData(float fov, float fovFocused, float maxDistanceDefault, float maxDistanceFocused, int raysPerSecondDefault, int raysPerSecondFocused)
		{
			m_mapperTrackerXRayDataSynced.fieldOfView = ClampFovNormal(fov);
			m_mapperTrackerXRayDataSynced.fieldOfViewFocused = fovFocused;
			m_mapperTrackerXRayDataSynced.maxDistanceDefault = maxDistanceDefault;
			m_mapperTrackerXRayDataSynced.maxDistanceFocused = maxDistanceFocused;
			m_mapperTrackerXRayDataSynced.raysPerSecondDefault = raysPerSecondDefault;
			m_mapperTrackerXRayDataSynced.raysPerSecondFocused = raysPerSecondFocused;
			MapperTrackerManager.s_MapperTrackerXRayDataAction.Do(m_mapperTrackerXRayDataSynced);
		}

		public void SyncSetXRayStatus(pMapperTrackerXRayStatus data)
		{
			((Component)((Component)this).transform.parent).gameObject.SetActive(true);
			m_statusFocusChanged = m_mapperTrackerXRayStatusSynced.focus != data.focus;
			m_mapperTrackerXRayStatusSynced = data;
			m_statusNeedUpdate = true;
		}

		public void SyncSetXRayData(pMapperTrackerXRayData data)
		{
			m_mapperTrackerXRayDataSynced = data;
			UpdateXRaysData();
		}
	}
}