Decompiled source of CGEnemyIcons v1.4.0

CGEnemyIcons.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using HarmonyLib;
using JadeLib;
using Microsoft.CodeAnalysis;
using PluginConfig.API;
using PluginConfig.API.Decorators;
using PluginConfig.API.Fields;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.UI;

[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("CGEnemyIcons")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: AssemblyInformationalVersion("1.4.0+5cfa43aa51ca277e4453e19f50710be2de2a899a")]
[assembly: AssemblyProduct("CGEnemyIcons")]
[assembly: AssemblyTitle("CGEnemyIcons")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace CGEnemyIcons
{
	internal enum EnemyCategory
	{
		Common,
		Uncommon,
		Special,
		Mass
	}
	internal readonly record struct IconInfo(EnemyIdentifier Enemy, EnemyCategory Type, bool IsRadiant, GameObject IconObject) : IComparable<IconInfo>
	{
		public bool Equals(IconInfo? other)
		{
			if (other.HasValue)
			{
				return (Object)(object)other.Value.Enemy == (Object)(object)Enemy;
			}
			return false;
		}

		public override int GetHashCode()
		{
			return ((Object)Enemy).GetInstanceID();
		}

		public int CompareTo(IconInfo other)
		{
			int num = Type.CompareTo(other.Type);
			if (num != 0)
			{
				return num;
			}
			int num2 = MonoSingleton<EnemyTracker>.Instance.GetEnemyRank(Enemy).CompareTo(MonoSingleton<EnemyTracker>.Instance.GetEnemyRank(other.Enemy));
			if (num2 != 0)
			{
				return num2;
			}
			int num3 = string.Compare(Enemy.FullName, other.Enemy.FullName, StringComparison.InvariantCultureIgnoreCase);
			if (num3 == 0)
			{
				return ((Object)Enemy).GetInstanceID().CompareTo(((Object)other.Enemy).GetInstanceID());
			}
			return num3;
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		private static readonly IEnumerable<SpawnableObject> enemies = Resources.FindObjectsOfTypeAll<SpawnableObjectsDatabase>().SelectMany((SpawnableObjectsDatabase db) => db.enemies);

		private static readonly GameObject iconPrefab = Plugin.Assets.LoadAsset<GameObject>("Enemy Icon");

		private static GameObject iconsCanvas;

		private static GameObject levelStats;

		private static readonly SortedSet<IconInfo> icons = new SortedSet<IconInfo>();

		[HarmonyPatch(typeof(EndlessGrid), "Start")]
		[HarmonyPostfix]
		private static void EndlessGrid_Start()
		{
			GameObject obj = Plugin.Assets.LoadAsset<GameObject>("Enemy Icons");
			CanvasController instance = MonoSingleton<CanvasController>.Instance;
			iconsCanvas = Object.Instantiate<GameObject>(obj, (instance != null) ? ((Component)instance).transform.Find("Level Stats Controller") : null);
			CanvasController instance2 = MonoSingleton<CanvasController>.Instance;
			levelStats = ((instance2 != null) ? ((Component)((Component)instance2).transform.Find("Level Stats Controller/Level Stats (1)")).gameObject : null);
			icons.Clear();
		}

		[HarmonyPatch(typeof(EndlessGrid), "SpawnOnGrid")]
		[HarmonyPostfix]
		private static void EndlessGrid_SpawnOnGrid(GameObject obj, bool radiant, GameObject __result, PrefabDatabase ___prefabs)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			EnemyIdentifier eid = ((__result != null) ? __result.GetComponentInChildren<EnemyIdentifier>(true) : null);
			if (eid != null)
			{
				GameObject val = Object.Instantiate<GameObject>(iconPrefab, Vector2.op_Implicit(Vector2.zero), Quaternion.identity, iconsCanvas.transform);
				((Component)val.transform.Find("Icon")).GetComponent<Image>().sprite = enemies.FirstOrDefault((Func<SpawnableObject, bool>)delegate(SpawnableObject spawnable)
				{
					EnemyIdentifier componentInChildren = spawnable.gameObject.GetComponentInChildren<EnemyIdentifier>(true);
					return ((componentInChildren != null) ? componentInChildren.FullName : null) == eid.FullName;
				})?.gridIcon;
				if (radiant)
				{
					((Component)val.transform.Find("Radiant")).gameObject.SetActive(true);
				}
				((Object)val).name = eid.FullName;
				EnemyCategory type = EnemyCategory.Common;
				if (___prefabs.uncommonEnemies.Any((EndlessEnemy prefab) => (Object)(object)prefab.prefab == (Object)(object)obj))
				{
					type = EnemyCategory.Uncommon;
				}
				else if (___prefabs.specialEnemies.Any((EndlessEnemy prefab) => (Object)(object)prefab.prefab == (Object)(object)obj))
				{
					type = EnemyCategory.Special;
				}
				else if ((Object)(object)obj == (Object)(object)___prefabs.hideousMass)
				{
					type = EnemyCategory.Mass;
				}
				icons.Add(new IconInfo(eid, type, radiant, val));
				CollectionExtensions.Do<IconInfo>((IEnumerable<IconInfo>)icons, (Action<IconInfo>)delegate(IconInfo icon2)
				{
					icon2.IconObject.transform.SetAsLastSibling();
				});
			}
		}

		[HarmonyPatch(typeof(EndlessGrid), "Update")]
		[HarmonyPostfix]
		private static void EndlessGrid_Update()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			((RectTransform)iconsCanvas.transform).anchoredPosition = (Vector2)(levelStats.activeSelf ? new Vector2(0f, -220f) : Vector2.zero);
			foreach (IconInfo icon in icons)
			{
				var (eid, type, flag2, val3) = (IconInfo)(ref icon);
				if (!Object.op_Implicit((Object)(object)eid) || Settings.HideCategories.Any(((EnemyCategory self, EnemyCategory other) hiders) => hiders.self == type && icons.Any((IconInfo otherIcon) => otherIcon.Type == hiders.other && !otherIcon.Enemy.dead)))
				{
					val3.SetActive(false);
					continue;
				}
				((Component)val3.transform.Find("Dead")).gameObject.SetActive(eid.dead);
				((Component)val3.transform.Find("Idoled")).gameObject.SetActive(eid.blessed);
				FilterType item2 = Settings.ShowEnemies.FirstOrDefault(((FilterType filter, string name, EnemyCategory type) item) => item.name == eid.FullName && item.type == type).filter;
				OnDeath onDeath = Settings.OnDeath;
				switch (item2)
				{
				case FilterType.RadiantOnly:
					switch (onDeath)
					{
					case OnDeath.Remove:
						val3.SetActive(flag2 && !eid.dead);
						break;
					case OnDeath.Marker:
						val3.SetActive(flag2);
						break;
					case OnDeath.RemoveIfAllDead:
						val3.SetActive(flag2 && AnyRadiantAlive());
						break;
					}
					break;
				case FilterType.PreferRadiant:
					switch (onDeath)
					{
					case OnDeath.Remove:
						val3.SetActive((flag2 || !AnyRadiantAlive()) && !eid.dead);
						break;
					case OnDeath.Marker:
						val3.SetActive(flag2 || !AnyRadiantAlive());
						break;
					case OnDeath.RemoveIfAllDead:
						val3.SetActive(flag2 ? AnyRadiantAlive() : (!AnyRadiantAlive() && AnyAlive()));
						break;
					}
					break;
				case FilterType.Both:
					switch (onDeath)
					{
					case OnDeath.Remove:
						val3.SetActive(!eid.dead);
						break;
					case OnDeath.Marker:
						val3.SetActive(true);
						break;
					case OnDeath.RemoveIfAllDead:
						val3.SetActive(AnyAlive());
						break;
					}
					break;
				case FilterType.Off:
					val3.SetActive(false);
					break;
				}
				bool AnyAlive()
				{
					return icons.Any((IconInfo otherIcon) => otherIcon.Enemy.FullName == eid.FullName && !otherIcon.Enemy.dead);
				}
				bool AnyRadiantAlive()
				{
					return icons.Any((IconInfo otherIcon) => otherIcon.Enemy.FullName == eid.FullName && otherIcon.IsRadiant && !otherIcon.Enemy.dead);
				}
			}
			iconsCanvas.SetActive(icons.Any((IconInfo icon) => icon.IconObject.activeSelf));
		}

		[HarmonyPatch(typeof(EndlessGrid), "NextWave")]
		[HarmonyPostfix]
		private static void EndlessGrid_NextWave()
		{
			CollectionExtensions.Do<IconInfo>((IEnumerable<IconInfo>)icons, (Action<IconInfo>)delegate(IconInfo icon)
			{
				Object.Destroy((Object)(object)icon.IconObject);
			});
			icons.Clear();
		}
	}
	[BepInPlugin("CGEnemyIcons", "CGEnemyIcons", "1.4.0")]
	internal class Plugin : BaseUnityPlugin
	{
		public static readonly AssetBundle Assets = AssetBundle.LoadFromFile(Path.Combine(ModDir, "cgenemyicons.bundle"));

		private static string ModDir => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		private void Awake()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			Settings.Initialize();
			new Harmony("CGEnemyIcons").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin CGEnemyIcons is loaded!");
		}
	}
	internal enum OnDeath
	{
		Marker,
		Remove,
		RemoveIfAllDead
	}
	internal enum FilterType
	{
		Both,
		RadiantOnly,
		PreferRadiant,
		Off
	}
	internal static class Settings
	{
		private static EnumField<OnDeath> onDeath;

		private static readonly Dictionary<EnumField<FilterType>, (string name, EnemyCategory type)> showEnemies = new Dictionary<EnumField<FilterType>, (string, EnemyCategory)>();

		private static readonly Dictionary<BoolField, (EnemyCategory self, EnemyCategory other)> hideCategories = new Dictionary<BoolField, (EnemyCategory, EnemyCategory)>();

		public static OnDeath OnDeath => onDeath.value;

		public static IEnumerable<(FilterType filter, string name, EnemyCategory type)> ShowEnemies => showEnemies.Select((KeyValuePair<EnumField<FilterType>, (string name, EnemyCategory type)> kvp) => (kvp.Key.value, kvp.Value.name, kvp.Value.type));

		public static IEnumerable<(EnemyCategory self, EnemyCategory other)> HideCategories => from kvp in hideCategories
			where kvp.Key.value
			select kvp.Value;

		internal static void Initialize()
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			PluginConfigurator config = PluginConfigurator.Create("CGEnemyIcons", "CGEnemyIcons");
			config.icon = Plugin.Assets.LoadAsset<Sprite>("Icon");
			onDeath = new EnumField<OnDeath>(config.rootPanel, "ACTION ON DEATH", "onDeath", OnDeath.Marker);
			onDeath.SetEnumDisplayName(OnDeath.Marker, "CROSS OUT");
			onDeath.SetEnumDisplayName(OnDeath.Remove, "REMOVE");
			onDeath.SetEnumDisplayName(OnDeath.RemoveIfAllDead, "REMOVE IF ALL DEAD");
			new ConfigHeader(config.rootPanel, "ENEMY TYPES", 24);
			PrefabDatabase val = Addressables.LoadAssetAsync<PrefabDatabase>((object)"Assets/Data/Cyber Grind Patterns/Data/Prefab Database.asset").WaitForCompletion();
			AddEnemies(val.meleeEnemies.Concat(val.projectileEnemies), EnemyCategory.Common);
			AddEnemies(val.uncommonEnemies, EnemyCategory.Uncommon);
			AddEnemies(val.specialEnemies, EnemyCategory.Special);
			CreateCategory(EnemyCategory.Mass, "HIDEOUS MASSES");
			AddEnemy(val.hideousMass, EnemyCategory.Mass);
			void AddEnemies(IEnumerable<EndlessEnemy> enemies, EnemyCategory category)
			{
				CreateCategory(category, EnumExtensions.Name<EnemyCategory>(category).ToUpperInvariant() + " ENEMIES");
				CollectionExtensions.Do<EndlessEnemy>(enemies, (Action<EndlessEnemy>)delegate(EndlessEnemy enemy)
				{
					AddEnemy(enemy.prefab, category);
				});
			}
			void AddEnemy(GameObject enemy, EnemyCategory category)
			{
				string fullName = enemy.GetComponentInChildren<EnemyIdentifier>(true).FullName;
				EnumField<FilterType> val2 = new EnumField<FilterType>(config.rootPanel, "SHOW " + fullName.ToUpperInvariant(), fullName, FilterType.Both);
				val2.SetEnumDisplayName(FilterType.Both, "YES");
				val2.SetEnumDisplayName(FilterType.RadiantOnly, "RADIANT ONLY");
				val2.SetEnumDisplayName(FilterType.PreferRadiant, "PREFER RADIANT");
				val2.SetEnumDisplayName(FilterType.Off, "NO");
				showEnemies.Add(val2, (fullName, category));
			}
			void CreateCategory(EnemyCategory category, string categoryName)
			{
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				new ConfigHeader(config.rootPanel, categoryName, 18);
				EnumExtensions.DoIf<EnemyCategory>(category, (Func<EnemyCategory, bool>)((EnemyCategory T) => T != category), (Action<EnemyCategory>)delegate(EnemyCategory T)
				{
					//IL_005a: Unknown result type (might be due to invalid IL or missing references)
					//IL_0070: Expected O, but got Unknown
					hideCategories.Add(new BoolField(config.rootPanel, "HIDE IF " + EnumExtensions.Name<EnemyCategory>(T).ToUpperInvariant() + " ALIVE", "hide" + EnumExtensions.Name<EnemyCategory>(category).ToLowerInvariant() + "if" + EnumExtensions.Name<EnemyCategory>(T).ToLowerInvariant(), false), (category, T));
				});
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "CGEnemyIcons";

		public const string PLUGIN_NAME = "CGEnemyIcons";

		public const string PLUGIN_VERSION = "1.4.0";
	}
}
namespace System.Runtime.CompilerServices
{
	public class IsExternalInit
	{
	}
}