Decompiled source of MonsterCompass v1.1.1

BepInEx/plugins/MonsterCompass/MonsterCompass.dll

Decompiled 5 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[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("RepoModDev")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("MonsterCompass")]
[assembly: AssemblyTitle("MonsterCompass")]
[assembly: AssemblyVersion("1.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 MonsterCompass
{
	internal static class BearingMath
	{
		internal static (float X, float Y) Edge(float right, float forward, float halfWidth, float halfHeight)
		{
			if (Math.Abs(right) + Math.Abs(forward) < 0.0001f)
			{
				return (X: 0f, Y: 0f - halfHeight);
			}
			float num = Math.Max(Math.Abs(right) / halfWidth, Math.Abs(forward) / halfHeight);
			return (X: right / num, Y: (0f - forward) / num);
		}

		internal static float Fade(float age, float duration)
		{
			if (age < 0f || age >= duration)
			{
				return 0f;
			}
			float num = Math.Min(0.35f, duration * 0.2f);
			float num2 = Math.Min(1.5f, duration * 0.4f);
			return Math.Min(1f, Math.Min(age / num, (duration - age) / num2));
		}
	}
	[BepInPlugin("RepoModDev.MonsterCompass", "Monster Compass", "1.1.0")]
	[BepInProcess("REPO.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class Cue
		{
			internal readonly Enemy Enemy;

			internal readonly float SpawnTime;

			internal float VisibleAge;

			internal Cue(Enemy enemy)
			{
				Enemy = enemy;
				SpawnTime = Time.unscaledTime;
			}
		}

		private readonly struct DrawCue
		{
			internal readonly Vector2 Position;

			internal readonly float Angle;

			internal readonly float Alpha;

			internal DrawCue(Vector2 position, float angle, float alpha)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				Position = position;
				Angle = angle;
				Alpha = alpha;
			}
		}

		public const string PluginId = "RepoModDev.MonsterCompass";

		public const string Version = "1.1.0";

		internal static Plugin? Instance;

		private Harmony? harmony;

		private readonly List<Cue> cues = new List<Cue>();

		private readonly List<DrawCue> draws = new List<DrawCue>();

		private readonly SpawnTracker spawnTracker = new SpawnTracker();

		private static readonly FieldInfo ParentEnemy = AccessTools.Field(typeof(EnemyParent), "Enemy");

		private static readonly FieldInfo ParentSpawned = AccessTools.Field(typeof(EnemyParent), "Spawned");

		private static readonly FieldInfo ParentSetupDone = AccessTools.Field(typeof(EnemyParent), "SetupDone");

		private float nextReconcile;

		private float statusUntil;

		private GUIStyle? statusStyle;

		private ConfigEntry<bool> enabledSetting;

		private ConfigEntry<bool> continuous;

		private ConfigEntry<float> duration;

		private ConfigEntry<float> opacity;

		private ConfigEntry<float> size;

		private ConfigEntry<float> margin;

		private ConfigEntry<float> maxDistance;

		private ConfigEntry<float> nearDistance;

		private ConfigEntry<float> farDistance;

		private ConfigEntry<Color> color;

		private ConfigEntry<KeyboardShortcut> toggle;

		private string lastStatus = "";

		private Texture2D? glow;

		private Texture2D? arrow;

		private void Awake()
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Expected O, but got Unknown
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Expected O, but got Unknown
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected O, but got Unknown
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Expected O, but got Unknown
			((Component)this).transform.SetParent((Transform)null);
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			Instance = this;
			enabledSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable direction hints. Re-enabling discovers monsters already spawned. Toggle with F7.");
			continuous = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ContinuousTracking", true, "Legacy compatibility setting. Monster hints now remain active while the monster is active.");
			duration = ((BaseUnityPlugin)this).Config.Bind<float>("Hints", "Duration", 8f, "Legacy setting retained for config compatibility; cues now remain while the monster is active.");
			opacity = ((BaseUnityPlugin)this).Config.Bind<float>("Hints", "Opacity", 0.45f, new ConfigDescription("Maximum hint opacity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			size = ((BaseUnityPlugin)this).Config.Bind<float>("Hints", "Size", 38f, new ConfigDescription("Hint size at 1080p; scales with screen height.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(16f, 100f), Array.Empty<object>()));
			margin = ((BaseUnityPlugin)this).Config.Bind<float>("Hints", "EdgeMargin", 24f, new ConfigDescription("Edge inset at 1080p.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 150f), Array.Empty<object>()));
			maxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Hints", "MaxDistance", 0f, new ConfigDescription("Maximum 3D distance in metres; 0 means unlimited.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), Array.Empty<object>()));
			nearDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Hints", "NearDistance", 5f, new ConfigDescription("Distance at which the hint reaches maximum intensity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
			farDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Hints", "FarDistance", 35f, new ConfigDescription("Distance at which the hint is least intense.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 200f), Array.Empty<object>()));
			color = ((BaseUnityPlugin)this).Config.Bind<Color>("Hints", "Color", new Color(1f, 0.42f, 0.23f, 1f), "Hint tint. Opacity also multiplies the color alpha.");
			toggle = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Toggle hints without opening a menu.");
			glow = MakeTexture(chevron: false);
			arrow = MakeTexture(chevron: true);
			SceneManager.activeSceneChanged += SceneChanged;
			harmony = new Harmony("RepoModDev.MonsterCompass");
			harmony.PatchAll(typeof(Plugin).Assembly);
			enabledSetting.SettingChanged += EnabledChanged;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Monster Compass 1.1.0 loaded. F7 toggles hints.");
		}

		internal void ObserveEnemy(Enemy enemy, bool spawned, string source)
		{
			if (!enabledSetting.Value || !Object.op_Implicit((Object)(object)enemy))
			{
				return;
			}
			bool flag = spawnTracker.Observe(((Object)enemy).GetInstanceID(), spawned);
			if (!spawned)
			{
				for (int num = cues.Count - 1; num >= 0; num--)
				{
					if ((Object)(object)cues[num].Enemy == (Object)(object)enemy)
					{
						cues.RemoveAt(num);
					}
				}
			}
			else
			{
				if (!flag)
				{
					return;
				}
				for (int num2 = cues.Count - 1; num2 >= 0; num2--)
				{
					if (!Object.op_Implicit((Object)(object)cues[num2].Enemy) || (Object)(object)cues[num2].Enemy == (Object)(object)enemy)
					{
						cues.RemoveAt(num2);
					}
				}
				if (cues.Count >= 64)
				{
					cues.RemoveAt(0);
				}
				cues.Add(new Cue(enemy));
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Spawn cue queued ({source}): {((Object)enemy).name}; pending={cues.Count}");
			}
		}

		private void EnabledChanged(object sender, EventArgs args)
		{
			cues.Clear();
			draws.Clear();
			spawnTracker.Clear();
			nextReconcile = 0f;
			statusUntil = Time.unscaledTime + 3f;
			lastStatus = "";
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Monster Compass enabled: {enabledSetting.Value}");
		}

		private void ReconcileEnemies()
		{
			if (!Object.op_Implicit((Object)(object)EnemyDirector.instance) || EnemyDirector.instance.enemiesSpawned == null)
			{
				return;
			}
			foreach (EnemyParent item in EnemyDirector.instance.enemiesSpawned)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					object? value = ParentEnemy.GetValue(item);
					Enemy val = (Enemy)((value is Enemy) ? value : null);
					if (val != null && Object.op_Implicit((Object)(object)val))
					{
						bool spawned = (bool)ParentSetupDone.GetValue(item) && (bool)ParentSpawned.GetValue(item) && ((Component)val).gameObject.activeInHierarchy;
						ObserveEnemy(val, spawned, "registry");
					}
				}
			}
		}

		private void Update()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = toggle.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				enabledSetting.Value = !enabledSetting.Value;
			}
			if (enabledSetting.Value && Time.unscaledTime >= nextReconcile)
			{
				nextReconcile = Time.unscaledTime + 0.25f;
				ReconcileEnemies();
			}
		}

		private void LateUpdate()
		{
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Invalid comparison between Unknown and I4
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: 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_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: 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_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			draws.Clear();
			if (!enabledSetting.Value)
			{
				cues.Clear();
				return;
			}
			float unscaledTime = Time.unscaledTime;
			for (int num = cues.Count - 1; num >= 0; num--)
			{
				Cue cue = cues[num];
				if (!Object.op_Implicit((Object)(object)cue.Enemy) || !((Component)cue.Enemy).gameObject.activeInHierarchy)
				{
					cues.RemoveAt(num);
				}
			}
			if (cues.Count == 0)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)GameDirector.instance) || !Object.op_Implicit((Object)(object)PlayerAvatar.instance) || !Object.op_Implicit((Object)(object)RunManager.instance))
			{
				Status("Waiting for local player/game initialization");
				return;
			}
			if (SemiFunc.MenuLevel() || (int)GameDirector.instance.currentState != 2)
			{
				Status($"Waiting for gameplay: {GameDirector.instance.currentState}");
				return;
			}
			if (GameDirector.instance.DisableInput || SemiFunc.IsSpectating())
			{
				Status("Hidden: input disabled or spectating");
				return;
			}
			Camera val = SemiFunc.MainCamera();
			if (!Object.op_Implicit((Object)(object)val) || !((Component)val).gameObject.activeInHierarchy)
			{
				Status("Waiting for camera");
				return;
			}
			Status("Rendering spawn cues");
			Vector3 val2 = Vector3.ProjectOnPlane(((Component)val).transform.forward, Vector3.up);
			if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
			{
				val2 = Vector3.Cross(((Component)val).transform.right, Vector3.up);
			}
			((Vector3)(ref val2)).Normalize();
			Vector3 val3 = Vector3.Cross(Vector3.up, val2);
			Vector3 normalized = ((Vector3)(ref val3)).normalized;
			float num2 = Mathf.Clamp((float)Screen.height / 1080f, 0.5f, 3f);
			float num3 = (margin.Value + size.Value * 0.5f) * num2;
			float halfWidth = Mathf.Max(1f, (float)Screen.width * 0.5f - num3);
			float halfHeight = Mathf.Max(1f, (float)Screen.height * 0.5f - num3);
			Vector2 position = default(Vector2);
			foreach (Cue cue2 in cues)
			{
				cue2.VisibleAge += Time.unscaledDeltaTime;
				float visibleAge = cue2.VisibleAge;
				if (unscaledTime - cue2.SpawnTime < 0.15f)
				{
					continue;
				}
				Vector3 val4 = ((Component)cue2.Enemy).transform.position - ((Component)val).transform.position;
				if (!(maxDistance.Value > 0f) || !(((Vector3)(ref val4)).sqrMagnitude > maxDistance.Value * maxDistance.Value))
				{
					Vector3 val5 = Vector3.ProjectOnPlane(val4, Vector3.up);
					if (!(((Vector3)(ref val5)).sqrMagnitude < 0.0001f))
					{
						float num4 = Vector3.Dot(val5, normalized);
						float num5 = Vector3.Dot(val5, val2);
						(float, float) tuple = BearingMath.Edge(num4, num5, halfWidth, halfHeight);
						((Vector2)(ref position))..ctor((float)Screen.width * 0.5f + tuple.Item1, (float)Screen.height * 0.5f + tuple.Item2);
						float magnitude = ((Vector3)(ref val5)).magnitude;
						float num6 = Mathf.InverseLerp(farDistance.Value, nearDistance.Value, magnitude);
						float num7 = Mathf.Lerp(0.92f, 1f, num6) + Mathf.Lerp(0.02f, 0.18f, num6) * Mathf.Sin(visibleAge * Mathf.Lerp(2f, 8f, num6));
						float num8 = Mathf.Lerp(0.18f, 1f, num6);
						draws.Add(new DrawCue(position, Mathf.Atan2(num4, num5) * 57.29578f, Mathf.Clamp01(opacity.Value * num8 * num7)));
					}
				}
			}
		}

		private void Status(string message)
		{
			if (!(lastStatus == message))
			{
				lastStatus = message;
				((BaseUnityPlugin)this).Logger.LogInfo((object)message);
			}
		}

		private void OnGUI()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: 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_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			bool flag = Time.unscaledTime < statusUntil;
			if ((int)Event.current.type != 7 || (draws.Count == 0 && !flag) || !Object.op_Implicit((Object)(object)glow) || !Object.op_Implicit((Object)(object)arrow))
			{
				return;
			}
			Color val = GUI.color;
			Matrix4x4 matrix = GUI.matrix;
			int depth = GUI.depth;
			try
			{
				GUI.depth = -50;
				GUI.matrix = Matrix4x4.identity;
				if (flag)
				{
					if (statusStyle == null)
					{
						statusStyle = new GUIStyle(GUI.skin.box)
						{
							alignment = (TextAnchor)4,
							fontSize = 18
						};
					}
					GUI.color = Color.white;
					string arg = (enabledSetting.Value ? "ON" : "OFF");
					string text = $"Monster hints: {arg} ({toggle.Value})";
					GUI.Box(new Rect((float)Screen.width / 2f - 230f, 75f, 460f, 38f), text, statusStyle);
				}
				float num = size.Value * Mathf.Clamp((float)Screen.height / 1080f, 0.5f, 3f);
				Rect val2 = default(Rect);
				foreach (DrawCue draw in draws)
				{
					Color value = color.Value;
					value.a *= draw.Alpha;
					GUI.color = value;
					((Rect)(ref val2))..ctor(draw.Position.x - num / 2f, draw.Position.y - num / 2f, num, num);
					GUI.DrawTexture(val2, (Texture)(object)glow);
					GUIUtility.RotateAroundPivot(draw.Angle, draw.Position);
					GUI.DrawTexture(val2, (Texture)(object)arrow);
					GUI.matrix = Matrix4x4.identity;
				}
			}
			finally
			{
				GUI.color = val;
				GUI.matrix = matrix;
				GUI.depth = depth;
			}
		}

		private static Texture2D MakeTexture(bool chevron)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0028: 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_0037: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				name = (chevron ? "MonsterCompassArrow" : "MonsterCompassGlow"),
				hideFlags = (HideFlags)61,
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			Color[] array = (Color[])(object)new Color[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num = ((float)j + 0.5f) / 64f * 2f - 1f;
					float num2 = ((float)i + 0.5f) / 64f * 2f - 1f;
					float num4;
					if (chevron)
					{
						float num3 = Mathf.Abs(num2 - (0.48f - Mathf.Abs(num) * 0.9f));
						num4 = Mathf.Clamp01((0.1f - num3) * 32f) * Mathf.Clamp01((0.6f - Mathf.Abs(num)) * 32f);
					}
					else
					{
						num4 = Mathf.Pow(Mathf.Clamp01(1f - Mathf.Sqrt(num * num + num2 * num2)), 2f) * 0.65f;
					}
					array[i * 64 + j] = new Color(1f, 1f, 1f, num4);
				}
			}
			val.SetPixels(array);
			val.Apply(false, true);
			return val;
		}

		private void SceneChanged(Scene previous, Scene current)
		{
			cues.Clear();
			draws.Clear();
			spawnTracker.Clear();
			nextReconcile = 0f;
			lastStatus = "";
		}

		private void OnDestroy()
		{
			SceneManager.activeSceneChanged -= SceneChanged;
			enabledSetting.SettingChanged -= EnabledChanged;
			Harmony? obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			cues.Clear();
			draws.Clear();
			if (Object.op_Implicit((Object)(object)glow))
			{
				Object.Destroy((Object)(object)glow);
			}
			if (Object.op_Implicit((Object)(object)arrow))
			{
				Object.Destroy((Object)(object)arrow);
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}
	}
	[HarmonyPatch(typeof(EnemyParent), "SpawnRPC")]
	internal static class EnemySpawnPatch
	{
		[HarmonyPrefix]
		private static void Prefix(bool ___Spawned, out bool __state)
		{
			__state = ___Spawned;
		}

		[HarmonyPostfix]
		private static void Postfix(Enemy ___Enemy, bool ___Spawned, bool __state)
		{
			if (!__state && ___Spawned)
			{
				Plugin.Instance?.ObserveEnemy(___Enemy, spawned: true, "RPC");
			}
		}
	}
	[HarmonyPatch(typeof(EnemyParent), "DespawnRPC")]
	internal static class EnemyDespawnPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Enemy ___Enemy, bool ___Spawned)
		{
			if (!___Spawned)
			{
				Plugin.Instance?.ObserveEnemy(___Enemy, spawned: false, "RPC");
			}
		}
	}
	internal sealed class SpawnTracker
	{
		private readonly HashSet<int> active = new HashSet<int>();

		internal bool Observe(int id, bool spawned)
		{
			if (spawned)
			{
				return active.Add(id);
			}
			active.Remove(id);
			return false;
		}

		internal void Clear()
		{
			active.Clear();
		}
	}
}