Decompiled source of DemonSummonSelector v0.4.0

plugins/DemonSummonSelector.dll

Decompiled 5 days 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.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Lamb.UI;
using Lamb.UI.FollowerSelect;
using Microsoft.CodeAnalysis;
using Spine;
using Spine.Unity;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using src.UINavigator;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Demon Summon Selector")]
[assembly: AssemblyDescription("Native Summoning Portal demon archetype selector for Cult of the Lamb")]
[assembly: AssemblyCompany("Codex")]
[assembly: AssemblyProduct("Demon Summon Selector")]
[assembly: ComVisible(false)]
[assembly: Guid("8391c6a4-9f18-4b9f-9fc4-5dbdb2a8c3ce")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyVersion("0.4.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[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 DemonSummonSelector
{
	[BepInPlugin("com.cotl.demonsummonselector", "Demon Summon Selector", "0.4.0")]
	public sealed class DemonSummonSelectorPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.cotl.demonsummonselector";

		public const string PluginName = "Demon Summon Selector";

		public const string PluginVersion = "0.4.0";

		private static readonly int[] SelectableDesignTypes = new int[10] { 0, 1, 2, 3, 4, 5, 8, 9, 10, 11 };

		private static readonly FieldInfo PortalDemonsField = AccessTools.Field(typeof(Interaction_DemonSummoner), "demons");

		private readonly Dictionary<int, int> _effectOverrides = new Dictionary<int, int>();

		private readonly Dictionary<int, int> _designOverrides = new Dictionary<int, int>();

		private readonly HashSet<string> _skinWarnings = new HashSet<string>();

		private ConfigEntry<bool> _enabled;

		private ConfigEntry<string> _savedEffects;

		private ConfigEntry<string> _savedDesigns;

		private Harmony _harmony;

		private float _nextPortalRefresh;

		internal static DemonSummonSelectorPlugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable exact Summoning Portal demon selection.");
			_savedEffects = ((BaseUnityPlugin)this).Config.Bind<string>("Choices", "FollowerDemonTypes", "", "Persisted follower ID to demon combat effect choices.");
			_savedDesigns = ((BaseUnityPlugin)this).Config.Bind<string>("Choices", "FollowerDemonDesigns", "", "Persisted follower ID to demon appearance choices.");
			LoadChoices();
			_harmony = new Harmony("com.cotl.demonsummonselector");
			_harmony.PatchAll(typeof(DemonSummonSelectorPlugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Demon Summon Selector 0.4.0 loaded.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			Instance = null;
		}

		private void Update()
		{
			if (_enabled != null && _enabled.Value && !(Time.unscaledTime < _nextPortalRefresh))
			{
				_nextPortalRefresh = Time.unscaledTime + 0.4f;
				ApplyPortalDesigns();
			}
		}

		internal bool TryGetOverride(int followerId, out int demonType)
		{
			demonType = -1;
			if (_enabled == null || !_enabled.Value)
			{
				return false;
			}
			if (DataManager.Instance == null)
			{
				return false;
			}
			FollowerInfo infoByID = FollowerInfo.GetInfoByID(followerId, true);
			if (!CanCustomizeEffect(infoByID))
			{
				return false;
			}
			if (_effectOverrides.TryGetValue(followerId, out demonType) && demonType >= 0)
			{
				return demonType <= 5;
			}
			return false;
		}

		internal int GetCurrentType(FollowerInfo follower)
		{
			if (follower == null)
			{
				return -1;
			}
			if (!TryGetOverride(follower.ID, out var demonType))
			{
				return GetVanillaType(follower);
			}
			return demonType;
		}

		internal int GetCurrentDesign(FollowerInfo follower)
		{
			if (follower == null)
			{
				return -1;
			}
			if (!_designOverrides.TryGetValue(follower.ID, out var value) || !IsSelectableDesign(value))
			{
				return GetVanillaType(follower);
			}
			return value;
		}

		internal bool CanCustomizeEffect(FollowerInfo follower)
		{
			if (follower == null)
			{
				return false;
			}
			if (follower.Traits != null && follower.Traits.Contains((TraitType)90))
			{
				return false;
			}
			int iD = follower.ID;
			if ((uint)(iD - 99994) <= 1u || iD == 100000)
			{
				return false;
			}
			return true;
		}

		internal bool CanCustomizeDesign(FollowerInfo follower)
		{
			return CanCustomizeEffect(follower);
		}

		internal bool CycleEffect(FollowerInfo follower, int direction)
		{
			if (!CanCustomizeEffect(follower) || direction == 0)
			{
				return false;
			}
			if (!_designOverrides.ContainsKey(follower.ID))
			{
				_designOverrides[follower.ID] = GetCurrentDesign(follower);
			}
			int num = GetCurrentType(follower);
			if (num < 0 || num > 5)
			{
				num = ((direction > 0) ? (-1) : 0);
			}
			HashSet<int> occupiedTypes = GetOccupiedTypes(follower.ID);
			for (int i = 0; i < 6; i++)
			{
				num = (num + ((direction > 0) ? 1 : 5)) % 6;
				if (!occupiedTypes.Contains(num))
				{
					_effectOverrides[follower.ID] = num;
					SaveChoices();
					Log.LogInfo((object)("Selected " + DemonModel.GetDemonName(num) + " effect for " + follower.Name + " (" + follower.ID + ")."));
					return true;
				}
			}
			return false;
		}

		internal bool CycleDesign(FollowerInfo follower, int direction)
		{
			if (!CanCustomizeDesign(follower) || direction == 0)
			{
				return false;
			}
			int currentDesign = GetCurrentDesign(follower);
			int num = Array.IndexOf(SelectableDesignTypes, currentDesign);
			if (num < 0)
			{
				num = 0;
			}
			num = (num + ((direction > 0) ? 1 : (SelectableDesignTypes.Length - 1))) % SelectableDesignTypes.Length;
			currentDesign = SelectableDesignTypes[num];
			_designOverrides[follower.ID] = currentDesign;
			SaveChoices();
			Log.LogInfo((object)("Selected " + DemonModel.GetDemonName(currentDesign) + " design for " + follower.Name + " (" + follower.ID + ")."));
			return true;
		}

		internal void RefreshFollowerButton(UIDemonSummonMenuController menu, FollowerInfo follower)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			if ((Object)(object)menu == (Object)null || follower == null)
			{
				return;
			}
			HashSet<int> occupiedTypes = GetOccupiedTypes(follower.ID);
			foreach (FollowerInformationBox followerInfoBox in ((UIFollowerSelectBase<FollowerInformationBox>)(object)menu).FollowerInfoBoxes)
			{
				if (!((Object)(object)followerInfoBox == (Object)null) && ((FollowerSelectItem)followerInfoBox).FollowerInfo != null && ((FollowerSelectItem)followerInfoBox).FollowerInfo.ID == follower.ID)
				{
					bool flag = ((FollowerSelectItem)followerInfoBox).FollowerSelectEntry != null && (int)((FollowerSelectItem)followerInfoBox).FollowerSelectEntry.AvailabilityStatus == 0;
					((FollowerSelectItem)followerInfoBox).Button.Confirmable = flag && !occupiedTypes.Contains(GetCurrentType(follower));
					break;
				}
			}
		}

		internal void ApplyPreviewDesign(DemonInfoCard card, FollowerInfo follower)
		{
			if (!((Object)(object)card == (Object)null) && CanCustomizeEffect(follower))
			{
				int currentDesign = GetCurrentDesign(follower);
				object? obj = AccessTools.Field(typeof(DemonInfoCard), "_demonSpine")?.GetValue(card);
				SkeletonGraphic val = (SkeletonGraphic)((obj is SkeletonGraphic) ? obj : null);
				object? obj2 = AccessTools.Field(typeof(DemonInfoCard), "_demonName")?.GetValue(card);
				TextMeshProUGUI val2 = (TextMeshProUGUI)((obj2 is TextMeshProUGUI) ? obj2 : null);
				if ((Object)(object)val != (Object)null)
				{
					ApplySkin(val.Skeleton, val.AnimationState, SkinName(currentDesign, follower.GetDemonLevel()), "preview");
				}
				if ((Object)(object)val2 != (Object)null)
				{
					((TMP_Text)val2).text = DemonModel.GetDemonName(currentDesign);
				}
			}
		}

		internal bool ApplyDungeonDesign(GameObject demonObject, int followerId)
		{
			if ((Object)(object)demonObject == (Object)null || DataManager.Instance == null)
			{
				return false;
			}
			FollowerInfo infoByID = FollowerInfo.GetInfoByID(followerId, true);
			if (!CanCustomizeEffect(infoByID))
			{
				return true;
			}
			string skinName = SkinName(GetCurrentDesign(infoByID), infoByID.GetDemonLevel());
			SkeletonAnimation[] componentsInChildren = demonObject.GetComponentsInChildren<SkeletonAnimation>(true);
			foreach (SkeletonAnimation val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ApplySkin(((SkeletonRenderer)val).Skeleton, val.AnimationState, skinName, ((Object)demonObject).name))
				{
					return true;
				}
			}
			return false;
		}

		private HashSet<int> GetOccupiedTypes(int selectedFollowerId)
		{
			HashSet<int> hashSet = new HashSet<int>();
			Interaction_DemonSummoner instance = Interaction_DemonSummoner.Instance;
			if ((Object)(object)instance == (Object)null || instance.StructureInfo == null || instance.StructureInfo.MultipleFollowerIDs == null)
			{
				return hashSet;
			}
			foreach (int multipleFollowerID in instance.StructureInfo.MultipleFollowerIDs)
			{
				if (multipleFollowerID != -1 && multipleFollowerID != selectedFollowerId)
				{
					hashSet.Add(DemonModel.GetDemonType(multipleFollowerID));
				}
			}
			return hashSet;
		}

		private static int GetVanillaType(FollowerInfo follower)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (follower == null)
			{
				return -1;
			}
			if (follower.Traits != null && follower.Traits.Contains((TraitType)90))
			{
				return 13;
			}
			switch (follower.ID)
			{
			case 99994:
				return 6;
			case 99995:
				return 7;
			case 99990:
				return 8;
			case 99991:
				return 9;
			case 99992:
				return 10;
			case 99993:
				return 11;
			case 100000:
				return 12;
			default:
			{
				State state = Random.state;
				Random.InitState(follower.ID);
				int result = Random.Range(0, 6);
				Random.state = state;
				return result;
			}
			}
		}

		private void LoadChoices()
		{
			_effectOverrides.Clear();
			_designOverrides.Clear();
			LoadMap(_savedEffects.Value, _effectOverrides, designMap: false);
			LoadMap(_savedDesigns.Value, _designOverrides, designMap: true);
		}

		private static void LoadMap(string raw, Dictionary<int, int> target, bool designMap)
		{
			if (string.IsNullOrWhiteSpace(raw))
			{
				return;
			}
			string[] array = raw.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Split(new char[1] { ':' });
				if (array2.Length != 2 || !int.TryParse(array2[0], out var result) || !int.TryParse(array2[1], out var result2))
				{
					continue;
				}
				bool num;
				if (!designMap)
				{
					if (result2 < 0)
					{
						continue;
					}
					num = result2 <= 5;
				}
				else
				{
					num = IsSelectableDesign(result2);
				}
				if (num)
				{
					target[result] = result2;
				}
			}
		}

		private void SaveChoices()
		{
			_savedEffects.Value = SerializeMap(_effectOverrides);
			_savedDesigns.Value = SerializeMap(_designOverrides);
			((BaseUnityPlugin)this).Config.Save();
		}

		private static string SerializeMap(Dictionary<int, int> values)
		{
			return string.Join(";", (from pair in values
				orderby pair.Key
				select pair.Key + ":" + pair.Value).ToArray());
		}

		private static bool IsSelectableDesign(int demonType)
		{
			return Array.IndexOf(SelectableDesignTypes, demonType) >= 0;
		}

		private void ApplyPortalDesigns()
		{
			Interaction_DemonSummoner instance = Interaction_DemonSummoner.Instance;
			if ((Object)(object)instance == (Object)null || PortalDemonsField == null || instance.StructureInfo == null || instance.StructureInfo.MultipleFollowerIDs == null || !(PortalDemonsField.GetValue(instance) is SkeletonAnimation[] array))
			{
				return;
			}
			int num = Mathf.Min(array.Length, instance.StructureInfo.MultipleFollowerIDs.Count);
			for (int i = 0; i < num; i++)
			{
				FollowerInfo infoByID = FollowerInfo.GetInfoByID(instance.StructureInfo.MultipleFollowerIDs[i], true);
				if (!((Object)(object)array[i] == (Object)null) && CanCustomizeEffect(infoByID))
				{
					ApplySkin(((SkeletonRenderer)array[i]).Skeleton, array[i].AnimationState, SkinName(GetCurrentDesign(infoByID), infoByID.GetDemonLevel()), "portal");
				}
			}
		}

		private static string SkinName(int design, int level)
		{
			if (design < 0 || design >= Interaction_DemonSummoner.DemonSkins.Length)
			{
				return "";
			}
			return Interaction_DemonSummoner.DemonSkins[design] + ((level > 1 && design < 6) ? "+" : "");
		}

		private bool ApplySkin(Skeleton skeleton, AnimationState animationState, string skinName, string context)
		{
			if (skeleton == null || string.IsNullOrEmpty(skinName))
			{
				return false;
			}
			Skin val = skeleton.Data.FindSkin(skinName);
			if (val == null)
			{
				string item = context + ":" + skinName;
				if (_skinWarnings.Add(item))
				{
					Log.LogWarning((object)("Demon design skin " + skinName + " is unavailable on " + context + "; keeping the effect prefab's normal appearance."));
				}
				return false;
			}
			if (skeleton.Skin != val)
			{
				skeleton.SetSkin(val);
				skeleton.SetSlotsToSetupPose();
				if (animationState != null)
				{
					animationState.Apply(skeleton, true);
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(DemonModel), "GetDemonType", new Type[] { typeof(int) })]
	internal static class DemonTypeOverridePatch
	{
		private static bool Prefix(int id, ref int __result)
		{
			DemonSummonSelectorPlugin instance = DemonSummonSelectorPlugin.Instance;
			if ((Object)(object)instance != (Object)null && instance.TryGetOverride(id, out var demonType))
			{
				__result = demonType;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(DemonInfoCard), "Configure")]
	internal static class DemonInfoCardConfigurePatch
	{
		private static void Postfix(DemonInfoCard __instance, FollowerInfo followerInfo)
		{
			if (!((Object)(object)__instance == (Object)null) && followerInfo != null)
			{
				DemonChoiceCardControls demonChoiceCardControls = ((Component)__instance).GetComponent<DemonChoiceCardControls>();
				if ((Object)(object)demonChoiceCardControls == (Object)null)
				{
					demonChoiceCardControls = ((Component)__instance).gameObject.AddComponent<DemonChoiceCardControls>();
				}
				demonChoiceCardControls.Configure(__instance, followerInfo);
				DemonSummonSelectorPlugin.Instance?.ApplyPreviewDesign(__instance, followerInfo);
			}
		}
	}
	internal enum DemonChoiceKind
	{
		Design,
		Effect
	}
	internal sealed class DemonChoiceCardControls : MonoBehaviour
	{
		private static readonly FieldInfo FollowerInfoField = AccessTools.Field(typeof(DemonInfoCard), "_followerInfo");

		private static readonly FieldInfo DemonNameField = AccessTools.Field(typeof(DemonInfoCard), "_demonName");

		private static readonly FieldInfo MenuCardControllerField = AccessTools.Field(typeof(UIDemonSummonMenuController), "_demonMenuInfoCardController");

		private DemonInfoCard _card;

		private DemonInfoCardController _controller;

		private UIDemonSummonMenuController _menu;

		private FollowerInfo _follower;

		private GameObject _root;

		private CanvasGroup _inputLayer;

		private TextMeshProUGUI _designText;

		private TextMeshProUGUI _effectText;

		private TextMeshProUGUI _hintText;

		private Image _designBackground;

		private Image _effectBackground;

		private RectTransform _designRow;

		private RectTransform _effectRow;

		private DemonChoiceKind _activeChoice = DemonChoiceKind.Effect;

		private float _ignoreInputUntil;

		private float _nextVerticalMove;

		internal void Configure(DemonInfoCard card, FollowerInfo follower)
		{
			_card = card;
			_follower = follower;
			_menu = ((Component)card).GetComponentInParent<UIDemonSummonMenuController>();
			if ((Object)(object)_menu == (Object)null)
			{
				_menu = ((Component)((Component)card).transform.root).GetComponentInChildren<UIDemonSummonMenuController>(true);
			}
			_controller = (DemonInfoCardController)(((Object)(object)_menu != (Object)null && MenuCardControllerField != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)_controller == (Object)null)
			{
				_controller = ((Component)card).GetComponentInParent<DemonInfoCardController>();
			}
			if ((Object)(object)_root == (Object)null)
			{
				Build();
			}
			DemonSummonSelectorPlugin instance = DemonSummonSelectorPlugin.Instance;
			bool flag = (Object)(object)instance != (Object)null && instance.CanCustomizeEffect(follower);
			_root.SetActive(flag);
			if (flag)
			{
				bool flag2 = instance.CanCustomizeDesign(follower);
				if ((Object)(object)_designRow != (Object)null)
				{
					((Component)_designRow).gameObject.SetActive(flag2);
				}
				if ((Object)(object)_effectRow != (Object)null)
				{
					SetRect(_effectRow, 0.08f, flag2 ? 0.28f : 0.43f, 0.84f, 0.27f);
				}
				if (!flag2)
				{
					_activeChoice = DemonChoiceKind.Effect;
				}
				RefreshLabel();
				_ignoreInputUntil = Time.unscaledTime + 0.12f;
			}
		}

		private void Update()
		{
			if ((Object)(object)_root == (Object)null)
			{
				return;
			}
			bool flag = IsCurrentCard();
			if ((Object)(object)_inputLayer != (Object)null)
			{
				_inputLayer.blocksRaycasts = flag;
				_inputLayer.interactable = flag;
			}
			if (_root.activeSelf != flag && (Object)(object)DemonSummonSelectorPlugin.Instance != (Object)null && DemonSummonSelectorPlugin.Instance.CanCustomizeEffect(_card.FollowerInfo))
			{
				_root.SetActive(flag);
			}
			if (!flag || !_root.activeInHierarchy || Time.unscaledTime < _ignoreInputUntil)
			{
				return;
			}
			_follower = _card.FollowerInfo ?? _follower;
			bool flag2 = false;
			bool flag3 = false;
			float num = 0f;
			PlayerFarming val = null;
			try
			{
				val = (((Object)(object)MonoSingleton<UINavigatorNew>.Instance != (Object)null) ? MonoSingleton<UINavigatorNew>.Instance.AllowInputOnlyFromPlayer : PlayerFarming.Instance);
				flag2 = InputManager.UI.GetPageNavigateLeftDown(val);
				flag3 = InputManager.UI.GetPageNavigateRightDown(val);
				num = InputManager.UI.GetVerticalAxis(val);
			}
			catch
			{
			}
			if (Input.GetKeyDown((KeyCode)91))
			{
				flag2 = true;
			}
			if (Input.GetKeyDown((KeyCode)93))
			{
				flag3 = true;
			}
			if ((Object)(object)_controller != (Object)null && !((Behaviour)_controller).enabled && (Object)(object)DemonSummonSelectorPlugin.Instance != (Object)null && DemonSummonSelectorPlugin.Instance.CanCustomizeDesign(_follower) && Time.unscaledTime >= _nextVerticalMove)
			{
				if (Input.GetKeyDown((KeyCode)119) || Input.GetKeyDown((KeyCode)273) || num > 0.65f)
				{
					SetActiveChoice(DemonChoiceKind.Design);
					_nextVerticalMove = Time.unscaledTime + 0.22f;
				}
				else if (Input.GetKeyDown((KeyCode)115) || Input.GetKeyDown((KeyCode)274) || num < -0.65f)
				{
					SetActiveChoice(DemonChoiceKind.Effect);
					_nextVerticalMove = Time.unscaledTime + 0.22f;
				}
			}
			if (flag2)
			{
				Select(_activeChoice, -1);
			}
			else if (flag3)
			{
				Select(_activeChoice, 1);
			}
			RefreshInputHint(val);
		}

		internal void Select(DemonChoiceKind kind, int direction)
		{
			DemonSummonSelectorPlugin instance = DemonSummonSelectorPlugin.Instance;
			if ((Object)(object)instance == (Object)null || !IsCurrentCard())
			{
				return;
			}
			_follower = _card.FollowerInfo ?? _follower;
			if ((kind == DemonChoiceKind.Design) ? instance.CycleDesign(_follower, direction) : instance.CycleEffect(_follower, direction))
			{
				SetActiveChoice(kind);
				if (kind == DemonChoiceKind.Effect)
				{
					instance.RefreshFollowerButton(_menu, _follower);
				}
				if (FollowerInfoField != null)
				{
					FollowerInfoField.SetValue(_card, null);
				}
				((UIInfoCardBase<FollowerInfo>)(object)_card).Configure(_follower);
				RefreshLabel();
				_ignoreInputUntil = Time.unscaledTime + 0.12f;
			}
		}

		internal void SetActiveChoice(DemonChoiceKind kind)
		{
			_activeChoice = kind;
			RefreshLabel();
		}

		private bool IsCurrentCard()
		{
			if ((Object)(object)_card == (Object)null || !((Component)_card).gameObject.activeInHierarchy)
			{
				return false;
			}
			if (!((Object)(object)_controller == (Object)null))
			{
				return (Object)(object)((UIInfoCardController<DemonInfoCard, FollowerInfo>)(object)_controller).CurrentCard == (Object)(object)_card;
			}
			return true;
		}

		private void RefreshLabel()
		{
			//IL_0084: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			DemonSummonSelectorPlugin instance = DemonSummonSelectorPlugin.Instance;
			if (!((Object)(object)instance == (Object)null) && _follower != null)
			{
				int currentDesign = instance.GetCurrentDesign(_follower);
				int currentType = instance.GetCurrentType(_follower);
				if ((Object)(object)_designText != (Object)null)
				{
					((TMP_Text)_designText).text = "DESIGN  " + DemonModel.GetDemonName(currentDesign);
					((Graphic)_designText).color = (Color)((_activeChoice == DemonChoiceKind.Design) ? new Color(1f, 0.82f, 0.08f, 1f) : StaticColors.OffWhiteColor);
				}
				if ((Object)(object)_effectText != (Object)null)
				{
					((TMP_Text)_effectText).text = "EFFECT  " + DemonModel.GetDemonName(currentType);
					((Graphic)_effectText).color = (Color)((_activeChoice == DemonChoiceKind.Effect) ? new Color(1f, 0.82f, 0.08f, 1f) : StaticColors.OffWhiteColor);
				}
				if ((Object)(object)_designBackground != (Object)null)
				{
					((Graphic)_designBackground).color = RowColor(_activeChoice == DemonChoiceKind.Design);
				}
				if ((Object)(object)_effectBackground != (Object)null)
				{
					((Graphic)_effectBackground).color = RowColor(_activeChoice == DemonChoiceKind.Effect);
				}
			}
		}

		private void RefreshInputHint(PlayerFarming inputOwner)
		{
			if (!((Object)(object)_hintText == (Object)null))
			{
				bool flag = false;
				try
				{
					flag = InputManager.General.InputIsController(inputOwner);
				}
				catch
				{
				}
				((TMP_Text)_hintText).text = ((!flag) ? (DemonSummonSelectorPlugin.Instance.CanCustomizeDesign(_follower) ? "W/S SELECT     [ / ] CHANGE" : "[ / ] CHANGE EFFECT") : (DemonSummonSelectorPlugin.Instance.CanCustomizeDesign(_follower) ? "UP/DOWN SELECT     LB/RB CHANGE" : "LB/RB CHANGE EFFECT"));
			}
		}

		private void Build()
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = (TextMeshProUGUI)((DemonNameField != null) ? /*isinst with value type is only supported in some contexts*/: null);
			TMP_Text val2 = (TMP_Text)(((Object)(object)val != (Object)null) ? ((object)val) : ((object)((IEnumerable<TMP_Text>)((Component)_card).GetComponentsInChildren<TMP_Text>(true)).FirstOrDefault((Func<TMP_Text, bool>)((TMP_Text text) => (Object)(object)text.font != (Object)null))));
			TMP_FontAsset font = (((Object)(object)val2 != (Object)null) ? val2.font : null);
			Sprite val3 = (from image in ((Component)_card).GetComponentsInChildren<Image>(true)
				where (Object)(object)image.sprite != (Object)null
				select image.sprite).FirstOrDefault();
			_root = new GameObject("Demon Effect Selector");
			RectTransform obj = _root.AddComponent<RectTransform>();
			((Transform)obj).SetParent(((Object)(object)val != (Object)null) ? ((TMP_Text)val).transform : ((Component)_card).transform, false);
			obj.anchorMin = new Vector2(0.5f, 0.5f);
			obj.anchorMax = new Vector2(0.5f, 0.5f);
			obj.sizeDelta = new Vector2(440f, 100f);
			obj.anchoredPosition = new Vector2(0f, -290f);
			((Transform)obj).SetAsLastSibling();
			Canvas obj2 = _root.AddComponent<Canvas>();
			obj2.overrideSorting = true;
			obj2.sortingOrder = 30000;
			_root.AddComponent<GraphicRaycaster>();
			Image obj3 = _root.AddComponent<Image>();
			obj3.sprite = val3;
			obj3.type = (Type)(((Object)(object)val3 != (Object)null) ? 1 : 0);
			((Graphic)obj3).color = new Color(0.025f, 0.02f, 0.018f, 0.97f);
			((Graphic)obj3).raycastTarget = false;
			_inputLayer = _root.AddComponent<CanvasGroup>();
			_inputLayer.interactable = true;
			_inputLayer.blocksRaycasts = true;
			_inputLayer.ignoreParentGroups = false;
			CreateChoiceRow("Design", DemonChoiceKind.Design, 0.58f, font, val3, out _designText, out _designBackground);
			CreateChoiceRow("Effect", DemonChoiceKind.Effect, 0.28f, font, val3, out _effectText, out _effectBackground);
			ref RectTransform designRow = ref _designRow;
			Transform parent = ((TMP_Text)_designText).transform.parent;
			designRow = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			ref RectTransform effectRow = ref _effectRow;
			Transform parent2 = ((TMP_Text)_effectText).transform.parent;
			effectRow = (RectTransform)(object)((parent2 is RectTransform) ? parent2 : null);
			_hintText = AddText("Input Hint", _root.transform, font, 11f, (FontStyles)1);
			SetRect(((TMP_Text)_hintText).rectTransform, 0.08f, 0.01f, 0.84f, 0.18f);
			((TMP_Text)_hintText).alignment = (TextAlignmentOptions)514;
			((Graphic)_hintText).color = new Color(0.75f, 0.69f, 0.61f, 1f);
		}

		private void CreateChoiceRow(string name, DemonChoiceKind kind, float y, TMP_FontAsset font, Sprite sprite, out TextMeshProUGUI label, out Image background)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			GameObject val = new GameObject(name + " Row");
			RectTransform obj = val.AddComponent<RectTransform>();
			((Transform)obj).SetParent(_root.transform, false);
			SetRect(obj, 0.08f, y, 0.84f, 0.27f);
			background = val.AddComponent<Image>();
			background.sprite = sprite;
			background.type = (Type)(((Object)(object)sprite != (Object)null) ? 1 : 0);
			((Graphic)background).raycastTarget = false;
			label = AddText(name + " Label", val.transform, font, 14f, (FontStyles)1);
			SetRect(((TMP_Text)label).rectTransform, 0.17f, 0f, 0.66f, 1f);
			((TMP_Text)label).alignment = (TextAlignmentOptions)514;
			CreateArrow("Previous " + name, val.transform, font, sprite, kind, next: false);
			CreateArrow("Next " + name, val.transform, font, sprite, kind, next: true);
		}

		private void CreateArrow(string name, Transform parent, TMP_FontAsset font, Sprite sprite, DemonChoiceKind kind, bool next)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			RectTransform obj = val.AddComponent<RectTransform>();
			((Transform)obj).SetParent(parent, false);
			obj.anchorMin = new Vector2(next ? 1f : 0f, 0.5f);
			obj.anchorMax = obj.anchorMin;
			obj.sizeDelta = new Vector2(43f, 38f);
			obj.anchoredPosition = new Vector2(next ? (-22f) : 22f, 0f);
			Image val2 = val.AddComponent<Image>();
			((Graphic)val2).color = new Color(0.52f, 0.035f, 0.025f, 0.98f);
			((Graphic)val2).raycastTarget = true;
			if ((Object)(object)sprite != (Object)null)
			{
				val2.sprite = sprite;
				val2.type = (Type)1;
			}
			TextMeshProUGUI obj2 = AddText("Glyph", val.transform, font, 32f, (FontStyles)1);
			SetRect(((TMP_Text)obj2).rectTransform, 0f, 0f, 1f, 1f);
			((TMP_Text)obj2).alignment = (TextAlignmentOptions)514;
			((Graphic)obj2).color = Color.white;
			((TMP_Text)obj2).text = (next ? ">" : "<");
			((Graphic)obj2).raycastTarget = false;
			val.AddComponent<DemonArrowClick>().Configure(this, kind, next ? 1 : (-1), val2);
		}

		private static TextMeshProUGUI AddText(string name, Transform parent, TMP_FontAsset font, float size, FontStyles style)
		{
			//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_0027: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			((Transform)val.AddComponent<RectTransform>()).SetParent(parent, false);
			TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).font = font;
			((TMP_Text)obj).fontSize = size;
			((TMP_Text)obj).fontStyle = style;
			((TMP_Text)obj).enableWordWrapping = false;
			((TMP_Text)obj).overflowMode = (TextOverflowModes)1;
			((Graphic)obj).raycastTarget = false;
			return obj;
		}

		private static void SetRect(RectTransform rect, float x, float y, float width, float height)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = new Vector2(x, y);
			rect.anchorMax = new Vector2(x + width, y + height);
			rect.offsetMin = Vector2.zero;
			rect.offsetMax = Vector2.zero;
		}

		private static Color RowColor(bool active)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!active)
			{
				return new Color(0.055f, 0.045f, 0.04f, 0.88f);
			}
			return new Color(0.26f, 0.035f, 0.025f, 0.96f);
		}
	}
	internal sealed class DemonArrowClick : MonoBehaviour, IPointerClickHandler, IEventSystemHandler, IPointerEnterHandler, IPointerExitHandler
	{
		private DemonChoiceCardControls _owner;

		private DemonChoiceKind _kind;

		private int _direction;

		private Image _image;

		private Color _normal;

		internal void Configure(DemonChoiceCardControls owner, DemonChoiceKind kind, int direction, Image image)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			_owner = owner;
			_kind = kind;
			_direction = direction;
			_image = image;
			_normal = ((Graphic)image).color;
		}

		public void OnPointerClick(PointerEventData eventData)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if ((int)eventData.button == 0)
			{
				_owner.Select(_kind, _direction);
			}
		}

		public void OnPointerEnter(PointerEventData eventData)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			_owner.SetActiveChoice(_kind);
			if ((Object)(object)_image != (Object)null)
			{
				((Graphic)_image).color = new Color(0.78f, 0.08f, 0.035f, 1f);
			}
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_image != (Object)null)
			{
				((Graphic)_image).color = _normal;
			}
		}
	}
	[HarmonyPatch(typeof(Demon), "Init")]
	internal static class DemonInitDesignPatch
	{
		private static void Postfix(Demon __instance, int followerID)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)DemonSummonSelectorPlugin.Instance == (Object)null))
			{
				DemonDesignApplicator demonDesignApplicator = ((Component)__instance).GetComponent<DemonDesignApplicator>();
				if ((Object)(object)demonDesignApplicator == (Object)null)
				{
					demonDesignApplicator = ((Component)__instance).gameObject.AddComponent<DemonDesignApplicator>();
				}
				demonDesignApplicator.Configure(followerID);
			}
		}
	}
	internal sealed class DemonDesignApplicator : MonoBehaviour
	{
		private int _followerId;

		private Coroutine _routine;

		internal void Configure(int followerId)
		{
			_followerId = followerId;
			if (_routine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_routine);
			}
			_routine = ((MonoBehaviour)this).StartCoroutine(ApplyAfterVanillaSkin());
		}

		private IEnumerator ApplyAfterVanillaSkin()
		{
			yield return null;
			Apply();
			yield return (object)new WaitForSecondsRealtime(0.15f);
			Apply();
			yield return (object)new WaitForSecondsRealtime(0.45f);
			Apply();
			yield return (object)new WaitForSecondsRealtime(0.8f);
			Apply();
			Object.Destroy((Object)(object)this);
		}

		private void Apply()
		{
			DemonSummonSelectorPlugin.Instance?.ApplyDungeonDesign(((Component)this).gameObject, _followerId);
		}
	}
}