using System; 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 MMTools; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Follower Trait Tree")] [assembly: AssemblyDescription("Controller-friendly follower trait editor prototype for Cult of the Lamb")] [assembly: AssemblyCompany("Codex")] [assembly: AssemblyProduct("Follower Trait Tree")] [assembly: ComVisible(false)] [assembly: Guid("19bce3de-2b65-4097-8785-fb7c1357c570")] [assembly: AssemblyFileVersion("0.5.3.0")] [assembly: AssemblyVersion("0.5.3.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 FollowerTraitTree { [BepInPlugin("com.cotl.followertraittree", "Follower Trait Tree", "0.5.3")] public sealed class FollowerTraitTreePlugin : BaseUnityPlugin { public const string PluginGuid = "com.cotl.followertraittree"; public const string PluginName = "Follower Trait Tree"; public const string PluginVersion = "0.5.3"; internal const string ProfilePromptLabel = "View Follower Profile"; private Harmony _harmony; private KeyCode _openKey; private KeyCode _repairKey; private TraitTreeMenu _menu; private UIFollowerSummaryMenuController _followerSummaryMenu; private PlayerFarming _menuPlayer; private float _nextTreeAttach; private float _nextTreeUnlock; private bool _pausedByMenu; private bool _legacySozoChecked; private readonly HashSet _treeTypes = new HashSet(); private static readonly HashSet UnsafeTraits = new HashSet { (TraitType)35, (TraitType)53, (TraitType)54, (TraitType)55, (TraitType)56, (TraitType)57, (TraitType)61, (TraitType)62, (TraitType)63, (TraitType)64, (TraitType)65, (TraitType)66, (TraitType)67, (TraitType)70, (TraitType)71, (TraitType)72, (TraitType)73, (TraitType)74, (TraitType)75, (TraitType)76, (TraitType)77, (TraitType)78, (TraitType)80, (TraitType)81, (TraitType)90, (TraitType)92, (TraitType)112, (TraitType)113, (TraitType)116, (TraitType)121, (TraitType)122, (TraitType)123, (TraitType)124, (TraitType)125 }; private static readonly HashSet RepairTraits = new HashSet { (TraitType)57, (TraitType)67, (TraitType)78, (TraitType)90, (TraitType)92, (TraitType)72, (TraitType)53, (TraitType)54, (TraitType)55, (TraitType)56, (TraitType)112, (TraitType)113, (TraitType)122, (TraitType)123, (TraitType)124, (TraitType)125 }; private static readonly HashSet VisualStateTraits = new HashSet { (TraitType)90, (TraitType)92, (TraitType)72 }; internal static ManualLogSource Log { get; private set; } internal static FollowerTraitTreePlugin Instance { get; private set; } private void Awake() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; TraitTreeConfig.Bind(((BaseUnityPlugin)this).Config); _openKey = ParseKey(TraitTreeConfig.OpenKey.Value, (KeyCode)287); _repairKey = ParseKey(TraitTreeConfig.RepairKey.Value, (KeyCode)283); RefreshTreeTypes(); try { FollowerTrait.Initialise(); } catch { } _harmony = new Harmony("com.cotl.followertraittree"); _harmony.PatchAll(typeof(FollowerTraitTreePlugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Follower Trait Tree 0.5.3 loaded."); } private void OnDestroy() { _menu?.Close(); Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; Instance = null; } private void Update() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (TraitTreeConfig.Enabled.Value) { EnsureCrystalTreeUnlocked(); if (_menu != null && _menu.IsOpen) { _menu.HandleInput(); return; } if (Input.GetKeyDown(_openKey)) { OpenMenu(PlayerFarming.Instance); return; } AttachTreeInteractions(); TryRepairLegacySozo(); } } internal void OpenMenu(PlayerFarming player) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (DataManager.Instance == null || DataManager.Instance.Followers == null || DataManager.Instance.Followers.Count == 0) { Log.LogInfo((object)"Trait Tree: no followers available."); return; } if (_menu == null) { _menu = new TraitTreeMenu(this, _repairKey); } BeginMenuSession(player); _menu.Open(DataManager.Instance.Followers); } internal bool TryOpenFollowerProfile(interaction_FollowerInteraction interaction, StateMachine state) { if ((Object)(object)interaction == (Object)null || (Object)(object)((Component)interaction).GetComponent() == (Object)null || ((Interaction)interaction).SecondaryLabel != "View Follower Profile" || !CanOpenFollowerProfile(interaction)) { return false; } if ((Object)(object)MonoSingleton.Instance == (Object)null || (Object)(object)MonoSingleton.Instance.FollowerSummaryMenuTemplate == (Object)null) { return false; } PlayerFarming val = (((Object)(object)state != (Object)null) ? ((Component)state).GetComponent() : PlayerFarming.Instance); ((Interaction)interaction).EndIndicateHighlighted(val); BeginMenuSession(val); _followerSummaryMenu = MonoSingleton.Instance.ShowFollowerSummaryMenu(interaction.follower); UIFollowerSummaryMenuController openedMenu = _followerSummaryMenu; ((UIMenuBase)openedMenu).OnHidden = (Action)Delegate.Combine(((UIMenuBase)openedMenu).OnHidden, (Action)delegate { if ((Object)(object)_followerSummaryMenu == (Object)(object)openedMenu) { _followerSummaryMenu = null; } OnMenuClosed(); }); return true; } internal void ConfigureFollowerProfilePrompt(interaction_FollowerInteraction interaction) { if ((Object)(object)interaction == (Object)null) { return; } TraitProfilePromptMarker component = ((Component)interaction).GetComponent(); string secondaryLabel = ((Interaction)interaction).SecondaryLabel; if ((Object)(object)component != (Object)null && !string.IsNullOrEmpty(secondaryLabel) && secondaryLabel != "View Follower Profile") { Object.Destroy((Object)(object)component); return; } if (!CanOpenFollowerProfile(interaction)) { if ((Object)(object)component != (Object)null && (string.IsNullOrEmpty(secondaryLabel) || secondaryLabel == "View Follower Profile")) { ((Interaction)interaction).HasSecondaryInteraction = false; ((Interaction)interaction).SecondaryInteractable = false; ((Interaction)interaction).SecondaryLabel = ""; } return; } if ((Object)(object)component == (Object)null) { if (((Interaction)interaction).HasSecondaryInteraction || !string.IsNullOrEmpty(secondaryLabel)) { return; } component = ((Component)interaction).gameObject.AddComponent(); } ((Interaction)interaction).HasSecondaryInteraction = true; ((Interaction)interaction).SecondaryInteractable = true; ((Interaction)interaction).SecondaryLabel = "View Follower Profile"; } internal void OnMenuClosed() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 if (_pausedByMenu) { SimulationManager.UnPause(); _pausedByMenu = false; } if ((Object)(object)_menuPlayer != (Object)null && (Object)(object)_menuPlayer.state != (Object)null && (int)_menuPlayer.state.CURRENT_STATE == 13) { _menuPlayer.state.CURRENT_STATE = (State)0; } _menuPlayer = null; } private void BeginMenuSession(PlayerFarming player) { _menuPlayer = (((Object)(object)player != (Object)null) ? player : PlayerFarming.Instance); if (!SimulationManager.IsPaused) { SimulationManager.Pause(); _pausedByMenu = true; } if ((Object)(object)_menuPlayer != (Object)null && (Object)(object)_menuPlayer.state != (Object)null) { _menuPlayer.state.CURRENT_STATE = (State)13; } } private void AttachTreeInteractions() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) if (!TraitTreeConfig.EnableTreeInteraction.Value || Time.unscaledTime < _nextTreeAttach) { return; } _nextTreeAttach = Time.unscaledTime + 1f; Structure[] array = Structure.Structures.ToArray(); foreach (Structure val in array) { if (!((Object)(object)val == (Object)null) && val.Brain != null && val.Brain.Data != null && _treeTypes.Contains(val.Brain.Data.Type)) { TraitTreeInteraction traitTreeInteraction = ((Component)val).GetComponent(); if ((Object)(object)traitTreeInteraction == (Object)null) { traitTreeInteraction = ((Component)val).gameObject.AddComponent(); } traitTreeInteraction.Configure(this, val, TraitTreeConfig.InteractionRadius.Value); } } } private void EnsureCrystalTreeUnlocked() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (TraitTreeConfig.UnlockCrystalTree.Value && !(Time.unscaledTime < _nextTreeUnlock) && DataManager.Instance != null) { _nextTreeUnlock = Time.unscaledTime + 2f; TYPES item = (TYPES)195; bool flag = false; if (DataManager.Instance.UnlockedStructures != null && !DataManager.Instance.UnlockedStructures.Contains(item)) { DataManager.Instance.UnlockedStructures.Add(item); flag = true; } if (DataManager.Instance.RevealedStructures != null && !DataManager.Instance.RevealedStructures.Contains(item)) { DataManager.Instance.RevealedStructures.Add(item); flag = true; } if (flag) { Log.LogInfo((object)"Trait Tree unlocked the Crystal Tree decoration for this save."); } } } private void RefreshTreeTypes() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) _treeTypes.Clear(); string[] array = TraitTreeConfig.TreeStructureTypes.Value.Split(new char[3] { ',', ';', '|' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (Enum.TryParse(array[i].Trim(), ignoreCase: true, out TYPES result)) { _treeTypes.Add(result); } } if (_treeTypes.Count == 0) { _treeTypes.Add((TYPES)195); } } private void TryRepairLegacySozo() { if (_legacySozoChecked || !TraitTreeConfig.RepairLegacySozoOnLoad.Value || DataManager.Instance == null || DataManager.Instance.Followers == null) { return; } FollowerInfo val = ((IEnumerable)DataManager.Instance.Followers).FirstOrDefault((Func)((FollowerInfo f) => f != null && f.ID == 99996)); if (val != null) { _legacySozoChecked = true; int num = RepairFollower(val, legacySozoRepair: true); if (num > 0) { Log.LogWarning((object)("Trait Tree repaired Dr. Sozo by removing " + num + " incompatible state trait(s) left by v0.1.0.")); } } } internal static bool IsUnsafeTrait(TraitType trait) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return UnsafeTraits.Contains(trait); } internal static bool CanRestoreUnsafeTrait(FollowerInfo follower, TraitType trait) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if (follower == null || (int)trait != 81) { return false; } bool num = follower.ID == 99990 || follower.ID == 99991 || follower.ID == 99992 || follower.ID == 99993; bool flag = !string.IsNullOrEmpty(follower.SkinName) && follower.SkinName.IndexOf("CultLeader", StringComparison.OrdinalIgnoreCase) >= 0; return num || flag; } internal static bool HasRepairableStateTraits(FollowerInfo follower) { if (follower != null && follower.Traits != null) { return follower.Traits.Any(RepairTraits.Contains); } return false; } internal unsafe static bool ApplyTrait(FollowerInfo follower, TraitType trait) { //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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if (follower == null || (int)trait == 0) { return false; } if (follower.Traits == null) { follower.Traits = new List(); } FollowerBrain val = FollowerBrain.FindBrainByID(follower.ID); bool flag = follower.Traits.Contains(trait); if (!flag && IsUnsafeTrait(trait) && !CanRestoreUnsafeTrait(follower, trait)) { Log.LogWarning((object)("Trait Tree blocked unsafe state trait " + ((object)(*(TraitType*)(&trait))/*cast due to .constrained prefix*/).ToString() + " from being added to " + follower.Name + ".")); return false; } if (flag) { if (val == null) { follower.Traits.RemoveAll((TraitType t) => t == trait); TwitchFollowers.SendFollowers(); } else { val.RemoveTrait(trait, true); } } else if (val == null) { RemoveExclusiveTraits(follower, trait); follower.Traits.Add(trait); TwitchFollowers.SendFollowers(); } else { val.AddTrait(trait, true); if (!follower.Traits.Contains(trait)) { follower.Traits.Add(trait); } } RepairLiveFollower(follower, val, flag && VisualStateTraits.Contains(trait), flag && RepairTraits.Contains(trait)); if (TraitTreeConfig.AutoSaveAfterChange.Value) { try { SaveAndLoad.Save(); } catch (Exception ex) { Log.LogWarning((object)("Trait Tree autosave failed: " + ex.Message)); } } string text = (flag ? "Removed " : "Added "); Log.LogInfo((object)("Trait Tree: " + text + ((object)(*(TraitType*)(&trait))/*cast due to .constrained prefix*/).ToString() + (flag ? " from " : " to ") + follower.Name + " (" + follower.ID + ").")); return true; } internal static int RepairFollower(FollowerInfo follower, bool legacySozoRepair = false) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Invalid comparison between Unknown and I4 //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Invalid comparison between Unknown and I4 //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Invalid comparison between Unknown and I4 //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (follower == null || follower.Traits == null) { return 0; } int num = 0; bool flag = false; foreach (TraitType trait in RepairTraits) { if (follower.Traits.Contains(trait) && (legacySozoRepair || (int)trait == 57 || (int)trait == 67 || (int)trait == 78 || VisualStateTraits.Contains(trait))) { num += follower.Traits.RemoveAll((TraitType t) => t == trait); flag |= VisualStateTraits.Contains(trait); } } FollowerBrain brain = FollowerBrain.FindBrainByID(follower.ID); RepairLiveFollower(follower, brain, flag, num > 0); if (num > 0) { TwitchFollowers.SendFollowers(); if (TraitTreeConfig.AutoSaveAfterChange.Value) { try { SaveAndLoad.Save(); } catch (Exception ex) { Log.LogWarning((object)("Trait Tree repair save failed: " + ex.Message)); } } Log.LogInfo((object)("Trait Tree repaired " + follower.Name + " (" + follower.ID + "), removed " + num + " incompatible state trait(s).")); } return num; } private static void RemoveExclusiveTraits(FollowerInfo follower, TraitType trait) { //IL_0026: 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) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair pair in FollowerTrait.ExclusiveTraits) { if (pair.Key == trait) { follower.Traits.RemoveAll((TraitType t) => t == pair.Value); } else if (pair.Value == trait) { follower.Traits.RemoveAll((TraitType t) => t == pair.Key); } } } private static void RepairLiveFollower(FollowerInfo follower, FollowerBrain brain, bool rebuildOutfit, bool resetState) { Follower val = FollowerManager.FindFollowerByID(follower.ID); if ((Object)(object)val != (Object)null) { if (rebuildOutfit) { try { val.UpdateOutfit(); } catch (Exception ex) { Log.LogWarning((object)("Trait Tree outfit repair failed for " + follower.Name + ": " + ex.Message)); } } try { if ((Object)(object)val.Interaction_FollowerInteraction != (Object)null) { ((Behaviour)val.Interaction_FollowerInteraction).enabled = true; ((Interaction)val.Interaction_FollowerInteraction).Interactable = !follower.Traits.Contains((TraitType)57); } } catch (Exception ex2) { Log.LogWarning((object)("Trait Tree interaction repair failed for " + follower.Name + ": " + ex2.Message)); } } if (brain != null && resetState) { try { brain.CompleteCurrentTask(); brain.CheckChangeState(); } catch (Exception ex3) { Log.LogWarning((object)("Trait Tree state repair failed for " + follower.Name + ": " + ex3.Message)); } } } internal unsafe static string TraitTitle(TraitType trait) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) try { string localizedTitle = FollowerTrait.GetLocalizedTitle(trait); return string.IsNullOrEmpty(localizedTitle) ? ((object)(*(TraitType*)(&trait))/*cast due to .constrained prefix*/).ToString() : localizedTitle; } catch { return ((object)(*(TraitType*)(&trait))/*cast due to .constrained prefix*/).ToString(); } } private static KeyCode ParseKey(string raw, KeyCode fallback) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) try { return (KeyCode)Enum.Parse(typeof(KeyCode), raw, ignoreCase: true); } catch { return fallback; } } internal bool CanOpenTree() { if (TraitTreeConfig.Enabled.Value && TraitTreeConfig.EnableTreeInteraction.Value && (_menu == null || !_menu.IsOpen)) { return (Object)(object)_followerSummaryMenu == (Object)null; } return false; } private bool CanOpenFollowerProfile(interaction_FollowerInteraction interaction) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 if (TraitTreeConfig.Enabled.Value && TraitTreeConfig.EnableFollowerProfiles.Value && (int)PlayerFarming.Location == 1 && (Object)(object)interaction != (Object)null && ((Interaction)interaction).Interactable && !((Interaction)interaction).AutomaticallyInteract && (Object)(object)interaction.follower != (Object)null && interaction.follower.Brain != null && interaction.follower.Brain.Info != null && (_menu == null || !_menu.IsOpen)) { return (Object)(object)_followerSummaryMenu == (Object)null; } return false; } } public sealed class TraitTreeInteraction : Interaction { private FollowerTraitTreePlugin _plugin; private Structure _structure; internal void Configure(FollowerTraitTreePlugin plugin, Structure structure, float radius) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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) //IL_0044: Unknown result type (might be due to invalid IL or missing references) _plugin = plugin; _structure = structure; base.ActivateDistance = radius; base.ActivatorOffset = new Vector3(0f, 0.35f, 0f); base.Offset = new Vector3(0f, 3.5f, 0f); base.OutlineTarget = (((Object)(object)structure != (Object)null) ? ((Component)structure).gameObject : ((Component)this).gameObject); base.IgnoreTutorial = true; base.SwitchMainPlayerOnInteract = true; base.InputOnlyFromInteractingPlayer = true; ((Interaction)this).HasChanged = true; } public override void GetLabel() { if ((Object)(object)_plugin == (Object)null) { _plugin = FollowerTraitTreePlugin.Instance; } base.Interactable = (Object)(object)_plugin != (Object)null && _plugin.CanOpenTree() && (Object)(object)_structure != (Object)null; ((Interaction)this).Label = (base.Interactable ? "Manage Follower Traits" : ""); } public override void OnInteract(StateMachine state) { if (base.Interactable && !((Object)(object)_plugin == (Object)null)) { ((Interaction)this).OnInteract(state); _plugin.OpenMenu(((Object)(object)state != (Object)null) ? ((Component)state).GetComponent() : PlayerFarming.Instance); } } } internal sealed class TraitTreeMenu { private enum ScreenState { Followers, Traits } private readonly FollowerTraitTreePlugin _plugin; private readonly KeyCode _repairKey; private readonly List _followers = new List(); private readonly List _traits = new List(); private readonly List _followerRows = new List(); private readonly List _traitRows = new List(); private readonly List _traitIcons = new List(); private readonly List _nativeTraitItems = new List(); private readonly List _nativeTraitTypes = new List(); private readonly string[] _categories = new string[7] { "Current", "Positive", "Negative", "Sin", "Winter", "Special", "All" }; private GameObject _root; private GameObject _promptBar; private Transform _previewParent; private FollowerInformationBox _followerPreview; private int _previewFollowerId = -1; private TextMeshProUGUI _title; private TextMeshProUGUI _subtitle; private TextMeshProUGUI _modeText; private TextMeshProUGUI _categoryText; private TextMeshProUGUI _detailText; private TextMeshProUGUI _footerText; private int _selectedFollower; private int _selectedTrait; private int _followerTop; private int _traitTop; private int _category; private float _nextMove; private ScreenState _state; internal bool IsOpen { get { if ((Object)(object)_root != (Object)null) { return _root.activeSelf; } return false; } } internal TraitTreeMenu(FollowerTraitTreePlugin plugin, KeyCode repairKey) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) _plugin = plugin; _repairKey = repairKey; } internal void Open(List followers) { _followers.Clear(); foreach (FollowerInfo follower in followers) { if (follower != null) { _followers.Add(follower); } } _followers.Sort((FollowerInfo a, FollowerInfo b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase)); _selectedFollower = Mathf.Clamp(_selectedFollower, 0, Mathf.Max(0, _followers.Count - 1)); _selectedTrait = 0; _followerTop = 0; _traitTop = 0; _category = 0; _state = ScreenState.Followers; if ((Object)(object)_root == (Object)null) { Build(); } _root.SetActive(true); RefreshTraits(); Refresh(); } internal void Close() { if ((Object)(object)_root != (Object)null) { GameObject root = _root; _root = null; ClearViewReferences(); Object.Destroy((Object)(object)root); } _plugin.OnMenuClosed(); } internal void HandleInput() { if (RepairPressed()) { if (_followers.Count > 0) { FollowerTraitTreePlugin.RepairFollower(_followers[_selectedFollower]); RefreshTraits(); } Refresh(); return; } if (CancelPressed()) { if (_state == ScreenState.Traits) { _state = ScreenState.Followers; Refresh(); } else { Close(); } return; } if (_state == ScreenState.Traits) { if (PageLeftPressed()) { _category = (_category + _categories.Length - 1) % _categories.Length; _selectedTrait = 0; _traitTop = 0; RefreshTraits(); Refresh(); return; } if (PageRightPressed()) { _category = (_category + 1) % _categories.Length; _selectedTrait = 0; _traitTop = 0; RefreshTraits(); Refresh(); return; } } int move = GetMove(); if (move != 0) { MoveSelection(move); } if (AcceptPressed()) { Accept(); } } private void Accept() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (_followers.Count != 0) { if (_state == ScreenState.Followers) { _state = ScreenState.Traits; _selectedTrait = 0; _traitTop = 0; RefreshTraits(); Refresh(); } else if (_traits.Count != 0) { FollowerTraitTreePlugin.ApplyTrait(_followers[_selectedFollower], _traits[_selectedTrait]); RefreshTraits(); Refresh(); } } } private void MoveSelection(int delta) { if (_state == ScreenState.Followers) { _selectedFollower = Mathf.Clamp(_selectedFollower + delta, 0, Mathf.Max(0, _followers.Count - 1)); KeepVisible(ref _selectedFollower, ref _followerTop, _followerRows.Count, _followers.Count); _selectedTrait = 0; _traitTop = 0; RefreshTraits(); } else { _selectedTrait = Mathf.Clamp(_selectedTrait + delta, 0, Mathf.Max(0, _traits.Count - 1)); KeepVisible(ref _selectedTrait, ref _traitTop, _traitRows.Count, _traits.Count); } Refresh(); } private static void KeepVisible(ref int selected, ref int top, int visibleRows, int count) { if (selected < top) { top = selected; } if (selected >= top + visibleRows) { top = selected - visibleRows + 1; } top = Mathf.Clamp(top, 0, Mathf.Max(0, count - visibleRows)); } private void RefreshTraits() { _traits.Clear(); if (_followers.Count == 0) { return; } FollowerInfo follower = _followers[_selectedFollower]; IEnumerable source = from TraitType t in Enum.GetValues(typeof(TraitType)) where (int)t != 0 && (!FollowerTraitTreePlugin.IsUnsafeTrait(t) || FollowerTraitTreePlugin.CanRestoreUnsafeTrait(follower, t)) select t; switch (_categories[_category]) { case "Current": source = ((follower.Traits == null) ? Enumerable.Empty() : follower.Traits.Where((TraitType t) => (int)t > 0).Distinct()); break; case "Positive": source = source.Where((TraitType t) => FollowerTrait.GoodTraits.Contains(t)); break; case "Negative": source = source.Where((TraitType t) => !FollowerTrait.GoodTraits.Contains(t) && !FollowerTrait.UniqueTraits.Contains(t) && !FollowerTrait.SinTraits.Contains(t)); break; case "Sin": source = source.Where((TraitType t) => FollowerTrait.SinTraits.Contains(t)); break; case "Winter": source = source.Where((TraitType t) => FollowerTrait.WinterSpecificTraits.Contains(t)); break; case "Special": source = source.Where((TraitType t) => FollowerTrait.UniqueTraits.Contains(t) || FollowerTrait.MajorDLCTraits.Contains(t)); break; } _traits.AddRange(source.Distinct().OrderBy(FollowerTraitTreePlugin.TraitTitle)); _selectedTrait = Mathf.Clamp(_selectedTrait, 0, Mathf.Max(0, _traits.Count - 1)); KeepVisible(ref _selectedTrait, ref _traitTop, _traitRows.Count, _traits.Count); } private void Refresh() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_root == (Object)null)) { FollowerInfo val = ((_followers.Count > 0) ? _followers[_selectedFollower] : null); ((TMP_Text)_title).text = "Trait Tree"; ((TMP_Text)_subtitle).text = ((val == null) ? "No followers found" : (val.Name + " | " + ((val.Traits != null) ? val.Traits.Count : 0) + " traits")); ((TMP_Text)_modeText).text = "Safe Trait Editing"; ((Graphic)_modeText).color = new Color(0.62f, 1f, 0.72f, 1f); ((TMP_Text)_categoryText).text = ((_state == ScreenState.Traits) ? ("< " + _categories[_category] + " >") : "Followers"); RefreshFollowerRows(); RefreshFollowerPreview(val); RefreshTraitRows(val); RefreshDetail(val); ((TMP_Text)_footerText).text = (((Object)(object)_promptBar != (Object)null) ? "" : ((_state == ScreenState.Followers) ? "Accept: choose follower Back: close" : "Accept: add/remove Back: followers LB/RB: category")); } } private void RefreshFollowerRows() { //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _followerRows.Count; i++) { int num = _followerTop + i; TextMeshProUGUI val = _followerRows[i]; if (num >= _followers.Count) { ((TMP_Text)val).text = ""; ((Component)((TMP_Text)val).transform.parent).gameObject.SetActive(false); continue; } ((Component)((TMP_Text)val).transform.parent).gameObject.SetActive(true); FollowerInfo val2 = _followers[num]; bool flag = _state == ScreenState.Followers && num == _selectedFollower; ((TMP_Text)val).text = (flag ? "> " : " ") + val2.Name + " [" + ((val2.Traits != null) ? val2.Traits.Count : 0) + "]"; ((Graphic)val).color = (Color)(flag ? new Color(1f, 0.9f, 0.18f, 1f) : Color.white); ((Graphic)((Component)((TMP_Text)val).transform.parent).GetComponent()).color = (flag ? new Color(0.32f, 0.06f, 0.05f, 0.92f) : new Color(0.04f, 0.035f, 0.03f, 0.72f)); } } private void RefreshTraitRows(FollowerInfo follower) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_027c: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: 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) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _traitRows.Count; i++) { int num = _traitTop + i; TextMeshProUGUI val = _traitRows[i]; if (num >= _traits.Count) { ((TMP_Text)val).text = ""; ((Component)((TMP_Text)val).transform.parent).gameObject.SetActive(false); ((Component)_traitIcons[i]).gameObject.SetActive(false); if (i < _nativeTraitItems.Count && (Object)(object)_nativeTraitItems[i] != (Object)null) { ((Component)_nativeTraitItems[i]).gameObject.SetActive(false); } continue; } ((Component)((TMP_Text)val).transform.parent).gameObject.SetActive(true); TraitType val2 = _traits[num]; bool flag = follower != null && follower.Traits != null && follower.Traits.Contains(val2); bool flag2 = _state == ScreenState.Traits && num == _selectedTrait; bool flag3 = FollowerTraitTreePlugin.IsUnsafeTrait(val2) && !FollowerTraitTreePlugin.CanRestoreUnsafeTrait(follower, val2); ((TMP_Text)val).text = (flag2 ? "> " : " ") + (flag ? "[x] " : "[ ] ") + FollowerTraitTreePlugin.TraitTitle(val2) + (flag3 ? " [state]" : ""); ((Graphic)val).color = (Color)(flag2 ? new Color(1f, 0.9f, 0.18f, 1f) : (flag3 ? new Color(1f, 0.46f, 0.38f, 1f) : (flag ? new Color(0.62f, 1f, 0.72f, 1f) : Color.white))); ((Graphic)((Component)((TMP_Text)val).transform.parent).GetComponent()).color = (flag2 ? new Color(0.32f, 0.06f, 0.05f, 0.92f) : new Color(0.04f, 0.035f, 0.03f, 0.72f)); Image val3 = _traitIcons[i]; Sprite val4 = null; try { val4 = FollowerTrait.GetIcon(val2); } catch { } IndoctrinationTraitItem val5 = ((i < _nativeTraitItems.Count) ? _nativeTraitItems[i] : null); if ((Object)(object)val5 != (Object)null) { ((Component)val3).gameObject.SetActive(false); ((Component)val5).gameObject.SetActive(true); if (_nativeTraitTypes[i] != val2) { val5.Configure(val2); _nativeTraitTypes[i] = val2; } if (_categories[_category] == "Current") { ShowNativeTraitPolarity(val5, val2); } else { val5.SetState((Type)(flag ? 1 : 2)); } val5.SetDeactivated(false); } else { val3.sprite = val4; ((Component)val3).gameObject.SetActive((Object)(object)val4 != (Object)null); } ((Graphic)val3).color = (Color)(flag3 ? new Color(1f, 0.52f, 0.46f, 1f) : Color.white); } } private static void ShowNativeTraitPolarity(IndoctrinationTraitItem item, TraitType trait) { //IL_0120: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)item == (Object)null)) { object? obj = AccessTools.Field(typeof(IndoctrinationTraitItem), "_arrow")?.GetValue(item); Image val = (Image)((obj is Image) ? obj : null); object? obj2 = AccessTools.Field(typeof(IndoctrinationTraitItem), "_positiveArrow")?.GetValue(item); Sprite val2 = (Sprite)((obj2 is Sprite) ? obj2 : null); object? obj3 = AccessTools.Field(typeof(IndoctrinationTraitItem), "_negativeArrow")?.GetValue(item); Sprite val3 = (Sprite)((obj3 is Sprite) ? obj3 : null); object? obj4 = AccessTools.Field(typeof(IndoctrinationTraitItem), "manipulationShuffle")?.GetValue(item); GameObject val4 = (GameObject)((obj4 is GameObject) ? obj4 : null); object? obj5 = AccessTools.Field(typeof(IndoctrinationTraitItem), "manipulationAdd")?.GetValue(item); GameObject val5 = (GameObject)((obj5 is GameObject) ? obj5 : null); object? obj6 = AccessTools.Field(typeof(IndoctrinationTraitItem), "manipulationMinus")?.GetValue(item); object? obj7 = ((obj6 is GameObject) ? obj6 : null); if (val4 != null) { val4.SetActive(false); } if (val5 != null) { val5.SetActive(false); } if (obj7 != null) { ((GameObject)obj7).SetActive(false); } if ((Object)(object)val != (Object)null) { val.sprite = (FollowerTrait.IsPositiveTrait(trait) ? val2 : val3); ((Component)val).gameObject.SetActive(true); } } } private void RefreshFollowerPreview(FollowerInfo follower) { //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_previewParent == (Object)null || follower == null || _previewFollowerId == follower.ID) { return; } if ((Object)(object)_followerPreview != (Object)null) { Object.Destroy((Object)(object)((Component)_followerPreview).gameObject); _followerPreview = null; } try { UIManager instance = MonoSingleton.Instance; UIFollowerSummaryMenuController val = (((Object)(object)instance != (Object)null) ? instance.FollowerSummaryMenuTemplate : null); FollowerInformationBox val2 = (FollowerInformationBox)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 == (Object)null && (Object)(object)instance != (Object)null) { val2 = instance.FollowerInformationBoxTemplate; } if (!((Object)(object)val2 == (Object)null)) { _followerPreview = Object.Instantiate(val2, _previewParent, false); ((Object)((Component)_followerPreview).gameObject).name = "Native Follower Preview"; ((Component)_followerPreview).gameObject.SetActive(true); Transform transform = ((Component)_followerPreview).transform; RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val3 != (Object)null) { ApplyAnchors(val3, AnchorFull()); ((Transform)val3).localScale = Vector3.one; } ((FollowerSelectItem)_followerPreview).Configure(follower); ((FollowerSelectItem)_followerPreview).OnFollowerHighlighted = null; ((FollowerSelectItem)_followerPreview).OnFollowerSelected = null; if ((Object)(object)((FollowerSelectItem)_followerPreview).Button != (Object)null) { ((UnityEventBase)((Button)((FollowerSelectItem)_followerPreview).Button).onClick).RemoveAllListeners(); ((FollowerSelectItem)_followerPreview).Button.OnSelected = null; ((FollowerSelectItem)_followerPreview).Button.OnDeselected = null; ((FollowerSelectItem)_followerPreview).Button.OnConfirmDenied = null; ((Selectable)((FollowerSelectItem)_followerPreview).Button).interactable = false; } Graphic[] componentsInChildren = ((Component)_followerPreview).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].raycastTarget = false; } _previewFollowerId = follower.ID; } } catch (Exception ex) { FollowerTraitTreePlugin.Log.LogWarning((object)("Could not create native follower preview: " + ex.Message)); } } private unsafe void RefreshDetail(FollowerInfo follower) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (follower == null) { ((TMP_Text)_detailText).text = ""; return; } if (_state == ScreenState.Followers || _traits.Count == 0) { string text = ((follower.Traits == null || follower.Traits.Count == 0) ? "No current traits." : string.Join(", ", follower.Traits.Distinct().Select(FollowerTraitTreePlugin.TraitTitle).Take(12) .ToArray())); ((TMP_Text)_detailText).text = text; return; } TraitType val = _traits[_selectedTrait]; bool flag = follower.Traits != null && follower.Traits.Contains(val); string text2; try { text2 = FollowerTrait.GetLocalizedDescription(val, FollowerBrain.FindBrainByID(follower.ID)); } catch { text2 = ((object)(*(TraitType*)(&val))/*cast due to .constrained prefix*/).ToString(); } if (FollowerTraitTreePlugin.IsUnsafeTrait(val) && !FollowerTraitTreePlugin.CanRestoreUnsafeTrait(follower, val)) { ((TMP_Text)_detailText).text = "State or quest trait.\n\nThis entry can be removed here, but cannot be added. These traits can disable normal follower interactions when assigned outside their vanilla event.\n\n" + text2; } else { ((TMP_Text)_detailText).text = (flag ? "Currently applied. Accept removes it.\n\n" : "Not applied. Accept adds it.\n\n") + text2; } } private void Build() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Expected O, but got Unknown //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Unknown result type (might be due to invalid IL or missing references) //IL_04bd: Unknown result type (might be due to invalid IL or missing references) //IL_0543: Unknown result type (might be due to invalid IL or missing references) //IL_055c: Unknown result type (might be due to invalid IL or missing references) //IL_0580: Unknown result type (might be due to invalid IL or missing references) //IL_0599: Unknown result type (might be due to invalid IL or missing references) //IL_05f4: Unknown result type (might be due to invalid IL or missing references) //IL_060d: Unknown result type (might be due to invalid IL or missing references) ClearViewReferences(); TMP_FontAsset font = FindVanillaFont(); _root = new GameObject("Follower Trait Tree Menu"); Object.DontDestroyOnLoad((Object)(object)_root); Canvas obj = _root.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 20000; CanvasScaler obj2 = _root.AddComponent(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); _root.AddComponent(); AddImage("Shade", _root.transform, new Color(0f, 0f, 0f, 0.52f), AnchorFull()).transform.SetAsFirstSibling(); GameObject val = AddImage("Panel", _root.transform, new Color(0.025f, 0.02f, 0.018f, 0.96f), RectFor(0.08f, 0.055f, 0.84f, 0.89f)); Sprite val2 = FindVanillaPanelSprite(); if ((Object)(object)val2 != (Object)null) { Image component = val.GetComponent(); component.sprite = val2; component.type = (Type)1; } AddImage("Top Rule", val.transform, new Color(0.68f, 0.03f, 0.02f, 1f), RectFor(0f, 0.94f, 1f, 0.012f)); _title = AddText("Title", val.transform, font, 42, (FontStyles)1, new Color(1f, 0.9f, 0.18f, 1f), RectFor(0.03f, 0.9f, 0.35f, 0.07f)); _subtitle = AddText("Subtitle", val.transform, font, 20, (FontStyles)0, Color.white, RectFor(0.03f, 0.855f, 0.62f, 0.04f)); _modeText = AddText("Mode", val.transform, font, 21, (FontStyles)1, Color.white, RectFor(0.72f, 0.9f, 0.25f, 0.055f)); ((TMP_Text)_modeText).alignment = (TextAlignmentOptions)4100; _categoryText = AddText("Category", val.transform, font, 25, (FontStyles)1, new Color(1f, 0.9f, 0.18f, 1f), RectFor(0.36f, 0.57f, 0.34f, 0.055f)); ((TMP_Text)_categoryText).alignment = (TextAlignmentOptions)514; ((TMP_Text)AddText("Follower Label", val.transform, font, 18, (FontStyles)1, new Color(0.8f, 0.75f, 0.68f, 1f), RectFor(0.03f, 0.81f, 0.25f, 0.04f))).text = "Followers"; ((TMP_Text)AddText("Preview Label", val.transform, font, 18, (FontStyles)1, new Color(0.8f, 0.75f, 0.68f, 1f), RectFor(0.32f, 0.81f, 0.4f, 0.04f))).text = "Follower Profile"; ((TMP_Text)AddText("Trait Label", val.transform, font, 18, (FontStyles)1, new Color(0.8f, 0.75f, 0.68f, 1f), RectFor(0.34f, 0.525f, 0.36f, 0.035f))).text = "Traits"; GameObject val3 = AddImage("Follower Preview Frame", val.transform, new Color(0.045f, 0.038f, 0.032f, 0.92f), RectFor(0.3f, 0.625f, 0.44f, 0.18f)); if ((Object)(object)val2 != (Object)null) { Image component2 = val3.GetComponent(); component2.sprite = val2; component2.type = (Type)1; } GameObject val4 = new GameObject("Follower Preview Content"); val4.transform.SetParent(val3.transform, false); RectTransform obj3 = val4.AddComponent(); obj3.anchorMin = new Vector2(0.02f, 0.04f); obj3.anchorMax = new Vector2(0.98f, 0.96f); obj3.offsetMin = Vector2.zero; obj3.offsetMax = Vector2.zero; _previewParent = val4.transform; for (int i = 0; i < 12; i++) { _followerRows.Add(AddRow(val.transform, font, RectFor(0.03f, 0.76f - (float)i * 0.053f, 0.25f, 0.045f))); } for (int j = 0; j < 12; j++) { Image icon; TextMeshProUGUI val5 = AddTraitRow(val.transform, font, RectFor(0.33f, 0.48f - (float)j * 0.035f, 0.38f, 0.031f), out icon); _traitRows.Add(val5); _traitIcons.Add(icon); IndoctrinationTraitItem item = TryAddNativeTraitItem(((TMP_Text)val5).transform.parent); _nativeTraitItems.Add(item); _nativeTraitTypes.Add((TraitType)0); } ((TMP_Text)AddText("Detail Label", val.transform, font, 18, (FontStyles)1, new Color(0.8f, 0.75f, 0.68f, 1f), RectFor(0.77f, 0.81f, 0.2f, 0.04f))).text = "Trait Details"; _detailText = AddText("Details", val.transform, font, 18, (FontStyles)0, Color.white, RectFor(0.77f, 0.22f, 0.2f, 0.58f)); ((TMP_Text)_detailText).alignment = (TextAlignmentOptions)257; ((TMP_Text)_detailText).enableWordWrapping = true; ((TMP_Text)_detailText).overflowMode = (TextOverflowModes)1; _footerText = AddText("Footer", val.transform, font, 18, (FontStyles)1, new Color(0.9f, 0.86f, 0.78f, 1f), RectFor(0.035f, 0.025f, 0.93f, 0.065f)); ((TMP_Text)_footerText).alignment = (TextAlignmentOptions)514; _promptBar = TryBuildVanillaPromptBar(val.transform, font); } private void ClearViewReferences() { _followerRows.Clear(); _traitRows.Clear(); _traitIcons.Clear(); _nativeTraitItems.Clear(); _nativeTraitTypes.Clear(); _promptBar = null; _previewParent = null; _followerPreview = null; _previewFollowerId = -1; _title = null; _subtitle = null; _modeText = null; _categoryText = null; _detailText = null; _footerText = null; } private static TextMeshProUGUI AddRow(Transform parent, TMP_FontAsset font, Vector4 anchors) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) GameObject val = AddImage("Row", parent, new Color(0.04f, 0.035f, 0.03f, 0.72f), anchors); TextMeshProUGUI obj = AddInsetText("Text", val.transform, font, 18, (FontStyles)1, Color.white, 10f, 2f, 10f, 2f); ((TMP_Text)obj).alignment = (TextAlignmentOptions)4097; ((TMP_Text)obj).overflowMode = (TextOverflowModes)0; return obj; } internal static TextMeshProUGUI AddTraitRow(Transform parent, TMP_FontAsset font, Vector4 anchors, out Image icon) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) GameObject val = AddImage("Trait Row", parent, new Color(0.04f, 0.035f, 0.03f, 0.72f), anchors); GameObject val2 = AddImage("Trait Icon", val.transform, Color.white, RectFor(0.018f, 0.1f, 0.12f, 0.8f)); icon = val2.GetComponent(); icon.preserveAspect = true; ((Graphic)icon).raycastTarget = false; TextMeshProUGUI obj = AddInsetText("Text", val.transform, font, 16, (FontStyles)1, Color.white, 58f, 1f, 8f, 1f); ((TMP_Text)obj).alignment = (TextAlignmentOptions)4097; ((TMP_Text)obj).overflowMode = (TextOverflowModes)1; return obj; } private static IndoctrinationTraitItem TryAddNativeTraitItem(Transform parent) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) try { UIManager instance = MonoSingleton.Instance; UIFollowerSummaryMenuController val = (((Object)(object)instance != (Object)null) ? instance.FollowerSummaryMenuTemplate : null); IndoctrinationTraitItem val2 = (IndoctrinationTraitItem)(((Object)(object)val != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val2 == (Object)null) { return null; } IndoctrinationTraitItem val3 = Object.Instantiate(val2, parent, false); ((Object)((Component)val3).gameObject).name = "Native Trait Item"; ((Component)val3).gameObject.SetActive(true); Transform transform = ((Component)val3).transform; RectTransform val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val4 != (Object)null) { val4.anchorMin = new Vector2(0.005f, 0.02f); val4.anchorMax = new Vector2(0.14f, 0.98f); val4.offsetMin = Vector2.zero; val4.offsetMax = Vector2.zero; ((Transform)val4).localScale = Vector3.one; } if ((Object)(object)val3.Button != (Object)null) { ((Selectable)val3.Button).interactable = false; } StripNativeTraitBacking(val3); Graphic[] componentsInChildren = ((Component)val3).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].raycastTarget = false; } return val3; } catch (Exception ex) { FollowerTraitTreePlugin.Log.LogWarning((object)("Could not create native trait item: " + ex.Message)); return null; } } private static void StripNativeTraitBacking(IndoctrinationTraitItem item) { object? obj = AccessTools.Field(typeof(IndoctrinationTraitItem), "_icon")?.GetValue(item); Image val = (Image)((obj is Image) ? obj : null); object? obj2 = AccessTools.Field(typeof(IndoctrinationTraitItem), "_arrow")?.GetValue(item); Image val2 = (Image)((obj2 is Image) ? obj2 : null); object? obj3 = AccessTools.Field(typeof(IndoctrinationTraitItem), "manipulationShuffle")?.GetValue(item); GameObject val3 = (GameObject)((obj3 is GameObject) ? obj3 : null); object? obj4 = AccessTools.Field(typeof(IndoctrinationTraitItem), "manipulationAdd")?.GetValue(item); GameObject val4 = (GameObject)((obj4 is GameObject) ? obj4 : null); object? obj5 = AccessTools.Field(typeof(IndoctrinationTraitItem), "manipulationMinus")?.GetValue(item); GameObject val5 = (GameObject)((obj5 is GameObject) ? obj5 : null); Image[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); foreach (Image val6 in componentsInChildren) { if (!((Object)(object)val6 == (Object)(object)val) && !((Object)(object)val6 == (Object)(object)val2) && (!((Object)(object)val3 != (Object)null) || !((Component)val6).transform.IsChildOf(val3.transform)) && (!((Object)(object)val4 != (Object)null) || !((Component)val6).transform.IsChildOf(val4.transform)) && (!((Object)(object)val5 != (Object)null) || !((Component)val6).transform.IsChildOf(val5.transform))) { ((Behaviour)val6).enabled = false; } } } internal static TextMeshProUGUI AddText(string name, Transform parent, TMP_FontAsset font, int size, FontStyles style, Color color, Vector4 anchors) { //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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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) //IL_0047: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); ApplyAnchors(val.AddComponent(), anchors); TextMeshProUGUI val2 = val.AddComponent(); if ((Object)(object)font != (Object)null) { ((TMP_Text)val2).font = font; } ((TMP_Text)val2).fontSize = size; ((TMP_Text)val2).fontStyle = style; ((Graphic)val2).color = color; ((TMP_Text)val2).alignment = (TextAlignmentOptions)4097; ((Graphic)val2).raycastTarget = false; return val2; } internal static TextMeshProUGUI AddInsetText(string name, Transform parent, TMP_FontAsset font, int size, FontStyles style, Color color, float left, float bottom, float right, float top) { //IL_0004: 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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI obj = AddText(name, parent, font, size, style, color, AnchorFull()); RectTransform rectTransform = ((TMP_Text)obj).rectTransform; rectTransform.offsetMin = new Vector2(left, bottom); rectTransform.offsetMax = new Vector2(0f - right, 0f - top); return obj; } internal static GameObject AddImage(string name, Transform parent, Color color, Vector4 anchors) { //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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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) //IL_002c: Expected O, but got Unknown GameObject val = new GameObject(name); val.transform.SetParent(parent, false); ApplyAnchors(val.AddComponent(), anchors); ((Graphic)val.AddComponent()).color = color; return val; } internal static Vector4 AnchorFull() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) return new Vector4(0f, 0f, 1f, 1f); } internal static TMP_FontAsset FindVanillaFont() { try { UIManager instance = MonoSingleton.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.FollowerSelectMenuTemplate != (Object)null) { TMP_Text componentInChildren = ((Component)instance.FollowerSelectMenuTemplate).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { return componentInChildren.font; } } } catch { } return TMP_Settings.defaultFontAsset; } internal static Sprite FindVanillaPanelSprite() { try { UIManager instance = MonoSingleton.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.ConfirmationWindowTemplate == (Object)null) { return null; } Image val = ((IEnumerable)((Component)instance.ConfirmationWindowTemplate).GetComponentsInChildren(true)).FirstOrDefault((Func)((Image image) => (Object)(object)image != (Object)null && (Object)(object)image.sprite != (Object)null && (((Object)image).name.IndexOf("background", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)image).name.IndexOf("backing", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)image).name.IndexOf("panel", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)image).name.IndexOf("window", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)image).name.IndexOf("brush", StringComparison.OrdinalIgnoreCase) >= 0))); if ((Object)(object)val != (Object)null) { return val.sprite; } return null; } catch { return null; } } internal static Vector4 RectFor(float x, float y, float width, float height) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return new Vector4(x, y, x + width, y + height); } internal static void ApplyAnchors(RectTransform rect, Vector4 anchors) { //IL_0001: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = new Vector2(anchors.x, anchors.y); rect.anchorMax = new Vector2(anchors.z, anchors.w); rect.offsetMin = Vector2.zero; rect.offsetMax = Vector2.zero; } private static GameObject TryBuildVanillaPromptBar(Transform parent, TMP_FontAsset font) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) try { UIManager instance = MonoSingleton.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.FollowerSelectMenuTemplate == (Object)null) { return null; } MMControlPrompt val = ((Component)instance.FollowerSelectMenuTemplate).GetComponentsInChildren(true).FirstOrDefault(); if ((Object)(object)val == (Object)null) { return null; } GameObject val2 = AddImage("Vanilla Control Prompts", parent, Color.clear, RectFor(0.035f, 0.018f, 0.93f, 0.075f)); ((Graphic)val2.GetComponent()).raycastTarget = false; HorizontalLayoutGroup obj = val2.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = 18f; ((LayoutGroup)obj).childAlignment = (TextAnchor)4; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; AddPrompt(val, val2.transform, font, 38, "Choose / Toggle", 220f); AddPrompt(val, val2.transform, font, 39, "Back", 135f); AddPrompt(val, val2.transform, font, 43, "Previous", 175f); AddPrompt(val, val2.transform, font, 44, "Next", 145f); return val2; } catch (Exception ex) { FollowerTraitTreePlugin.Log.LogWarning((object)("Trait Tree could not create vanilla control prompts: " + ex.Message)); return null; } } internal static GameObject AddPrompt(MMControlPrompt prototype, Transform parent, TMP_FontAsset font, int action, string label, float width, int category = 1) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Trait Tree Prompt Item " + action); val.transform.SetParent(parent, false); val.AddComponent(); LayoutElement obj = val.AddComponent(); obj.preferredWidth = width; obj.preferredHeight = 62f; HorizontalLayoutGroup obj2 = val.AddComponent(); ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 8f; ((LayoutGroup)obj2).childAlignment = (TextAnchor)3; ((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; MMControlPrompt val2 = Object.Instantiate(prototype, val.transform, false); ((Object)((Component)val2).gameObject).name = "Trait Tree Prompt " + action; ((Component)val2).gameObject.SetActive(false); Button[] componentsInChildren = ((Component)val2).GetComponentsInChildren