Decompiled source of FollowerTraitTree v0.5.3

plugins/FollowerTraitTree.dll

Decompiled 4 days ago
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<TYPES> _treeTypes = new HashSet<TYPES>();

		private static readonly HashSet<TraitType> UnsafeTraits = new HashSet<TraitType>
		{
			(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<TraitType> RepairTraits = new HashSet<TraitType>
		{
			(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<TraitType> VisualStateTraits = new HashSet<TraitType>
		{
			(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<TraitProfilePromptMarker>() == (Object)null || ((Interaction)interaction).SecondaryLabel != "View Follower Profile" || !CanOpenFollowerProfile(interaction))
			{
				return false;
			}
			if ((Object)(object)MonoSingleton<UIManager>.Instance == (Object)null || (Object)(object)MonoSingleton<UIManager>.Instance.FollowerSummaryMenuTemplate == (Object)null)
			{
				return false;
			}
			PlayerFarming val = (((Object)(object)state != (Object)null) ? ((Component)state).GetComponent<PlayerFarming>() : PlayerFarming.Instance);
			((Interaction)interaction).EndIndicateHighlighted(val);
			BeginMenuSession(val);
			_followerSummaryMenu = MonoSingleton<UIManager>.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<TraitProfilePromptMarker>();
			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<TraitProfilePromptMarker>();
			}
			((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<TraitTreeInteraction>();
					if ((Object)(object)traitTreeInteraction == (Object)null)
					{
						traitTreeInteraction = ((Component)val).gameObject.AddComponent<TraitTreeInteraction>();
					}
					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<TYPES>(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<FollowerInfo>)DataManager.Instance.Followers).FirstOrDefault((Func<FollowerInfo, bool>)((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<TraitType>();
			}
			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<TraitType, TraitType> 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>() : PlayerFarming.Instance);
			}
		}
	}
	internal sealed class TraitTreeMenu
	{
		private enum ScreenState
		{
			Followers,
			Traits
		}

		private readonly FollowerTraitTreePlugin _plugin;

		private readonly KeyCode _repairKey;

		private readonly List<FollowerInfo> _followers = new List<FollowerInfo>();

		private readonly List<TraitType> _traits = new List<TraitType>();

		private readonly List<TextMeshProUGUI> _followerRows = new List<TextMeshProUGUI>();

		private readonly List<TextMeshProUGUI> _traitRows = new List<TextMeshProUGUI>();

		private readonly List<Image> _traitIcons = new List<Image>();

		private readonly List<IndoctrinationTraitItem> _nativeTraitItems = new List<IndoctrinationTraitItem>();

		private readonly List<TraitType> _nativeTraitTypes = new List<TraitType>();

		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<FollowerInfo> 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<TraitType> 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<TraitType>() : 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<Image>()).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<Image>()).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<UIManager>.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<FollowerInformationBox>(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<Graphic>(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<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 20000;
			CanvasScaler obj2 = _root.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			_root.AddComponent<GraphicRaycaster>();
			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<Image>();
				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<Image>();
				component2.sprite = val2;
				component2.type = (Type)1;
			}
			GameObject val4 = new GameObject("Follower Preview Content");
			val4.transform.SetParent(val3.transform, false);
			RectTransform obj3 = val4.AddComponent<RectTransform>();
			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<Image>();
			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<UIManager>.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<IndoctrinationTraitItem>(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<Graphic>(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<Image>(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<RectTransform>(), anchors);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			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<RectTransform>(), anchors);
			((Graphic)val.AddComponent<Image>()).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<UIManager>.Instance;
				if ((Object)(object)instance != (Object)null && (Object)(object)instance.FollowerSelectMenuTemplate != (Object)null)
				{
					TMP_Text componentInChildren = ((Component)instance.FollowerSelectMenuTemplate).GetComponentInChildren<TMP_Text>(true);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						return componentInChildren.font;
					}
				}
			}
			catch
			{
			}
			return TMP_Settings.defaultFontAsset;
		}

		internal static Sprite FindVanillaPanelSprite()
		{
			try
			{
				UIManager instance = MonoSingleton<UIManager>.Instance;
				if ((Object)(object)instance == (Object)null || (Object)(object)instance.ConfirmationWindowTemplate == (Object)null)
				{
					return null;
				}
				Image val = ((IEnumerable<Image>)((Component)instance.ConfirmationWindowTemplate).GetComponentsInChildren<Image>(true)).FirstOrDefault((Func<Image, bool>)((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<UIManager>.Instance;
				if ((Object)(object)instance == (Object)null || (Object)(object)instance.FollowerSelectMenuTemplate == (Object)null)
				{
					return null;
				}
				MMControlPrompt val = ((Component)instance.FollowerSelectMenuTemplate).GetComponentsInChildren<MMControlPrompt>(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<Image>()).raycastTarget = false;
				HorizontalLayoutGroup obj = val2.AddComponent<HorizontalLayoutGroup>();
				((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<RectTransform>();
			LayoutElement obj = val.AddComponent<LayoutElement>();
			obj.preferredWidth = width;
			obj.preferredHeight = 62f;
			HorizontalLayoutGroup obj2 = val.AddComponent<HorizontalLayoutGroup>();
			((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<MMControlPrompt>(prototype, val.transform, false);
			((Object)((Component)val2).gameObject).name = "Trait Tree Prompt " + action;
			((Component)val2).gameObject.SetActive(false);
			Button[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Button>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				((UnityEventBase)componentsInChildren[i].onClick).RemoveAllListeners();
			}
			LayoutElement val3 = ((Component)val2).GetComponent<LayoutElement>();
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = ((Component)val2).gameObject.AddComponent<LayoutElement>();
			}
			val3.preferredWidth = 58f;
			val3.preferredHeight = 62f;
			val3.flexibleWidth = 0f;
			val2.Category = category;
			val2.Action = action;
			val2.playerFarming = PlayerFarming.Instance;
			object? obj3 = AccessTools.Field(typeof(MMControlPrompt), "_actionText")?.GetValue(val2);
			TMP_Text val4 = (TMP_Text)((obj3 is TMP_Text) ? obj3 : null);
			if ((Object)(object)val4 != (Object)null && val4.transform.IsChildOf(((Component)val2).transform))
			{
				((Component)val4).gameObject.SetActive(false);
			}
			TextMeshProUGUI obj4 = AddText("Prompt Label", val.transform, font, 18, (FontStyles)1, new Color(0.9f, 0.86f, 0.78f, 1f), AnchorFull());
			((TMP_Text)obj4).text = label;
			((TMP_Text)obj4).alignment = (TextAlignmentOptions)4097;
			((TMP_Text)obj4).enableWordWrapping = false;
			((TMP_Text)obj4).overflowMode = (TextOverflowModes)1;
			LayoutElement obj5 = ((Component)obj4).gameObject.AddComponent<LayoutElement>();
			obj5.preferredWidth = Mathf.Max(60f, width - 66f);
			obj5.preferredHeight = 62f;
			obj5.flexibleWidth = 0f;
			((Component)val2).gameObject.SetActive(true);
			val2.ForceUpdate();
			return val;
		}

		private int GetMove()
		{
			//IL_0017: 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)
			float num = 0f;
			try
			{
				num = InputManager.UI.GetVerticalAxis((PlayerFarming)null);
			}
			catch
			{
			}
			if (Input.mouseScrollDelta.y > 0.1f)
			{
				return -1;
			}
			if (Input.mouseScrollDelta.y < -0.1f)
			{
				return 1;
			}
			if (Input.GetKeyDown((KeyCode)273) || Input.GetKeyDown((KeyCode)119))
			{
				return -1;
			}
			if (Input.GetKeyDown((KeyCode)274) || Input.GetKeyDown((KeyCode)115))
			{
				return 1;
			}
			if (Mathf.Abs(num) < 0.45f)
			{
				_nextMove = 0f;
				return 0;
			}
			if (Time.unscaledTime < _nextMove)
			{
				return 0;
			}
			_nextMove = Time.unscaledTime + 0.18f;
			if (!(num > 0f))
			{
				return 1;
			}
			return -1;
		}

		private bool RepairPressed()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return Input.GetKeyDown(_repairKey);
		}

		private static bool AcceptPressed()
		{
			try
			{
				if (InputManager.UI.GetAcceptButtonDown((PlayerFarming)null))
				{
					return true;
				}
			}
			catch
			{
			}
			if (!Input.GetKeyDown((KeyCode)13))
			{
				return Input.GetKeyDown((KeyCode)32);
			}
			return true;
		}

		private static bool CancelPressed()
		{
			try
			{
				if (InputManager.UI.GetCancelButtonDown((PlayerFarming)null))
				{
					return true;
				}
			}
			catch
			{
			}
			if (!Input.GetKeyDown((KeyCode)27))
			{
				return Input.GetKeyDown((KeyCode)8);
			}
			return true;
		}

		private static bool PageLeftPressed()
		{
			try
			{
				if (InputManager.UI.GetPageNavigateLeftDown((PlayerFarming)null))
				{
					return true;
				}
			}
			catch
			{
			}
			if (!Input.GetKeyDown((KeyCode)276))
			{
				return Input.GetKeyDown((KeyCode)113);
			}
			return true;
		}

		private static bool PageRightPressed()
		{
			try
			{
				if (InputManager.UI.GetPageNavigateRightDown((PlayerFarming)null))
				{
					return true;
				}
			}
			catch
			{
			}
			if (!Input.GetKeyDown((KeyCode)275))
			{
				return Input.GetKeyDown((KeyCode)101);
			}
			return true;
		}
	}
	internal sealed class FollowerProfilePanel
	{
		private readonly FollowerTraitTreePlugin _plugin;

		private readonly List<TextMeshProUGUI> _traitRows = new List<TextMeshProUGUI>();

		private readonly List<Image> _traitIcons = new List<Image>();

		private readonly List<TraitType> _traits = new List<TraitType>();

		private GameObject _root;

		private FollowerInfo _follower;

		private TextMeshProUGUI _nameText;

		private TextMeshProUGUI _metaText;

		private TextMeshProUGUI _statsText;

		private TextMeshProUGUI _statusText;

		private TextMeshProUGUI _traitHeader;

		private int _traitTop;

		private float _nextMove;

		private float _ignoreInputUntil;

		internal bool IsOpen
		{
			get
			{
				if ((Object)(object)_root != (Object)null)
				{
					return _root.activeSelf;
				}
				return false;
			}
		}

		internal FollowerProfilePanel(FollowerTraitTreePlugin plugin)
		{
			_plugin = plugin;
		}

		internal void Open(FollowerInfo follower)
		{
			_follower = follower;
			_traitTop = 0;
			if ((Object)(object)_root == (Object)null)
			{
				Build();
			}
			_root.SetActive(true);
			_ignoreInputUntil = Time.unscaledTime + 0.15f;
			Refresh();
		}

		internal void Close()
		{
			if ((Object)(object)_root != (Object)null)
			{
				GameObject root = _root;
				_root = null;
				_traitRows.Clear();
				_traitIcons.Clear();
				Object.Destroy((Object)(object)root);
			}
			_follower = null;
			_plugin.OnMenuClosed();
		}

		internal void HandleInput()
		{
			if (Time.unscaledTime < _ignoreInputUntil)
			{
				return;
			}
			bool flag = false;
			try
			{
				flag = InputManager.Gameplay.GetInteract2ButtonDown((PlayerFarming)null);
			}
			catch
			{
			}
			if (CancelPressed() || Input.GetMouseButtonDown(1) || flag)
			{
				Close();
				return;
			}
			int move = GetMove();
			if (move != 0)
			{
				_traitTop = Mathf.Clamp(_traitTop + move, 0, Mathf.Max(0, _traits.Count - _traitRows.Count));
				RefreshRows();
			}
		}

		private void Refresh()
		{
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null || _follower == null)
			{
				return;
			}
			FollowerInfo infoByID = FollowerInfo.GetInfoByID(_follower.ID, true);
			if (infoByID != null)
			{
				_follower = infoByID;
			}
			_traits.Clear();
			if (_follower.Traits != null)
			{
				_traits.AddRange(_follower.Traits.Where((TraitType trait) => (int)trait > 0).Distinct().OrderBy(FollowerTraitTreePlugin.TraitTitle));
			}
			((TMP_Text)_nameText).text = _follower.Name;
			((TMP_Text)_metaText).text = "Level " + _follower.XPLevel + "   |   Age " + _follower.Age + "   |   Joined Day " + _follower.DayJoined;
			((TMP_Text)_statsText).text = "Faith  " + Mathf.RoundToInt(_follower.Faith) + "     Happiness  " + Mathf.RoundToInt(_follower.Happiness) + "\nAdoration  " + Mathf.RoundToInt(_follower.Adoration) + "/100     Pleasure  " + _follower.Pleasure + "/65";
			List<string> list = new List<string>();
			if (_follower.IsDisciple)
			{
				list.Add("Disciple");
			}
			if (_follower.MarriedToLeader)
			{
				list.Add("Married");
			}
			if (_follower.OldAge)
			{
				list.Add("Elder");
			}
			if ((int)_follower.CursedState != 0)
			{
				list.Add(((object)Unsafe.As<Thought, Thought>(ref _follower.CursedState)/*cast due to .constrained prefix*/).ToString());
			}
			((TMP_Text)_statusText).text = ((list.Count == 0) ? "Cult Follower" : string.Join("  |  ", list.ToArray()));
			RefreshRows();
		}

		private void RefreshRows()
		{
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_traitHeader != (Object)null)
			{
				int num = ((_traits.Count != 0) ? (_traitTop + 1) : 0);
				int num2 = Mathf.Min(_traits.Count, _traitTop + _traitRows.Count);
				((TMP_Text)_traitHeader).text = ((_traits.Count == 0) ? "Traits (0)" : ("Traits (" + _traits.Count + ")                         " + num + "-" + num2));
			}
			for (int i = 0; i < _traitRows.Count; i++)
			{
				int num3 = _traitTop + i;
				TextMeshProUGUI val = _traitRows[i];
				Image val2 = _traitIcons[i];
				if (num3 >= _traits.Count)
				{
					((TMP_Text)val).text = "";
					((Component)((TMP_Text)val).transform.parent).gameObject.SetActive(false);
					((Component)val2).gameObject.SetActive(false);
					continue;
				}
				((Component)((TMP_Text)val).transform.parent).gameObject.SetActive(true);
				TraitType val3 = _traits[num3];
				((TMP_Text)val).text = FollowerTraitTreePlugin.TraitTitle(val3);
				((Graphic)val).color = (Color)(FollowerTraitTreePlugin.IsUnsafeTrait(val3) ? new Color(1f, 0.62f, 0.48f, 1f) : Color.white);
				Sprite val4 = null;
				try
				{
					val4 = FollowerTrait.GetIcon(val3);
				}
				catch
				{
				}
				val2.sprite = val4;
				((Graphic)val2).color = Color.white;
				((Component)val2).gameObject.SetActive((Object)(object)val4 != (Object)null);
			}
		}

		private void Build()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: 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_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			TMP_FontAsset font = TraitTreeMenu.FindVanillaFont();
			_root = new GameObject("Follower Profile Panel");
			Object.DontDestroyOnLoad((Object)(object)_root);
			Canvas obj = _root.AddComponent<Canvas>();
			obj.renderMode = (RenderMode)0;
			obj.sortingOrder = 20001;
			CanvasScaler obj2 = _root.AddComponent<CanvasScaler>();
			obj2.uiScaleMode = (ScaleMode)1;
			obj2.referenceResolution = new Vector2(1920f, 1080f);
			_root.AddComponent<GraphicRaycaster>();
			GameObject val = TraitTreeMenu.AddImage("Profile Panel", _root.transform, new Color(0.025f, 0.02f, 0.018f, 0.97f), TraitTreeMenu.RectFor(0.665f, 0.07f, 0.31f, 0.86f));
			Sprite val2 = TraitTreeMenu.FindVanillaPanelSprite();
			if ((Object)(object)val2 != (Object)null)
			{
				Image component = val.GetComponent<Image>();
				component.sprite = val2;
				component.type = (Type)1;
			}
			TraitTreeMenu.AddImage("Top Rule", val.transform, new Color(0.68f, 0.03f, 0.02f, 1f), TraitTreeMenu.RectFor(0f, 0.955f, 1f, 0.012f));
			((TMP_Text)TraitTreeMenu.AddText("Profile Title", val.transform, font, 20, (FontStyles)1, new Color(0.8f, 0.75f, 0.68f, 1f), TraitTreeMenu.RectFor(0.055f, 0.905f, 0.89f, 0.045f))).text = "Follower Profile";
			_nameText = TraitTreeMenu.AddText("Follower Name", val.transform, font, 36, (FontStyles)1, new Color(1f, 0.9f, 0.18f, 1f), TraitTreeMenu.RectFor(0.055f, 0.845f, 0.89f, 0.065f));
			_metaText = TraitTreeMenu.AddText("Follower Meta", val.transform, font, 17, (FontStyles)0, Color.white, TraitTreeMenu.RectFor(0.055f, 0.795f, 0.89f, 0.045f));
			_statsText = TraitTreeMenu.AddText("Follower Stats", val.transform, font, 18, (FontStyles)1, new Color(0.9f, 0.86f, 0.78f, 1f), TraitTreeMenu.RectFor(0.055f, 0.705f, 0.89f, 0.085f));
			((TMP_Text)_statsText).alignment = (TextAlignmentOptions)257;
			_statusText = TraitTreeMenu.AddText("Follower Status", val.transform, font, 17, (FontStyles)1, new Color(0.62f, 1f, 0.72f, 1f), TraitTreeMenu.RectFor(0.055f, 0.655f, 0.89f, 0.045f));
			_traitHeader = TraitTreeMenu.AddText("Trait Header", val.transform, font, 19, (FontStyles)1, new Color(0.8f, 0.75f, 0.68f, 1f), TraitTreeMenu.RectFor(0.055f, 0.605f, 0.89f, 0.04f));
			for (int i = 0; i < 10; i++)
			{
				Image icon;
				TextMeshProUGUI item = TraitTreeMenu.AddTraitRow(val.transform, font, TraitTreeMenu.RectFor(0.055f, 0.552f - (float)i * 0.051f, 0.89f, 0.043f), out icon);
				_traitRows.Add(item);
				_traitIcons.Add(icon);
			}
			TryBuildClosePrompt(val.transform, font);
		}

		private static void TryBuildClosePrompt(Transform parent, TMP_FontAsset font)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				UIManager instance = MonoSingleton<UIManager>.Instance;
				MMControlPrompt val = (((Object)(object)instance != (Object)null && (Object)(object)instance.FollowerSelectMenuTemplate != (Object)null) ? ((Component)instance.FollowerSelectMenuTemplate).GetComponentsInChildren<MMControlPrompt>(true).FirstOrDefault() : null);
				if (!((Object)(object)val == (Object)null))
				{
					GameObject val2 = TraitTreeMenu.AddImage("Profile Prompt", parent, Color.clear, TraitTreeMenu.RectFor(0.055f, 0.018f, 0.89f, 0.07f));
					((Graphic)val2.GetComponent<Image>()).raycastTarget = false;
					HorizontalLayoutGroup obj = val2.AddComponent<HorizontalLayoutGroup>();
					((LayoutGroup)obj).childAlignment = (TextAnchor)5;
					((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true;
					((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true;
					((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false;
					((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false;
					TraitTreeMenu.AddPrompt(val, val2.transform, font, 68, "Close Profile", 210f, 0);
				}
			}
			catch (Exception ex)
			{
				FollowerTraitTreePlugin.Log.LogWarning((object)("Trait Tree could not create the profile close prompt: " + ex.Message));
			}
		}

		private int GetMove()
		{
			//IL_0000: 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)
			if (Input.mouseScrollDelta.y > 0.1f)
			{
				return -1;
			}
			if (Input.mouseScrollDelta.y < -0.1f)
			{
				return 1;
			}
			if (Input.GetKeyDown((KeyCode)273) || Input.GetKeyDown((KeyCode)119))
			{
				return -1;
			}
			if (Input.GetKeyDown((KeyCode)274) || Input.GetKeyDown((KeyCode)115))
			{
				return 1;
			}
			float num = 0f;
			try
			{
				num = InputManager.UI.GetVerticalAxis((PlayerFarming)null);
			}
			catch
			{
			}
			if (Mathf.Abs(num) < 0.45f)
			{
				_nextMove = 0f;
				return 0;
			}
			if (Time.unscaledTime < _nextMove)
			{
				return 0;
			}
			_nextMove = Time.unscaledTime + 0.18f;
			if (!(num > 0f))
			{
				return 1;
			}
			return -1;
		}

		private static bool CancelPressed()
		{
			try
			{
				if (InputManager.UI.GetCancelButtonDown((PlayerFarming)null))
				{
					return true;
				}
			}
			catch
			{
			}
			if (!Input.GetKeyDown((KeyCode)27))
			{
				return Input.GetKeyDown((KeyCode)8);
			}
			return true;
		}
	}
	internal sealed class TraitProfilePromptMarker : MonoBehaviour
	{
	}
	[HarmonyPatch(typeof(interaction_FollowerInteraction), "GetLabel")]
	internal static class FollowerProfileLabelPatch
	{
		private static void Postfix(interaction_FollowerInteraction __instance)
		{
			FollowerTraitTreePlugin.Instance?.ConfigureFollowerProfilePrompt(__instance);
		}
	}
	[HarmonyPatch(typeof(Interaction), "OnSecondaryInteract")]
	internal static class FollowerProfileSecondaryInteractionPatch
	{
		private static bool Prefix(Interaction __instance, StateMachine state)
		{
			interaction_FollowerInteraction val = (interaction_FollowerInteraction)(object)((__instance is interaction_FollowerInteraction) ? __instance : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			FollowerTraitTreePlugin instance = FollowerTraitTreePlugin.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				return !instance.TryOpenFollowerProfile(val, state);
			}
			return true;
		}
	}
	internal static class TraitTreeConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<string> OpenKey;

		internal static ConfigEntry<string> RepairKey;

		internal static ConfigEntry<bool> EnableTreeInteraction;

		internal static ConfigEntry<bool> UnlockCrystalTree;

		internal static ConfigEntry<bool> EnableFollowerProfiles;

		internal static ConfigEntry<string> TreeStructureTypes;

		internal static ConfigEntry<float> InteractionRadius;

		internal static ConfigEntry<bool> AutoSaveAfterChange;

		internal static ConfigEntry<bool> RepairLegacySozoOnLoad;

		internal static void Bind(ConfigFile config)
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Follower Trait Tree.");
			OpenKey = config.Bind<string>("Controls", "OpenKey", "F6", "Fallback keyboard KeyCode used to open the trait tree menu.");
			RepairKey = config.Bind<string>("Controls", "RepairKey", "F2", "Fallback keyboard KeyCode used to repair interaction-blocking state traits on the selected follower.");
			EnableTreeInteraction = config.Bind<bool>("Trait Tree", "EnableTreeInteraction", true, "Turn the Crystal Tree decoration into an interactable Trait Tree.");
			UnlockCrystalTree = config.Bind<bool>("Trait Tree", "UnlockCrystalTree", true, "Unlock and reveal the Crystal Tree decoration while this mod is installed.");
			EnableFollowerProfiles = config.Bind<bool>("Follower Profiles", "Enabled", true, "Add View Follower Profile to the unused secondary follower interaction.");
			TreeStructureTypes = config.Bind<string>("Trait Tree", "TreeStructureTypes", "DECORATION_CRYSTAL_TREE", "Comma-separated StructureBrain.TYPES values that should behave as Trait Trees.");
			InteractionRadius = config.Bind<float>("Trait Tree", "InteractionRadius", 2.5f, new ConfigDescription("Vanilla interaction distance for the Trait Tree.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 6f), Array.Empty<object>()));
			AutoSaveAfterChange = config.Bind<bool>("Safety", "AutoSaveAfterChange", true, "Call SaveAndLoad.Save after each trait add/remove.");
			RepairLegacySozoOnLoad = config.Bind<bool>("Safety", "RepairLegacySozoOnLoad", true, "Repair incompatible state traits that Follower Trait Tree v0.1.0 may have assigned to Dr. Sozo.");
			if (string.Equals(TreeStructureTypes.Value, "DECORATION_TREE,DECORATION_CRYSTAL_TREE,DECORATION_CHRISTMAS_TREE,DECORATION_DLC_WOOLHAVEN_TREE,DECORATION_DLC_YNGYA_TREEPOT", StringComparison.OrdinalIgnoreCase))
			{
				TreeStructureTypes.Value = "DECORATION_CRYSTAL_TREE";
			}
		}
	}
}