Decompiled source of UKMDUnlocker v0.2.1

UKMDUnlocker.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BananaDifficulty;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Logging;
using Discord;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UKMDUnlocker.CrossMod;
using Ultrapain;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using plog;
using plog.Models;

[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: AssemblyCompany("UKMDUnlocker")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Adds ULTRAKILL MUST DIE to the difficulty selection menu.")]
[assembly: AssemblyFileVersion("0.2.1.0")]
[assembly: AssemblyInformationalVersion("0.2.1+0eb7d31ac81e59ca6593351155ebd444c4848399")]
[assembly: AssemblyProduct("UKMDUnlocker")]
[assembly: AssemblyTitle("UKMDUnlocker")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.1.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 UKMDUnlocker
{
	[BepInPlugin("com.whyis2plus2.UKMDUnlocker", "UKMDUnlocker", "0.2.1")]
	public class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static class PrefsManager_Ctor_Patch
		{
			private static void Postfix(Logger ___Log, ref Dictionary<string, Func<object, object>> ___propertyValidators)
			{
				___propertyValidators.Remove("difficulty");
				___propertyValidators.Add("difficulty", delegate(object value)
				{
					if (!(value is int num))
					{
						___Log.Warning("Difficulty value is not an int", (IEnumerable<Tag>)null, (string)null, (object)null);
						return (object)(GameDifficulty)2;
					}
					if (num < 0 || num > 5)
					{
						___Log.Warning("Difficulty validation error", (IEnumerable<Tag>)null, (string)null, (object)null);
						return (object)(GameDifficulty)5;
					}
					return value;
				});
			}
		}

		public const string PLUGIN_GUID = "com.whyis2plus2.UKMDUnlocker";

		public const string PLUGIN_NAME = "UKMDUnlocker";

		public const string PLUGIN_VERSION = "0.2.1";

		public const string DIF_NAME = "Ultrakill Must Die";

		public const string DIF_NAME_SHORT = "UKMD";

		public GameObject UKMDButton = null;

		public GameObject UKMDInfo = null;

		public static Plugin Instance;

		private readonly Harmony Harmony = new Harmony("com.whyis2plus2.UKMDUnlocker");

		public Transform Interactables { get; private set; }

		public ManualLogSource Log => ((BaseUnityPlugin)this).Logger;

		private void Awake()
		{
			Instance = this;
			SceneManager.activeSceneChanged += delegate
			{
				OnSceneChange();
			};
			BananasFix.Init();
			UltrapainFix.Init();
			Harmony.PatchAll();
			Log.LogInfo((object)"Loaded UKMDUnlocker");
		}

		private void OnSceneChange()
		{
			//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)
			LeaderboardProperties.Difficulties[5] = ((SceneHelper.CurrentScene == "Main Menu") ? "UKMD" : "Ultrakill Must Die");
			if (!(SceneHelper.CurrentScene != "Main Menu"))
			{
				Scene activeScene = SceneManager.GetActiveScene();
				Transform transform = (from obj in ((Scene)(ref activeScene)).GetRootGameObjects()
					where ((Object)obj).name == "Canvas"
					select obj).First().transform;
				Interactables = transform.Find("Difficulty Select (1)/Interactables");
				AddInfo();
				AddButton();
			}
		}

		private void AddButton()
		{
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			Log.LogInfo((object)"Adding UKMD Button...");
			Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>(new <>z__ReadOnlyArray<KeyValuePair<string, GameObject>>(new KeyValuePair<string, GameObject>[6]
			{
				FindElem("Casual Easy"),
				FindElem("Casual Hard"),
				FindElem("Standard"),
				FindElem("Violent"),
				FindElem("Brutal"),
				FindElem("V1 Must Die")
			}));
			Dictionary<string, GameObject> infos = new Dictionary<string, GameObject>(new <>z__ReadOnlyArray<KeyValuePair<string, GameObject>>(new KeyValuePair<string, GameObject>[5]
			{
				FindElem("Harmless Info"),
				FindElem("Lenient Info"),
				FindElem("Standard Info"),
				FindElem("Violent Info"),
				FindElem("Brutal Info")
			}));
			UKMDButton = Object.Instantiate<GameObject>(GeneralExtensions.GetValueSafe<string, GameObject>(dictionary, "Brutal"), Interactables);
			UKMDButton.GetComponent<DifficultySelectButton>().difficulty = 5;
			((Component)UKMDButton.transform.Find("Name")).GetComponent<TMP_Text>().text = "Ultrakill Must Die".ToUpper();
			UKMDButton.transform.position = GeneralExtensions.GetValueSafe<string, GameObject>(dictionary, "V1 Must Die").transform.position;
			((Object)UKMDButton).name = "UKMD Button";
			GeneralExtensions.GetValueSafe<string, GameObject>(dictionary, "V1 Must Die").gameObject.SetActive(false);
			EventTrigger component = UKMDButton.GetComponent<EventTrigger>();
			component.triggers.Clear();
			if (!Object.op_Implicit((Object)(object)UKMDInfo))
			{
				AddInfo();
			}
			foreach (GameObject value in dictionary.Values)
			{
				EventTrigger component2 = value.GetComponent<EventTrigger>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					component2.triggers.Add(Tools.CreateTriggerEntry((EventTriggerType)0, delegate
					{
						UKMDInfo.SetActive(false);
					}));
				}
			}
			component.triggers.AddRange(new <>z__ReadOnlyArray<Entry>((Entry[])(object)new Entry[3]
			{
				Tools.CreateTriggerEntry((EventTriggerType)0, delegate
				{
					UKMDInfo.SetActive(true);
					foreach (GameObject value2 in infos.Values)
					{
						value2.SetActive(false);
					}
				}),
				Tools.CreateTriggerEntry((EventTriggerType)1, delegate
				{
					UKMDInfo.SetActive(false);
				}),
				Tools.CreateTriggerEntry((EventTriggerType)4, delegate
				{
					UKMDInfo.SetActive(((Component)Interactables).gameObject.activeSelf);
				})
			}));
			ObjectActivateInSequence component3 = ((Component)Interactables).GetComponent<ObjectActivateInSequence>();
			component3.objectsToActivate[14] = UKMDButton;
			Log.LogInfo((object)"Added UKMD Button");
			KeyValuePair<string, GameObject> FindElem(string name)
			{
				return new KeyValuePair<string, GameObject>(name, ((Component)Interactables.Find(name)).gameObject);
			}
		}

		private void AddInfo()
		{
			Log.LogInfo((object)"Adding UKMD Info...");
			UKMDInfo = Object.Instantiate<GameObject>(((Component)Interactables.Find("Brutal Info")).gameObject, Interactables);
			((Object)UKMDInfo).name = "UKMD Info";
			TMP_Text component = ((Component)UKMDInfo.transform.Find("Title (1)")).GetComponent<TMP_Text>();
			component.fontSize = 29f;
			component.text = "--" + "Ultrakill Must Die".ToUpper() + "--";
			((Component)UKMDInfo.transform.Find("Text")).GetComponent<TMP_Text>().text = "<color=yellow>The unfinished version of UKMD in the game's files.</color>\r\n\r\n<color=white>Fast and extremely aggresive enemies with very high damage.\r\n\r\nQuick thinking and a full arsenal are expected. Slip-ups are often fatal.</color>\r\n\r\n<b>Recommended for players who have achieved near mastery over the game and are looking for a fitting challenge.</b>";
			Log.LogInfo((object)"Added UKMD Info");
		}
	}
	public static class Tools
	{
		public static Entry CreateTriggerEntry(EventTriggerType id, UnityAction<BaseEventData> call)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			Entry val = new Entry
			{
				eventID = id
			};
			((UnityEvent<BaseEventData>)(object)val.callback).AddListener(call);
			return val;
		}
	}
}
namespace UKMDUnlocker.CrossMod
{
	public static class BananasFix
	{
		[HarmonyPatch(typeof(BananaDifficultyPlugin), "CanUseIt")]
		private static class BananaDifficultyPlugin_CanUseIt_Patch
		{
			private static bool Prepare()
			{
				return HasBananas;
			}

			private static void Postfix(ref bool __result)
			{
				if (!IsEnabled)
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(DifficultyTitle), "Check")]
		private class DifficultyTitle_Check_Patch
		{
			private static bool Prepare()
			{
				return HasBananas;
			}

			private static void Postfix(ref TMP_Text ___txt2)
			{
				if (!IsEnabled && ___txt2.text.Contains("BANANAS DIFFICULTY"))
				{
					___txt2.text = ___txt2.text.Replace("BANANAS DIFFICULTY", "Ultrakill Must Die".ToUpper());
				}
			}
		}

		[HarmonyPatch(typeof(DiscordController), "SendActivity")]
		private static class DiscordController_SendActivity_Patch
		{
			private static bool Prepare()
			{
				return HasBananas;
			}

			private static void Prefix(ref Activity ___cachedActivity)
			{
				if (!IsEnabled && !(___cachedActivity.State != "DIFFICULTY: BANANAS"))
				{
					___cachedActivity.State = "DIFFICULTY UKMD";
				}
			}
		}

		public static bool HasBananas => Chainloader.PluginInfos.ContainsKey("com.michi.BananaDifficulty");

		public static bool IsEnabled { get; private set; }

		public static Transform Button { get; private set; }

		public static Transform Info { get; private set; }

		private static Plugin plugin => Plugin.Instance;

		public static void Init()
		{
			if (HasBananas)
			{
				plugin.Log.LogInfo((object)"Detected BananasDifficulty");
				SceneManager.activeSceneChanged += delegate
				{
					OnSceneChange();
				};
			}
		}

		private static void OnSceneChange()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			if (SceneHelper.CurrentScene != "Main Menu")
			{
				return;
			}
			foreach (Transform interactable in plugin.Interactables)
			{
				Transform val = interactable;
				if (((Object)val).name != "Brutal(Clone)")
				{
					continue;
				}
				plugin.Log.LogInfo((object)$"Found Brutal(Clone) with ID {((Object)val).GetInstanceID()}");
				Transform val2 = val.Find("Name");
				if (Object.op_Implicit((Object)(object)val2))
				{
					TMP_Text component = ((Component)val2).GetComponent<TMP_Text>();
					if (component.text.ToLower().Contains("banana"))
					{
						plugin.Log.LogInfo((object)$"Found BananasDifficulty button (ID: {((Object)val).GetInstanceID()})");
						Button = val;
						break;
					}
				}
			}
			foreach (Transform interactable2 in plugin.Interactables)
			{
				Transform val3 = interactable2;
				if (((Object)val3).name != "Brutal Info(Clone)")
				{
					continue;
				}
				plugin.Log.LogInfo((object)$"Found Brutal Info(Clone) with ID {((Object)val3).GetInstanceID()}");
				Transform val4 = val3.Find("Title (1)");
				if (Object.op_Implicit((Object)(object)val4))
				{
					TMP_Text component2 = ((Component)val4).GetComponent<TMP_Text>();
					if (component2.text.ToLower().Contains("banana"))
					{
						plugin.Log.LogInfo((object)$"Found BananasDifficulty info (ID: {((Object)val3).GetInstanceID()})");
						Info = val3;
						break;
					}
				}
			}
			((Component)Button).GetComponent<EventTrigger>().triggers.Add(Tools.CreateTriggerEntry((EventTriggerType)4, delegate
			{
				IsEnabled = true;
			}));
			plugin.UKMDButton.GetComponent<EventTrigger>().triggers.Add(Tools.CreateTriggerEntry((EventTriggerType)4, delegate
			{
				IsEnabled = false;
			}));
			TMP_Text component3 = ((Component)Info.Find("Text")).GetComponent<TMP_Text>();
			component3.text += "\n\n<#ff0>This uses the same save data as Ultrakill Must Die";
		}
	}
	public static class UltrapainFix
	{
		public static bool HasUltrapain => Chainloader.PluginInfos.ContainsKey("com.eternalUnion.ultraPain");

		public static Transform Button => Plugin.currentDifficultyButton.transform;

		public static Transform Info => ((TMP_Text)Plugin.currentDifficultyInfoText).transform.parent;

		private static Plugin plugin => Plugin.Instance;

		public static void Init()
		{
			if (HasUltrapain)
			{
				plugin.Log.LogInfo((object)"Detected Ultrapain");
				SceneManager.activeSceneChanged += delegate
				{
					OnSceneChange();
				};
			}
		}

		private static void OnSceneChange()
		{
			if (!(SceneHelper.CurrentScene != "Main Menu"))
			{
				((Component)Button).GetComponent<EventTrigger>().triggers.Add(Tools.CreateTriggerEntry((EventTriggerType)0, delegate
				{
					plugin.UKMDInfo.SetActive(false);
				}));
				plugin.UKMDButton.GetComponent<EventTrigger>().triggers.Add(Tools.CreateTriggerEntry((EventTriggerType)0, delegate
				{
					((Component)Info).gameObject.SetActive(false);
				}));
			}
		}
	}
}
[CompilerGenerated]
internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	int ICollection.Count => _items.Length;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => _items.Length;

	T IReadOnlyList<T>.this[int index] => _items[index];

	int ICollection<T>.Count => _items.Length;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlyArray(T[] items)
	{
		_items = items;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return ((IEnumerable)_items).GetEnumerator();
	}

	void ICollection.CopyTo(Array array, int index)
	{
		((ICollection)_items).CopyTo(array, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return ((IList)_items).Contains(value);
	}

	int IList.IndexOf(object value)
	{
		return ((IList)_items).IndexOf(value);
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return ((IEnumerable<T>)_items).GetEnumerator();
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return ((ICollection<T>)_items).Contains(item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		((ICollection<T>)_items).CopyTo(array, arrayIndex);
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		return ((IList<T>)_items).IndexOf(item);
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}