Decompiled source of Enemy Indicators v1.0.0

EnemyIndicators.dll

Decompiled 5 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("NoteBoxz")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EnemyIndicators")]
[assembly: AssemblyTitle("EnemyIndicators")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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 EnemyIndicators
{
	[BepInPlugin("NoteBoxz.EnemyIndicators", "EnemyIndicators", "1.0.0")]
	public class EnemyIndicators : BaseUnityPlugin
	{
		public IndicatorUI UIInstance = null;

		public GameObject indicatorSlotPrefab = null;

		public GameObject IndicatorHolderPrefab = null;

		public Sprite ClockSprite = null;

		public Sprite SkullSprite = null;

		public Sprite ActiveSprite = null;

		public Sprite ZzzSprite = null;

		internal static EnemyIndicators Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		internal static AssetBundle assetBundle { get; private set; }

		public ConfigEntry<bool> ShowRespawnTimers { get; private set; } = null;


		private void Awake()
		{
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			Patch();
			LoadAssetBundle();
			PreInitAssets();
			BindConfigs();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		private void PreInitAssets()
		{
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			IndicatorHolderPrefab = assetBundle.LoadAsset<GameObject>("Assets/EnemyIdicatorAssets/InidcatorContainer.prefab");
			indicatorSlotPrefab = assetBundle.LoadAsset<GameObject>("Assets/EnemyIdicatorAssets/IndicatorSlot.prefab");
			ClockSprite = assetBundle.LoadAsset<Sprite>("Assets/EnemyIdicatorAssets/clock.png");
			SkullSprite = assetBundle.LoadAsset<Sprite>("Assets/EnemyIdicatorAssets/skull.png");
			ActiveSprite = assetBundle.LoadAsset<Sprite>("Assets/EnemyIdicatorAssets/active.png");
			ZzzSprite = assetBundle.LoadAsset<Sprite>("Assets/EnemyIdicatorAssets/zzz.png");
			IndicatorUI indicatorUI = IndicatorHolderPrefab.GetComponent<IndicatorUI>();
			if ((Object)(object)IndicatorHolderPrefab.GetComponent<IndicatorUI>() == (Object)null)
			{
				Logger.LogInfo((object)"Adding IndicatorUI component to IndicatorHolderPrefab.");
				indicatorUI = IndicatorHolderPrefab.AddComponent<IndicatorUI>();
			}
			((SemiUI)indicatorUI).showPosition = new Vector2(270f, 0f);
			((SemiUI)indicatorUI).hidePosition = new Vector2(900f, 0f);
			if ((Object)(object)indicatorSlotPrefab.GetComponent<indicatorSlot>() == (Object)null)
			{
				Logger.LogInfo((object)"Adding indicatorSlot component to indicatorSlotPrefab.");
				indicatorSlotPrefab.AddComponent<indicatorSlot>();
			}
		}

		internal static void LoadAssetBundle()
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (directoryName == null)
			{
				throw new InvalidOperationException("Unable to determine assembly location.");
			}
			string text = Path.Combine(directoryName, "enemyindicatorassets");
			assetBundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)assetBundle == (Object)null)
			{
				throw new InvalidOperationException("Failed to load AssetBundle.");
			}
		}

		private void BindConfigs()
		{
			ShowRespawnTimers = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Show Respawn Timers", true, "Show respawn timers for enemies.");
		}

		internal void Patch()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0026: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val2 = val;
				Harmony = val;
			}
			Harmony.PatchAll();
		}

		internal void Unpatch()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void Update()
		{
		}
	}
	[HarmonyPatch(typeof(EnemyParent))]
	internal static class EnemyParentPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("Awake")]
		private static void Awake_Prefix(EnemyParent __instance)
		{
			try
			{
				IndicatorUI.Instance.AddEnemyToIndicator(__instance);
			}
			catch (Exception arg)
			{
				EnemyIndicators.Logger.LogError((object)$"Error in EnemyParentPatch.Awake_Prefix: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(HUD))]
	internal static class HUDPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("Awake")]
		private static void Awake_Prefix(HUD __instance)
		{
			try
			{
				EnemyIndicators.Logger.LogInfo((object)"HUD Awake Prefix called, initializing Enemy Indicators UI...");
				if ((Object)(object)EnemyIndicators.Instance.UIInstance == (Object)null)
				{
					EnemyIndicators.Logger.LogInfo((object)"Instantiating IndicatorUI and assigning it to EnemyIndicators.Instance.UIInstance.");
					EnemyIndicators.Instance.UIInstance = Object.Instantiate<GameObject>(EnemyIndicators.Instance.IndicatorHolderPrefab, ((Component)((Component)__instance).transform).transform.Find("HUD Canvas/HUD/Game Hud")).GetComponent<IndicatorUI>();
				}
			}
			catch (Exception arg)
			{
				EnemyIndicators.Logger.LogError((object)$"Error in HUDPatch.Start_Prefix: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(RoundDirector))]
	internal static class RoundDirectorPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("Start")]
		private static void Start_Prefix(RoundDirector __instance)
		{
			try
			{
				IndicatorUI.Instance.ClearAllSlots();
			}
			catch (Exception arg)
			{
				EnemyIndicators.Logger.LogError((object)$"Error in RoundDirectorPatch.Start_Prefix: {arg}");
			}
		}
	}
	public class indicatorSlot : MonoBehaviour
	{
		public EnemyParent enemyParent = null;

		public TMP_Text NameText = null;

		public TMP_Text TimerText = null;

		public Image StatusImage = null;

		public InidcatorStatus status = InidcatorStatus.Active;

		private void Awake()
		{
			TMP_Text[] componentsInChildren = ((Component)this).GetComponentsInChildren<TMP_Text>();
			foreach (TMP_Text val in componentsInChildren)
			{
				if (((Object)val).name == "Text (TMP)")
				{
					NameText = val;
				}
				else if (((Object)val).name == "Text (TMP) (1)")
				{
					TimerText = val;
				}
			}
			StatusImage = ((Component)this).GetComponentInChildren<Image>();
		}

		private void Update()
		{
			if ((Object)(object)enemyParent == (Object)null)
			{
				EnemyIndicators.Logger.LogWarning((object)"EnemyParent is null in indicatorSlot.Update, removing this slot.");
				IndicatorUI.Instance.indicatorSlots.Remove(this);
				if ((Object)(object)((Component)this).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)this).gameObject);
				}
			}
			else
			{
				UpdateStatus();
				UpdateVisuals();
				UpdateTimer();
			}
		}

		private void UpdateStatus()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Invalid comparison between Unknown and I4
			if (enemyParent.Enemy.HasHealth && enemyParent.Enemy.Health.dead)
			{
				status = InidcatorStatus.Dead;
				return;
			}
			if (EnemyDirector.instance.spawnIdlePauseTimer > 0f)
			{
				status = InidcatorStatus.Waiting;
				return;
			}
			EnemyState currentState = enemyParent.Enemy.CurrentState;
			EnemyState val = currentState;
			if ((int)val == 11)
			{
				status = InidcatorStatus.Dipped;
			}
			else
			{
				status = InidcatorStatus.Active;
			}
		}

		private void UpdateVisuals()
		{
			NameText.text = enemyParent.enemyName;
			switch (status)
			{
			case InidcatorStatus.Active:
				StatusImage.sprite = EnemyIndicators.Instance.ActiveSprite;
				break;
			case InidcatorStatus.Waiting:
				StatusImage.sprite = EnemyIndicators.Instance.ClockSprite;
				break;
			case InidcatorStatus.Dipped:
				StatusImage.sprite = EnemyIndicators.Instance.ZzzSprite;
				break;
			case InidcatorStatus.Dead:
				StatusImage.sprite = EnemyIndicators.Instance.SkullSprite;
				break;
			}
		}

		private void UpdateTimer()
		{
			if (!EnemyIndicators.Instance.ShowRespawnTimers.Value)
			{
				((Component)TimerText).gameObject.SetActive(false);
				return;
			}
			switch (status)
			{
			case InidcatorStatus.Waiting:
				((Component)TimerText).gameObject.SetActive(true);
				TimerText.text = TimeSpan.FromSeconds(EnemyDirector.instance.spawnIdlePauseTimer).ToString("mm\\:ss");
				break;
			case InidcatorStatus.Dipped:
			case InidcatorStatus.Dead:
				((Component)TimerText).gameObject.SetActive(true);
				TimerText.text = TimeSpan.FromSeconds(enemyParent.DespawnedTimer).ToString("mm\\:ss");
				break;
			default:
				((Component)TimerText).gameObject.SetActive(false);
				break;
			}
		}
	}
	public enum InidcatorStatus
	{
		Active,
		Waiting,
		Dipped,
		Dead
	}
	public class IndicatorUI : SemiUI
	{
		public List<indicatorSlot> indicatorSlots = new List<indicatorSlot>();

		public static IndicatorUI Instance { get; private set; }

		private MapToolController Map => PlayerAvatar.instance.mapToolController;

		private void Awake()
		{
			Instance = this;
		}

		public override void Start()
		{
			((SemiUI)this).Start();
			((SemiUI)this).Hide();
		}

		public override void Update()
		{
			((SemiUI)this).Update();
			if (!((Object)(object)Map == (Object)null))
			{
				if (Map.Active)
				{
					((SemiUI)this).Show();
				}
				else
				{
					((SemiUI)this).Hide();
				}
			}
		}

		public void AddEnemyToIndicator(EnemyParent enemyParent)
		{
			GameObject val = Object.Instantiate<GameObject>(EnemyIndicators.Instance.indicatorSlotPrefab, ((Component)this).transform);
			indicatorSlot component = val.GetComponent<indicatorSlot>();
			component.enemyParent = enemyParent;
			indicatorSlots.Add(component);
			base.allChildren.Add(((Component)component).gameObject);
			EnemyIndicators.Logger.LogInfo((object)$"Added enemy {enemyParent.enemyName} to indicator slots. Total slots: {indicatorSlots.Count}");
		}

		public void RemoveEnemyFromIndicator(EnemyParent enemyParent)
		{
			EnemyParent enemyParent2 = enemyParent;
			indicatorSlot indicatorSlot2 = indicatorSlots.Find((indicatorSlot slot) => (Object)(object)slot.enemyParent == (Object)(object)enemyParent2);
			if ((Object)(object)indicatorSlot2 != (Object)null)
			{
				if ((Object)(object)((Component)indicatorSlot2).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)indicatorSlot2).gameObject);
				}
				indicatorSlots.Remove(indicatorSlot2);
				base.allChildren.Remove(((Component)indicatorSlot2).gameObject);
				EnemyIndicators.Logger.LogInfo((object)$"Removed enemy {enemyParent2.enemyName} from indicator slots. Remaining slots: {indicatorSlots.Count}");
			}
			else
			{
				EnemyIndicators.Logger.LogWarning((object)("Tried to remove enemy " + enemyParent2.enemyName + " from indicators, but it was not found."));
			}
		}

		public void ClearAllSlots()
		{
			foreach (indicatorSlot indicatorSlot in indicatorSlots)
			{
				if ((Object)(object)indicatorSlot != (Object)null && (Object)(object)((Component)indicatorSlot).gameObject != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)indicatorSlot).gameObject);
				}
			}
			indicatorSlots.Clear();
			base.allChildren.Clear();
			EnemyIndicators.Logger.LogInfo((object)"Cleared all indicator slots.");
		}
	}
}