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 _effectOverrides = new Dictionary(); private readonly Dictionary _designOverrides = new Dictionary(); private readonly HashSet _skinWarnings = new HashSet(); private ConfigEntry _enabled; private ConfigEntry _savedEffects; private ConfigEntry _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("General", "Enabled", true, "Enable exact Summoning Portal demon selection."); _savedEffects = ((BaseUnityPlugin)this).Config.Bind("Choices", "FollowerDemonTypes", "", "Persisted follower ID to demon combat effect choices."); _savedDesigns = ((BaseUnityPlugin)this).Config.Bind("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 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 occupiedTypes = GetOccupiedTypes(follower.ID); foreach (FollowerInformationBox followerInfoBox in ((UIFollowerSelectBase)(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(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 GetOccupiedTypes(int selectedFollowerId) { HashSet hashSet = new HashSet(); 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 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 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(); if ((Object)(object)demonChoiceCardControls == (Object)null) { demonChoiceCardControls = ((Component)__instance).gameObject.AddComponent(); } 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(); if ((Object)(object)_menu == (Object)null) { _menu = ((Component)((Component)card).transform.root).GetComponentInChildren(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(); } 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.Instance != (Object)null) ? MonoSingleton.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)(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)(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)((Component)_card).GetComponentsInChildren(true)).FirstOrDefault((Func)((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(true) where (Object)(object)image.sprite != (Object)null select image.sprite).FirstOrDefault(); _root = new GameObject("Demon Effect Selector"); RectTransform obj = _root.AddComponent(); ((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(); obj2.overrideSorting = true; obj2.sortingOrder = 30000; _root.AddComponent(); Image obj3 = _root.AddComponent(); 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(); _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(); ((Transform)obj).SetParent(_root.transform, false); SetRect(obj, 0.08f, y, 0.84f, 0.27f); background = val.AddComponent(); 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(); ((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(); ((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().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()).SetParent(parent, false); TextMeshProUGUI obj = val.AddComponent(); ((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(); if ((Object)(object)demonDesignApplicator == (Object)null) { demonDesignApplicator = ((Component)__instance).gameObject.AddComponent(); } 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); } } }