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();
}
}