Decompiled source of MoreSkillTrees v1.1.0
BepInEx/plugins/MoreSkillTrees.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Pigeon.Math; using Pigeon.Movement; using Pigeon.UI; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Sparroh")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: AssemblyProduct("MoreSkillTrees")] [assembly: AssemblyTitle("MoreSkillTrees")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] [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 MoreSkillTrees { [HarmonyPatch(typeof(AllSkillTreesWindow))] internal static class AllSkillTreesWindowPatches { [HarmonyPrefix] [HarmonyPatch("OnOpen")] private static bool OnOpen_Prefix(AllSkillTreesWindow __instance) { try { if (!GearSkillTreeController.IsOurWindow(__instance)) { return true; } ((Component)__instance).GetComponent<GearSkillTreeController>()?.HandleOpen(); return false; } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[MoreSkillTrees] AllSkillTreesWindow.OnOpen prefix failed: {arg}"); } return true; } } [HarmonyPrefix] [HarmonyPatch("Update")] private static bool Update_Prefix(AllSkillTreesWindow __instance) { return !GearSkillTreeController.IsOurWindow(__instance); } [HarmonyPrefix] [HarmonyPatch("SetupTree")] private static bool SetupTree_Prefix(AllSkillTreesWindow __instance) { return !GearSkillTreeController.IsOurWindow(__instance); } [HarmonyPrefix] [HarmonyPatch("MoveLeft")] private static bool MoveLeft_Prefix(AllSkillTreesWindow __instance) { try { if (!GearSkillTreeController.IsOurWindow(__instance)) { return true; } ((Component)__instance).GetComponent<GearSkillTreeController>()?.MoveLeft(); return false; } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[MoreSkillTrees] MoveLeft prefix failed: {arg}"); } return true; } } [HarmonyPrefix] [HarmonyPatch("MoveRight")] private static bool MoveRight_Prefix(AllSkillTreesWindow __instance) { try { if (!GearSkillTreeController.IsOurWindow(__instance)) { return true; } ((Component)__instance).GetComponent<GearSkillTreeController>()?.MoveRight(); return false; } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[MoreSkillTrees] MoveRight prefix failed: {arg}"); } return true; } } [HarmonyPrefix] [HarmonyPatch("OnEnable")] private static bool OnEnable_Prefix(AllSkillTreesWindow __instance) { return !GearSkillTreeController.IsOurWindow(__instance); } [HarmonyPrefix] [HarmonyPatch("OnDisable")] private static bool OnDisable_Prefix(AllSkillTreesWindow __instance) { return !GearSkillTreeController.IsOurWindow(__instance); } } [HarmonyPatch(typeof(GearData), "AddXP")] internal static class GearDataAddXPPatch { private static void Prefix(GearData __instance, out int __state) { __state = __instance.Level; } private static void Postfix(GearData __instance, int __state) { try { int level = __instance.Level; if (level <= __state) { return; } IUpgradable gear = __instance.Gear; if (gear == null || gear is Character || (Object)(object)gear.Info == (Object)null || !gear.Info.CanGainXP) { return; } int num = level - __state; int num2 = 0; if (level <= __instance.MaxLevel) { num2 = ((level > 10) ? (num * 2) : num); } if (num2 > 0 && PlayerData.Instance != null && !((Object)(object)Global.Instance == (Object)null)) { PlayerData.Instance.AddResource(Global.Instance.SkillPointResource, num2, true); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)($"[MoreSkillTrees] {gear.Info.Name} leveled {__state}->{level}, " + $"granted {num2} skill point(s).")); } } } catch (Exception arg) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)$"[MoreSkillTrees] AddXP postfix failed: {arg}"); } } } } [HarmonyPatch(typeof(GearDetailsWindow))] internal static class GearDetailsWindowPatches { private static readonly FieldInfo SkillTreeButtonField = AccessTools.Field(typeof(GearDetailsWindow), "skillTreeButton"); private static readonly FieldInfo SkillTreePointsTextField = AccessTools.Field(typeof(GearDetailsWindow), "skillTreePointsText"); [HarmonyPostfix] [HarmonyPatch("Setup")] private static void Setup_Postfix(GearDetailsWindow __instance, IUpgradable upgradable) { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) try { if (upgradable is Character) { return; } object? obj = SkillTreeButtonField?.GetValue(__instance); Component val = (Component)((obj is Component) ? obj : null); object? obj2 = SkillTreePointsTextField?.GetValue(__instance); Component val2 = (Component)((obj2 is Component) ? obj2 : null); bool flag = MoreSkillTreeData.HasTree(upgradable); if ((Object)(object)val != (Object)null) { val.gameObject.SetActive(flag); } if (!flag) { if ((Object)(object)val2 != (Object)null) { val2.gameObject.SetActive(false); } return; } int resource = PlayerData.Instance.GetResource(Global.Instance.SkillPointResource); bool flag2 = resource > 0 && HasAnyUnclaimedNode(upgradable); if ((Object)(object)val2 != (Object)null) { TextMeshProUGUI component = val2.GetComponent<TextMeshProUGUI>(); if ((Object)(object)component != (Object)null) { if (flag2) { Color uIColor = Global.UIColor; ((Graphic)component).color = uIColor; ((TMP_Text)component).text = ((resource == 1) ? string.Format("{0} {1}", resource, TextBlocks.GetString("skillpoint", 0)) : string.Format("{0} {1}", resource, TextBlocks.GetString("skillpoints"))); ((Component)component).gameObject.SetActive(true); } else { ((Component)component).gameObject.SetActive(false); } } } if (!((Object)(object)val != (Object)null)) { return; } Graphic[] componentsInChildren = val.GetComponentsInChildren<Graphic>(true); foreach (Graphic val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null)) { if (flag2 && (Object)(object)Global.Instance.UIShimmerClipMat != (Object)null) { val3.material = Global.Instance.UIShimmerClipMat; } else { val3.material = null; } break; } } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[MoreSkillTrees] GearDetails Setup postfix failed: {arg}"); } } } [HarmonyPostfix] [HarmonyPatch("ToggleSkillAndCraftingUI")] private static void ToggleSkillAndCraftingUI_Postfix(GearDetailsWindow __instance, bool enable) { try { IUpgradable upgradablePrefab = __instance.UpgradablePrefab; if (!(upgradablePrefab is Character) && upgradablePrefab != null) { object? obj = SkillTreeButtonField?.GetValue(__instance); Component val = (Component)((obj is Component) ? obj : null); object? obj2 = SkillTreePointsTextField?.GetValue(__instance); Component val2 = (Component)((obj2 is Component) ? obj2 : null); bool flag = enable && MoreSkillTreeData.HasTree(upgradablePrefab); if ((Object)(object)val != (Object)null) { val.gameObject.SetActive(flag); } if ((Object)(object)val2 != (Object)null) { int resource = PlayerData.Instance.GetResource(Global.Instance.SkillPointResource); bool active = flag && resource > 0 && HasAnyUnclaimedNode(upgradablePrefab); val2.gameObject.SetActive(active); } } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[MoreSkillTrees] ToggleSkillAndCraftingUI postfix failed: {arg}"); } } } [HarmonyPrefix] [HarmonyPatch("ShowSkillTree")] private static bool ShowSkillTree_Prefix(GearDetailsWindow __instance) { try { IUpgradable upgradablePrefab = __instance.UpgradablePrefab; if (upgradablePrefab is Character) { return true; } if (!MoreSkillTreeData.HasTree(upgradablePrefab)) { return false; } GearSkillTreeController.Open(__instance, upgradablePrefab); return false; } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[MoreSkillTrees] ShowSkillTree prefix failed: {arg}"); } return true; } } private static bool HasAnyUnclaimedNode(IUpgradable gear) { MoreSkillTreeData.Tree tree = MoreSkillTreeData.FindTreeForGear(gear); if (tree == null) { return false; } List<ResolvedNode> list = MoreSkillTreeService.ResolveTree(gear, tree); for (int i = 0; i < list.Count; i++) { if (list[i].State == NodeState.Available || list[i].State == NodeState.CannotAfford) { return true; } } return false; } } [DefaultExecutionOrder(-100)] public sealed class GearSkillTreeController : MonoBehaviour { private struct GearBarButton { public RectTransform Root; public IUpgradable Gear; public int Index; } private static readonly FieldInfo SkillTreeContainerField = AccessTools.Field(typeof(AllSkillTreesWindow), "skillTreeContainer"); private static readonly FieldInfo SkillPointResourceUIField = AccessTools.Field(typeof(AllSkillTreesWindow), "skillPointResourceUI"); private static readonly FieldInfo CharacterTextField = AccessTools.Field(typeof(AllSkillTreesWindow), "characterText"); private static readonly FieldInfo LevelTextField = AccessTools.Field(typeof(AllSkillTreesWindow), "levelText"); private static readonly FieldInfo CharacterButtonsField = AccessTools.Field(typeof(AllSkillTreesWindow), "characterButtons"); private static readonly FieldInfo SelectorField = AccessTools.Field(typeof(AllSkillTreesWindow), "selector"); private static readonly FieldInfo ParallaxIntensityField = AccessTools.Field(typeof(AllSkillTreesWindow), "parallaxIntensity"); private static readonly FieldInfo ParallaxPaddingField = AccessTools.Field(typeof(AllSkillTreesWindow), "parallaxPadding"); private static readonly FieldInfo SkillTutorialField = AccessTools.Field(typeof(AllSkillTreesWindow), "skillTutorial"); private static readonly FieldInfo UpgradeField = AccessTools.Field(typeof(SkillTreeUpgradeUI), "upgrade"); private static readonly FieldInfo LayerField = AccessTools.Field(typeof(SkillTreeUpgradeUI), "layer"); private static readonly FieldInfo MustBeUnlockedFirstField = AccessTools.Field(typeof(SkillTreeUpgradeUI), "mustBeUnlockedFirst"); private static readonly FieldInfo CoordXField = AccessTools.Field(typeof(SkillTreeUpgradeUI), "coordX"); private static readonly FieldInfo CoordYField = AccessTools.Field(typeof(SkillTreeUpgradeUI), "coordY"); private static GearSkillTreeController _instance; private AllSkillTreesWindow _window; private RectTransform _skillTreeContainer; private ResourceUI _skillPointResourceUI; private TextMeshProUGUI _characterText; private TextMeshProUGUI _levelText; private Graphic[] _stockButtons; private Graphic _selector; private float _parallaxIntensity; private float _parallaxPadding; private MenuTutorialPopup _skillTutorial; private readonly List<IUpgradable> _categoryGear = new List<IUpgradable>(); private readonly List<GearBarButton> _gearButtons = new List<GearBarButton>(); private SkillTreeUpgradeUI _nodeTemplate; private SkillTree _runtimeTree; private RectTransform _runtimeTreeRt; private Graphic _runtimeTreeBg; private IUpgradable _selectedGear; private GearType _selectedCategory; private int _selectedIndex; private Vector2 _minSkillTreePos; private Vector2 _maxSkillTreePos; private bool _bound; private bool _opened; private static readonly int[] HexNq = new int[6] { 0, 1, 1, 0, -1, -1 }; private static readonly int[] HexNr = new int[6] { -1, -1, 0, 1, 1, 0 }; public static bool IsOurWindow(AllSkillTreesWindow window) { if ((Object)(object)_instance != (Object)null) { return (Object)(object)_instance._window == (Object)(object)window; } return false; } public static bool IsOurSkillTree(SkillTree tree) { if ((Object)(object)_instance != (Object)null && (Object)(object)_instance._runtimeTree != (Object)null) { return (Object)(object)_instance._runtimeTree == (Object)(object)tree; } return false; } public static void Open(GearDetailsWindow parent, IUpgradable gear) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)parent == (Object)null || gear == null) { return; } if (!MoreSkillTreeData.HasTree(gear)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[MoreSkillTrees] Open called with no tree."); } return; } EnsureInstance(parent); if (!((Object)(object)_instance == (Object)null)) { _instance._selectedGear = gear.GetPrefab(); _instance._selectedCategory = NormalizeCategory(gear.GearType); _instance.OpenInternal(parent); } } private static GearType NormalizeCategory(GearType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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 ((int)type != 1) { if ((int)type == 3) { return (GearType)3; } return (GearType)0; } return (GearType)1; } private static void EnsureInstance(GearDetailsWindow parent) { if ((Object)(object)_instance != (Object)null) { return; } try { AllSkillTreesWindow val = ResolveSourceWindow(parent); if ((Object)(object)val == (Object)null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)"[MoreSkillTrees] Could not find AllSkillTreesWindow to clone."); } return; } Transform val2 = (((Object)(object)((Component)val).transform.parent != (Object)null) ? ((Component)val).transform.parent : (((Object)(object)Menu.Instance != (Object)null) ? ((Component)Menu.Instance.WindowSystem).transform : ((Component)parent).transform.parent)); GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, val2, false); ((Object)val3).name = "MoreGearSkillTreesWindow"; val3.SetActive(false); AllSkillTreesWindow component = val3.GetComponent<AllSkillTreesWindow>(); if ((Object)(object)component == (Object)null) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)"[MoreSkillTrees] Clone missing AllSkillTreesWindow."); } Object.Destroy((Object)(object)val3); } else { ((Behaviour)component).enabled = false; GearSkillTreeController gearSkillTreeController = val3.AddComponent<GearSkillTreeController>(); gearSkillTreeController.Bind(component); _instance = gearSkillTreeController; } } catch (Exception arg) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogError((object)$"[MoreSkillTrees] Failed to clone skill tree window: {arg}"); } } } private static AllSkillTreesWindow ResolveSourceWindow(GearDetailsWindow parent) { if ((Object)(object)Menu.Instance != (Object)null && (Object)(object)Menu.Instance.SkillTreeWindow != (Object)null) { return Menu.Instance.SkillTreeWindow; } object? obj = AccessTools.Field(typeof(GearDetailsWindow), "skillTreeWindow")?.GetValue(parent); return (AllSkillTreesWindow)((obj is AllSkillTreesWindow) ? obj : null); } private void Bind(AllSkillTreesWindow window) { _window = window; ref RectTransform skillTreeContainer = ref _skillTreeContainer; object? obj = SkillTreeContainerField?.GetValue(window); skillTreeContainer = (RectTransform)((obj is RectTransform) ? obj : null); ref ResourceUI skillPointResourceUI = ref _skillPointResourceUI; object? obj2 = SkillPointResourceUIField?.GetValue(window); skillPointResourceUI = (ResourceUI)((obj2 is ResourceUI) ? obj2 : null); ref TextMeshProUGUI characterText = ref _characterText; object? obj3 = CharacterTextField?.GetValue(window); characterText = (TextMeshProUGUI)((obj3 is TextMeshProUGUI) ? obj3 : null); ref TextMeshProUGUI levelText = ref _levelText; object? obj4 = LevelTextField?.GetValue(window); levelText = (TextMeshProUGUI)((obj4 is TextMeshProUGUI) ? obj4 : null); _stockButtons = CharacterButtonsField?.GetValue(window) as Graphic[]; ref Graphic selector = ref _selector; object? obj5 = SelectorField?.GetValue(window); selector = (Graphic)((obj5 is Graphic) ? obj5 : null); _parallaxIntensity = ((ParallaxIntensityField != null) ? ((float)ParallaxIntensityField.GetValue(window)) : 0.15f); _parallaxPadding = ((ParallaxPaddingField != null) ? ((float)ParallaxPaddingField.GetValue(window)) : 40f); ref MenuTutorialPopup skillTutorial = ref _skillTutorial; object? obj6 = SkillTutorialField?.GetValue(window); skillTutorial = (MenuTutorialPopup)((obj6 is MenuTutorialPopup) ? obj6 : null); if ((Object)(object)_skillTutorial != (Object)null) { ((Component)_skillTutorial).gameObject.SetActive(false); } CacheNodeTemplate(); HideStockCharacterButtons(); _bound = true; } private void CacheNodeTemplate() { if ((Object)(object)_nodeTemplate != (Object)null) { return; } Character[] array = Global.Instance?.Characters; if (array == null) { return; } for (int i = 0; i < array.Length; i++) { SkillTree val = array[i]?.SkillTree; if (!((Object)(object)val == (Object)null)) { SkillTreeUpgradeUI[] componentsInChildren = ((Component)val).GetComponentsInChildren<SkillTreeUpgradeUI>(true); if (componentsInChildren != null && componentsInChildren.Length != 0) { GameObject val2 = Object.Instantiate<GameObject>(((Component)componentsInChildren[0]).gameObject, ((Component)this).transform, false); ((Object)val2).name = "GearSkillNodeTemplate"; val2.SetActive(false); _nodeTemplate = val2.GetComponent<SkillTreeUpgradeUI>(); return; } } } ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)"[MoreSkillTrees] No SkillTreeUpgradeUI template found on character trees."); } } private void HideStockCharacterButtons() { if (_stockButtons == null) { return; } for (int i = 0; i < _stockButtons.Length; i++) { if ((Object)(object)_stockButtons[i] != (Object)null) { ((Component)_stockButtons[i]).gameObject.SetActive(false); } } } private void OpenInternal(GearDetailsWindow parent) { if (_bound && !((Object)(object)_window == (Object)null)) { if ((Object)(object)parent != (Object)null && (Object)(object)((Window)parent).WindowSystem != (Object)null) { ((Window)parent).OpenWindow((Window)(object)_window); return; } if ((Object)(object)Menu.Instance != (Object)null) { Menu.Instance.WindowSystem.OpenWindow((Window)(object)_window); return; } ((Component)_window).gameObject.SetActive(true); HandleOpen(); } } public void HandleOpen() { if (_bound) { _opened = true; if ((Object)(object)_skillTutorial != (Object)null) { ((Component)_skillTutorial).gameObject.SetActive(false); } HideStockCharacterButtons(); UpdateResources(); RebuildCategoryGear(); EnsureSelectedGearInCategory(); RebuildGearBar(); RebuildTree(); RefreshHeader(); } } public void HandleClose() { _opened = false; } private void OnEnable() { PlayerData.OnResourcesUpdated += UpdateResources; } private void OnDisable() { PlayerData.OnResourcesUpdated -= UpdateResources; HandleClose(); } private void UpdateResources() { if ((Object)(object)_skillPointResourceUI != (Object)null && (Object)(object)Global.Instance != (Object)null) { _skillPointResourceUI.Setup(Global.Instance.SkillPointResource); } } private void Update() { //IL_004a: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if (!_opened || (Object)(object)_runtimeTreeRt == (Object)null || (Object)(object)_skillTreeContainer == (Object)null) { return; } try { if (PlayerInput.Controls != null && !((Object)(object)PlayerLook.LocalUICamera == (Object)null)) { RectTransform skillTreeContainer = _skillTreeContainer; MenuActions menu = PlayerInput.Controls.Menu; Vector2 val = MathUtil.ScreenPointToLocalPointInRectangle(skillTreeContainer, ((MenuActions)(ref menu)).Point.ReadValue<Vector2>(), PlayerLook.LocalUICamera); val.x = Mathf.Clamp(val.x * _parallaxIntensity, _minSkillTreePos.x, _maxSkillTreePos.x); val.y = Mathf.Clamp(val.y * _parallaxIntensity, 0f - _maxSkillTreePos.y, 0f - _minSkillTreePos.y); _runtimeTreeRt.anchoredPosition = val; if ((Object)(object)Menu.Instance != (Object)null) { Menu.Instance.BacklightColor = GetAccentColor(_selectedGear); } } } catch { } } public void MoveLeft() { if (_categoryGear.Count != 0) { _selectedIndex = (_selectedIndex - 1 + _categoryGear.Count) % _categoryGear.Count; _selectedGear = _categoryGear[_selectedIndex]; RebuildTree(); RefreshHeader(); RefreshGearBarSelection(); } } public void MoveRight() { if (_categoryGear.Count != 0) { _selectedIndex = (_selectedIndex + 1) % _categoryGear.Count; _selectedGear = _categoryGear[_selectedIndex]; RebuildTree(); RefreshHeader(); RefreshGearBarSelection(); } } private void SelectGear(int index) { if (index >= 0 && index < _categoryGear.Count) { _selectedIndex = index; _selectedGear = _categoryGear[index]; RebuildTree(); RefreshHeader(); RefreshGearBarSelection(); } } private void RebuildCategoryGear() { //IL_0035: 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) //IL_0040: Unknown result type (might be due to invalid IL or missing references) _categoryGear.Clear(); IUpgradable[] array = Global.Instance?.AllGear; if (array == null) { return; } foreach (IUpgradable val in array) { if (val == null || val is Character || NormalizeCategory(val.GearType) != _selectedCategory || !MoreSkillTreeData.HasTree(val)) { continue; } try { if (!PlayerData.IsGearCollected(val) && (Object)(object)val.Info != (Object)null && val.Info.HideWhenNotCollected) { continue; } } catch { } if (val.ShowInGearList()) { _categoryGear.Add(val.GetPrefab()); } } _categoryGear.Sort(CompareGearLikeSelectionMenu); } private static int CompareGearLikeSelectionMenu(IUpgradable a, IUpgradable b) { return GearSelectScore(a) - GearSelectScore(b); } private static int GearSelectScore(IUpgradable gear) { if (gear == null || Global.Instance?.AllGear == null) { return int.MaxValue; } int num = Array.IndexOf(Global.Instance.AllGear, gear); if (num < 0) { GearInfo info = gear.Info; int num2 = ((info != null) ? info.ID : (-1)); if (num2 >= 0) { for (int i = 0; i < Global.Instance.AllGear.Length; i++) { IUpgradable val = Global.Instance.AllGear[i]; if ((Object)(object)((val != null) ? val.Info : null) != (Object)null && val.Info.ID == num2) { num = i; gear = val; break; } } } } if (num < 0) { num = 9999; } GearData gearData = PlayerData.GetGearData(gear); if (gearData == null) { return num + 5000; } if (!gearData.IsUnlocked) { num += (gearData.IsCollected ? 2000 : 5000); num += gearData.MaxLevel * 10; } return num; } private void EnsureSelectedGearInCategory() { if (_selectedGear == null) { if (_categoryGear.Count > 0) { _selectedIndex = 0; _selectedGear = _categoryGear[0]; } return; } for (int i = 0; i < _categoryGear.Count; i++) { if (_categoryGear[i] == _selectedGear || ((Object)(object)_categoryGear[i].Info != (Object)null && (Object)(object)_selectedGear.Info != (Object)null && _categoryGear[i].Info.ID == _selectedGear.Info.ID)) { _selectedIndex = i; _selectedGear = _categoryGear[i]; return; } } if (_categoryGear.Count > 0) { _selectedIndex = 0; _selectedGear = _categoryGear[0]; } else { _selectedIndex = 0; _selectedGear = null; } } private void RebuildGearBar() { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: 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_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Expected O, but got Unknown //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Expected O, but got Unknown //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Expected O, but got Unknown //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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_0146: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0321: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _gearButtons.Count; i++) { if ((Object)(object)_gearButtons[i].Root != (Object)null) { Object.Destroy((Object)(object)((Component)_gearButtons[i].Root).gameObject); } } _gearButtons.Clear(); if (_stockButtons == null || _stockButtons.Length == 0 || (Object)(object)_stockButtons[0] == (Object)null) { return; } Graphic val = _stockButtons[0]; Transform parent = ((Transform)val.rectTransform).parent; int count = _categoryGear.Count; if (count == 0) { return; } RectTransform rectTransform = val.rectTransform; Vector2 sizeDelta = rectTransform.sizeDelta; if (sizeDelta.x < 10f) { ((Vector2)(ref sizeDelta))..ctor(72f, 72f); } float num = 10f; float num2 = (float)count * sizeDelta.x + (float)(count - 1) * num; float num3 = 1100f; float num4 = ((num2 > num3) ? (num3 / num2) : 1f); Vector2 val2 = sizeDelta * num4; float num5 = num * num4; num2 = (float)count * val2.x + (float)(count - 1) * num5; float num6 = (0f - num2) * 0.5f + val2.x * 0.5f; float y = rectTransform.anchoredPosition.y; float num7 = default(float); float num8 = default(float); float num9 = default(float); for (int j = 0; j < count; j++) { IUpgradable val3 = _categoryGear[j]; GameObject val4 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent, false); GearInfo info = val3.Info; ((Object)val4).name = "GearBtn_" + (((info != null) ? info.APIName : null) ?? j.ToString()); val4.SetActive(true); RectTransform val5 = (RectTransform)val4.transform; val5.anchorMin = new Vector2(0.5f, rectTransform.anchorMin.y); val5.anchorMax = new Vector2(0.5f, rectTransform.anchorMax.y); val5.pivot = new Vector2(0.5f, rectTransform.pivot.y); val5.sizeDelta = val2; val5.anchoredPosition = new Vector2(num6 + (float)j * (val2.x + num5), y); ClearAllButtonListeners(val4); int captured = j; Button component = val4.GetComponent<Button>(); if ((Object)(object)component != (Object)null) { component.onClick = new ButtonClickedEvent(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { SelectGear(captured); }); } if ((Object)(object)component == (Object)null) { Graphic component2 = val4.GetComponent<Graphic>(); component = val4.AddComponent<Button>(); ((Selectable)component).targetGraphic = component2; ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { SelectGear(captured); }); } ApplyGearIcon(val4, val3); try { Color accentColor = GetAccentColor(val3); Color.RGBToHSV(accentColor, ref num7, ref num8, ref num9); Color hoverColor = Color.HSVToRGB(num7, 0.35f, 0.19f); hoverColor.a = 0.96f; ColorButtonInstant component3 = val4.GetComponent<ColorButtonInstant>(); if ((Object)(object)component3 != (Object)null) { ((ColorButton)component3).SetHoverColor(hoverColor); ((ColorButton)component3).SetClickColor(accentColor); } else { DefaultButton component4 = val4.GetComponent<DefaultButton>(); if (component4 != null) { component4.SetHoverColor(hoverColor); component4.SetClickColor(accentColor, true); } } } catch { } _gearButtons.Add(new GearBarButton { Root = val5, Gear = val3, Index = j }); } RefreshGearBarSelection(); } private static void ClearAllButtonListeners(GameObject go) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown Button[] componentsInChildren = go.GetComponentsInChildren<Button>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].onClick = new ButtonClickedEvent(); } DefaultButton[] componentsInChildren2 = go.GetComponentsInChildren<DefaultButton>(true); foreach (DefaultButton val in componentsInChildren2) { if (!((Object)(object)val == (Object)null)) { try { ((Button)val).IgnoreEvents = true; } catch { } } } } private static void ApplyGearIcon(GameObject buttonGo, IUpgradable gear) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) object obj; if (gear == null) { obj = null; } else { GearInfo info = gear.Info; obj = ((info != null) ? info.Icon : null); } if ((Object)obj == (Object)null) { return; } Image[] componentsInChildren = buttonGo.GetComponentsInChildren<Image>(true); Image val = null; for (int i = 0; i < componentsInChildren.Length; i++) { if (!((Object)(object)componentsInChildren[i] == (Object)null) && !((Object)(object)((Component)componentsInChildren[i]).gameObject == (Object)(object)buttonGo)) { val = componentsInChildren[i]; break; } } if (val == null) { val = buttonGo.GetComponent<Image>(); } if ((Object)(object)val == (Object)null) { return; } val.sprite = gear.Info.Icon; ((Graphic)val).color = Color.white; val.preserveAspect = true; try { Material iconMaterial = gear.GetIconMaterial(); if ((Object)(object)iconMaterial != (Object)null) { ((Graphic)val).material = iconMaterial; } else { ((Graphic)val).material = null; } } catch { ((Graphic)val).material = null; } } private void RefreshGearBarSelection() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: 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) if (!((Object)(object)_selector == (Object)null)) { if (_selectedIndex < 0 || _selectedIndex >= _gearButtons.Count) { ((Component)_selector).gameObject.SetActive(false); return; } RectTransform root = _gearButtons[_selectedIndex].Root; ((Transform)_selector.rectTransform).SetParent((Transform)(object)root, false); _selector.rectTransform.anchorMin = Vector2.zero; _selector.rectTransform.anchorMax = Vector2.one; _selector.rectTransform.offsetMin = Vector2.zero; _selector.rectTransform.offsetMax = Vector2.zero; _selector.rectTransform.anchoredPosition = Vector2.zero; _selector.color = GetAccentColor(_selectedGear); ((Component)_selector).gameObject.SetActive(true); } } private void RefreshHeader() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) Color accentColor = GetAccentColor(_selectedGear); IUpgradable selectedGear = _selectedGear; object obj; if (selectedGear == null) { obj = null; } else { GearInfo info = selectedGear.Info; obj = ((info != null) ? info.Name : null); } if (obj == null) { obj = "No Gear"; } string text = (string)obj; if ((Object)(object)_characterText != (Object)null) { ((TMP_Text)_characterText).text = text; ((Graphic)_characterText).color = accentColor; } if (!((Object)(object)_levelText != (Object)null)) { return; } GearData val = ((_selectedGear != null) ? PlayerData.GetGearData(_selectedGear) : null); if (val != null) { try { ((TMP_Text)_levelText).text = TextBlocks.GetString("level", val.GetLevelString(), true); } catch { ((TMP_Text)_levelText).text = $"Lv {val.Level}"; } } else { ((TMP_Text)_levelText).text = string.Empty; } ((Graphic)_levelText).color = accentColor; } private void EnsureRuntimeTree() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_runtimeTree != (Object)null) && !((Object)(object)_skillTreeContainer == (Object)null)) { GameObject val = new GameObject("GearRuntimeSkillTree", new Type[3] { typeof(RectTransform), typeof(Image), typeof(SkillTree) }); _runtimeTreeRt = (RectTransform)val.transform; ((Transform)_runtimeTreeRt).SetParent((Transform)(object)_skillTreeContainer, false); _runtimeTreeRt.anchorMin = new Vector2(0.5f, 0.5f); _runtimeTreeRt.anchorMax = new Vector2(0.5f, 0.5f); _runtimeTreeRt.pivot = new Vector2(0.5f, 0.5f); _runtimeTreeRt.anchoredPosition = Vector2.zero; RectTransform runtimeTreeRt = _runtimeTreeRt; Rect rect = _skillTreeContainer.rect; runtimeTreeRt.sizeDelta = ((Rect)(ref rect)).size; _runtimeTreeBg = (Graphic)(object)val.GetComponent<Image>(); _runtimeTreeBg.color = new Color(0.05f, 0.05f, 0.07f, 0.55f); _runtimeTreeBg.raycastTarget = false; _runtimeTree = val.GetComponent<SkillTree>(); } } private void ClearTreeNodes() { if (!((Object)(object)_runtimeTreeRt == (Object)null)) { for (int num = ((Transform)_runtimeTreeRt).childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)((Transform)_runtimeTreeRt).GetChild(num)).gameObject); } if ((Object)(object)_runtimeTree != (Object)null) { _runtimeTree.upgrades.Clear(); } } } private void RebuildTree() { //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_024a: 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_0263: Unknown result type (might be due to invalid IL or missing references) EnsureRuntimeTree(); ClearTreeNodes(); if ((Object)(object)_runtimeTree == (Object)null || _selectedGear == null || (Object)(object)_nodeTemplate == (Object)null) { return; } MoreSkillTreeData.Tree tree = MoreSkillTreeData.FindTreeForGear(_selectedGear); if (tree == null) { return; } List<ResolvedNode> list = MoreSkillTreeService.ResolveTree(_selectedGear, tree); List<ResolvedNode> list2 = new List<ResolvedNode>(); for (int i = 0; i < list.Count; i++) { if ((Object)(object)list[i].Upgrade != (Object)null) { list2.Add(list[i]); } } List<(int, int)> list3 = BuildHexSpiralCoords(list2.Count); for (int j = 0; j < list2.Count; j++) { ResolvedNode resolvedNode = list2[j]; SkillTreeUpgradeUI val = Object.Instantiate<SkillTreeUpgradeUI>(_nodeTemplate, (Transform)(object)_runtimeTreeRt, false); ((Component)val).gameObject.SetActive(true); ((Object)val).name = "Node_" + resolvedNode.Upgrade.Name; RectTransform val2 = (RectTransform)((Component)val).transform; val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); int num = 0; int num2 = 0; if (j < list3.Count) { num = list3[j].Item1; num2 = list3[j].Item2; } val2.anchoredPosition = AxialToPixel(num, num2, 45f); UpgradeField?.SetValue(val, resolvedNode.Upgrade); LayerField?.SetValue(val, resolvedNode.Layer); MustBeUnlockedFirstField?.SetValue(val, null); CoordXField?.SetValue(val, num); CoordYField?.SetValue(val, num2); } Color accentColor = GetAccentColor(_selectedGear); if ((Object)(object)_runtimeTreeBg != (Object)null) { float num3 = default(float); float num4 = default(float); float num5 = default(float); Color.RGBToHSV(accentColor, ref num3, ref num4, ref num5); _runtimeTreeBg.color = Color.HSVToRGB(num3, num4, 0.08f); Color color = _runtimeTreeBg.color; color.a = 0.55f; _runtimeTreeBg.color = color; } _runtimeTree.Setup(_selectedGear, _window); ComputeParallaxBounds(); } private static int HexDistance(int q, int r) { return (Mathf.Abs(q) + Mathf.Abs(r) + Mathf.Abs(q + r)) / 2; } private static List<(int q, int r)> BuildHexSpiralCoords(int count) { List<(int, int)> list = new List<(int, int)>(Mathf.Max(count, 0)); if (count <= 0) { return list; } list.Add((0, 0)); if (count == 1) { return list; } HashSet<long> hashSet = new HashSet<long> { PackAxial(0, 0) }; int num = 0; int num2 = 0; int num3 = 1; while (list.Count < count) { int nq = num + HexNq[0]; int nr = num2 + HexNr[0]; if ((HexDistance(nq, nr) != num3 || hashSet.Contains(PackAxial(nq, nr))) && !TryEnterNextRing(num, num2, num3, hashSet, out nq, out nr)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"[MoreSkillTrees] Hex spiral enter-ring failed at ring {num3} from ({num},{num2})."); } break; } num = nq; num2 = nr; hashSet.Add(PackAxial(num, num2)); list.Add((num, num2)); if (list.Count >= count) { break; } int num4 = 6 * num3 - 1; while (num4 > 0 && list.Count < count) { if (!TryNextRingNeighbor(num, num2, num3, hashSet, out var nq2, out var nr2)) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)$"[MoreSkillTrees] Hex spiral stuck at ring {num3} ({num},{num2}), left {num4}."); } break; } num = nq2; num2 = nr2; hashSet.Add(PackAxial(num, num2)); list.Add((num, num2)); num4--; } num3++; } return list; } private static bool TryEnterNextRing(int q, int r, int ring, HashSet<long> visited, out int nq, out int nr) { for (int i = 0; i < 2; i++) { for (int j = 0; j < 6; j++) { int num = ((i != 0) ? j : 0); if (i == 0 && j > 0) { break; } int num2 = q + HexNq[num]; int num3 = r + HexNr[num]; if (HexDistance(num2, num3) == ring && !visited.Contains(PackAxial(num2, num3))) { nq = num2; nr = num3; return true; } } } nq = q; nr = r; return false; } private static bool TryNextRingNeighbor(int q, int r, int ring, HashSet<long> visited, out int nq, out int nr) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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) //IL_0083: Unknown result type (might be due to invalid IL or missing references) nq = q; nr = r; Vector2 val = AxialToPixel(q, r, 1f); float num = Mathf.Atan2(val.y, val.x); float num2 = float.MaxValue; bool result = false; for (int i = 0; i < 6; i++) { int num3 = q + HexNq[i]; int num4 = r + HexNr[i]; if (HexDistance(num3, num4) == ring && !visited.Contains(PackAxial(num3, num4))) { Vector2 val2 = AxialToPixel(num3, num4, 1f); float num5; for (num5 = Mathf.Atan2(val2.y, val2.x) - num; num5 <= 0.0001f; num5 += MathF.PI * 2f) { } while (num5 > MathF.PI * 2f) { num5 -= MathF.PI * 2f; } if (num5 < num2) { num2 = num5; nq = num3; nr = num4; result = true; } } } return result; } private static long PackAxial(int q, int r) { return ((long)q << 32) ^ (uint)r; } private static Vector2 AxialToPixel(int q, int r, float spacing) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) float num = spacing * (1.5f * (float)q); float num2 = spacing * (Mathf.Sqrt(3f) / 2f * (float)q + Mathf.Sqrt(3f) * (float)r); return new Vector2(num, num2); } public void RefreshAfterUnlock() { if ((Object)(object)_runtimeTree != (Object)null) { _runtimeTree.Refresh(); } UpdateResources(); RefreshHeader(); } private void ComputeParallaxBounds() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0148: 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_0157: 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_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_0119: Unknown result type (might be due to invalid IL or missing references) _minSkillTreePos = new Vector2(float.MaxValue, float.MaxValue); _maxSkillTreePos = new Vector2(float.MinValue, float.MinValue); if ((Object)(object)_runtimeTree == (Object)null || (Object)(object)_skillTreeContainer == (Object)null) { return; } List<SkillTreeUpgradeUI> upgrades = _runtimeTree.upgrades; if (upgrades == null || upgrades.Count == 0) { _minSkillTreePos = Vector2.zero; _maxSkillTreePos = Vector2.zero; return; } for (int i = 0; i < upgrades.Count; i++) { if (!((Object)(object)upgrades[i] == (Object)null)) { Vector2 anchoredPosition = ((RectTransform)((Component)upgrades[i]).transform).anchoredPosition; _minSkillTreePos.x = Mathf.Min(_minSkillTreePos.x, anchoredPosition.x); _minSkillTreePos.y = Mathf.Min(_minSkillTreePos.y, anchoredPosition.y); _maxSkillTreePos.x = Mathf.Max(_maxSkillTreePos.x, anchoredPosition.x); _maxSkillTreePos.y = Mathf.Max(_maxSkillTreePos.y, anchoredPosition.y); } } Rect rect = _skillTreeContainer.rect; Vector2 val = ((Rect)(ref rect)).size * 0.5f; _minSkillTreePos.x = Mathf.Min(_minSkillTreePos.x - (0f - val.x), 0f) - _parallaxPadding; _minSkillTreePos.y = Mathf.Min(_minSkillTreePos.y - (0f - val.y), 0f) - _parallaxPadding; _maxSkillTreePos.x = Mathf.Max(_maxSkillTreePos.x - val.x, 0f) + _parallaxPadding; _maxSkillTreePos.y = Mathf.Max(_maxSkillTreePos.y - val.y, 0f) + _parallaxPadding; } private static Color GetAccentColor(IUpgradable gear) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Character val = (Character)(object)((gear is Character) ? gear : null); if (val != null) { return ((Dude)val).PrimaryColor; } return new Color(0.55f, 0.85f, 1f, 1f); } private void OnDestroy() { if ((Object)(object)_instance == (Object)(object)this) { _instance = null; } } } internal static class HasUnlockActionPatch { private static readonly FieldInfo SkillTreeField = AccessTools.Field(typeof(SkillTreeUpgradeUI), "skillTree"); private static readonly FieldInfo UpgradeField = AccessTools.Field(typeof(SkillTreeUpgradeUI), "upgrade"); private static readonly FieldInfo LayerField = AccessTools.Field(typeof(SkillTreeUpgradeUI), "layer"); private static readonly FieldInfo MustBeUnlockedFirstField = AccessTools.Field(typeof(SkillTreeUpgradeUI), "mustBeUnlockedFirst"); private static Type _paramsType; private static FieldInfo _durationField; private static FieldInfo _onCompleteField; private static FieldInfo _costField; private static FieldInfo _unlockLoopField; internal static void Apply(Harmony harmony) { //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(SkillTreeUpgradeUI), "HasUnlockAction", (Type[])null, (Type[])null); if (methodInfo == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[MoreSkillTrees] HasUnlockAction not found; hold-unlock patch skipped."); } return; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length < 1) { return; } _paramsType = (parameters[0].ParameterType.IsByRef ? parameters[0].ParameterType.GetElementType() : parameters[0].ParameterType); if (!(_paramsType == null)) { _durationField = AccessTools.Field(_paramsType, "Duration"); _onCompleteField = AccessTools.Field(_paramsType, "OnComplete"); _costField = AccessTools.Field(_paramsType, "Cost"); _unlockLoopField = AccessTools.Field(_paramsType, "UnlockLoop"); HarmonyMethod val = new HarmonyMethod(typeof(HasUnlockActionPatch), "PrefixWithArgs", (Type[])null); harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)"[MoreSkillTrees] HasUnlockAction patched for gear trees."); } } } catch (Exception arg) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogError((object)$"[MoreSkillTrees] HasUnlockAction patch failed: {arg}"); } } } private static bool PrefixWithArgs(SkillTreeUpgradeUI __instance, ref bool __result, object[] __args) { try { object? obj = SkillTreeField?.GetValue(__instance); SkillTree val = (SkillTree)((obj is SkillTree) ? obj : null); if (!GearSkillTreeController.IsOurSkillTree(val)) { return true; } object? obj2 = UpgradeField?.GetValue(__instance); Upgrade val2 = (Upgrade)((obj2 is Upgrade) ? obj2 : null); int layer = ((LayerField != null) ? ((int)LayerField.GetValue(__instance)) : 0); object? obj3 = MustBeUnlockedFirstField?.GetValue(__instance); Upgrade val3 = (Upgrade)((obj3 is Upgrade) ? obj3 : null); object obj4 = Activator.CreateInstance(_paramsType); _durationField?.SetValue(obj4, 0.65f); _onCompleteField?.SetValue(obj4, new Action(__instance.Unlock)); _costField?.SetValue(obj4, Global.Instance.SkillPointUnlockCost); try { _unlockLoopField?.SetValue(obj4, Global.Instance.UnlockLoop); } catch { } if (__args != null && __args.Length != 0) { __args[0] = obj4; } bool flag = PlayerData.Instance != null && PlayerData.Instance.TotalSkillPointsSpent >= MoreSkillTreeData.MinSpentForLayer(layer); bool flag2 = (Object)(object)val3 == (Object)null || PlayerData.GetUpgradeInfo(val.Gear, val3).TotalInstancesCollected > 0; bool flag3 = MoreSkillTreeService.IsClaimed(val.Gear, val2); __result = flag && flag2 && (Object)(object)val2 != (Object)null && !flag3; return false; } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[MoreSkillTrees] HasUnlockAction prefix failed: {arg}"); } return true; } } } public static class MoreSkillTreeData { public sealed class Branch { public readonly int Layer; public readonly string[] NodeNames; public Branch(int layer, params string[] nodeNames) { Layer = layer; NodeNames = nodeNames ?? Array.Empty<string>(); } } public sealed class Tree { public readonly Branch[] Branches; public readonly string[] WeaponApiNames; public readonly string WeaponDisplayName; public readonly bool UseAllGearUpgrades; public Tree(string weaponDisplayName, string[] weaponApiNames, params Branch[] branches) { WeaponDisplayName = weaponDisplayName; WeaponApiNames = weaponApiNames ?? Array.Empty<string>(); Branches = branches ?? Array.Empty<Branch>(); UseAllGearUpgrades = false; } private Tree(string weaponDisplayName, string[] weaponApiNames, bool useAllGearUpgrades) { WeaponDisplayName = weaponDisplayName; WeaponApiNames = weaponApiNames ?? Array.Empty<string>(); Branches = Array.Empty<Branch>(); UseAllGearUpgrades = useAllGearUpgrades; } public static Tree AllUpgrades(string weaponDisplayName, params string[] weaponApiNames) { return new Tree(weaponDisplayName, weaponApiNames, useAllGearUpgrades: true); } } private static Dictionary<string, Tree> _byDisplayName; public static int MinSpentForLayer(int layer) { if (layer <= 0) { return 0; } return 2 + (layer - 1) * 5; } public static int LayerFromRarity(Rarity rarity) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected I4, but got Unknown return (int)rarity switch { 0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 4, _ => 0, }; } public static bool TryGetTree(string weaponDisplayName, out Tree tree) { EnsureIndex(); return _byDisplayName.TryGetValue(weaponDisplayName, out tree); } public static Tree FindTreeForGear(IUpgradable gear) { if ((Object)(object)((gear != null) ? gear.Info : null) == (Object)null) { return null; } EnsureIndex(); string name = gear.Info.Name; if (!string.IsNullOrEmpty(name) && _byDisplayName.TryGetValue(name, out var value)) { return value; } string aPIName = gear.Info.APIName; if (!string.IsNullOrEmpty(aPIName)) { if (_byDisplayName.TryGetValue(aPIName, out var value2)) { return value2; } string text = NameNormalize.Normalize(aPIName, stripRichTextTags: false); Tree[] allTrees = SkillTreeCatalog.AllTrees; foreach (Tree tree in allTrees) { if (NameNormalize.Normalize(tree.WeaponDisplayName, stripRichTextTags: false) == text) { return tree; } string[] weaponApiNames = tree.WeaponApiNames; foreach (string text2 in weaponApiNames) { if (string.Equals(text2, aPIName, StringComparison.OrdinalIgnoreCase)) { return tree; } if (NameNormalize.Normalize(text2, stripRichTextTags: false) == text) { return tree; } } } } string name2 = ((object)gear).GetType().Name; if (!string.IsNullOrEmpty(name2)) { string text3 = NameNormalize.Normalize(name2, stripRichTextTags: false); Tree[] allTrees = SkillTreeCatalog.AllTrees; foreach (Tree tree2 in allTrees) { if (NameNormalize.Normalize(tree2.WeaponDisplayName, stripRichTextTags: false) == text3) { return tree2; } string[] weaponApiNames = tree2.WeaponApiNames; for (int j = 0; j < weaponApiNames.Length; j++) { if (NameNormalize.Normalize(weaponApiNames[j], stripRichTextTags: false) == text3) { return tree2; } } } } return null; } public static bool HasTree(IUpgradable gear) { return FindTreeForGear(gear) != null; } private static void EnsureIndex() { if (_byDisplayName != null) { return; } _byDisplayName = new Dictionary<string, Tree>(StringComparer.OrdinalIgnoreCase); Tree[] allTrees = SkillTreeCatalog.AllTrees; foreach (Tree tree in allTrees) { _byDisplayName[tree.WeaponDisplayName] = tree; string[] weaponApiNames = tree.WeaponApiNames; foreach (string text in weaponApiNames) { if (!string.IsNullOrEmpty(text) && !_byDisplayName.ContainsKey(text)) { _byDisplayName[text] = tree; } } } if (_byDisplayName.TryGetValue("Shock Grenade", out var value)) { _byDisplayName["Voltaic Grenade"] = value; } } } public static class MoreSkillTreeService { private static readonly Dictionary<int, Dictionary<string, Upgrade>> UpgradeCache = new Dictionary<int, Dictionary<string, Upgrade>>(); private static readonly HashSet<string> LoggedMissing = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public static ManualLogSource Log { get; set; } public static bool IsClaimed(IUpgradable gear, Upgrade upgrade) { if (gear == null || (Object)(object)upgrade == (Object)null) { return false; } UpgradeInfo upgradeInfo = PlayerData.GetUpgradeInfo(gear, upgrade); if (upgradeInfo != null) { return upgradeInfo.TotalInstancesCollected > 0; } return false; } public static int GetMinSpentForLayer(int layer) { return MoreSkillTreeData.MinSpentForLayer(layer); } public static bool IsLayerUnlocked(int layer) { if (PlayerData.Instance == null) { return false; } return PlayerData.Instance.TotalSkillPointsSpent >= GetMinSpentForLayer(layer); } public static NodeState GetNodeState(IUpgradable gear, Upgrade upgrade, int layer) { if ((Object)(object)upgrade == (Object)null) { return NodeState.Unresolved; } if (IsClaimed(gear, upgrade)) { return NodeState.Claimed; } if (!IsLayerUnlocked(layer)) { return NodeState.LayerLocked; } if (PlayerData.Instance.GetResource(Global.Instance.SkillPointResource) <= 0) { return NodeState.CannotAfford; } return NodeState.Available; } public static bool TryUnlock(IUpgradable gear, Upgrade upgrade, int layer, out string message) { message = null; if (gear == null || (Object)(object)upgrade == (Object)null) { message = "Invalid upgrade."; return false; } if (IsClaimed(gear, upgrade)) { message = "Already owned."; return true; } if (!IsLayerUnlocked(layer)) { int num = GetMinSpentForLayer(layer) - PlayerData.Instance.TotalSkillPointsSpent; message = $"Spend {num} more skill point(s) first."; return false; } if (!PlayerData.Instance.TryRemoveResources(Global.Instance.SkillPointUnlockCost)) { message = "Not enough skill points."; return false; } UpgradeInstance val = PlayerData.CollectInstance(gear, upgrade, (UnlockFlags)0); if (val != null) { val.Seed = upgrade.NumberID; val.Unlock(false); } PlayerData instance = PlayerData.Instance; int totalSkillPointsSpent = instance.TotalSkillPointsSpent; instance.TotalSkillPointsSpent = totalSkillPointsSpent + 1; message = "Unlocked."; ManualLogSource log = Log; if (log != null) { string[] obj = new string[6] { "[MoreSkillTrees] Unlocked '", upgrade.Name, "' on '", null, null, null }; GearInfo info = gear.Info; obj[3] = ((info != null) ? info.Name : null); obj[4] = "' "; obj[5] = $"(spent total now {PlayerData.Instance.TotalSkillPointsSpent})."; log.LogInfo((object)string.Concat(obj)); } return true; } public static List<ResolvedNode> ResolveTree(IUpgradable gear, MoreSkillTreeData.Tree tree) { List<ResolvedNode> list = new List<ResolvedNode>(); if (gear == null || tree == null) { return list; } if (tree.UseAllGearUpgrades) { ResolveAllGearUpgrades(gear, list); SortResolvedNodes(list); return list; } Dictionary<string, Upgrade> upgradeMap = GetUpgradeMap(gear); HashSet<Upgrade> hashSet = new HashSet<Upgrade>(); MoreSkillTreeData.Branch[] branches = tree.Branches; for (int i = 0; i < branches.Length; i++) { string[] nodeNames = branches[i].NodeNames; foreach (string text in nodeNames) { upgradeMap.TryGetValue(NameNormalize.Normalize(text), out var value); if ((Object)(object)value == (Object)null) { value = FuzzyFind(upgradeMap, text); } if ((Object)(object)value == (Object)null) { if (LoggedMissing.Add(tree.WeaponDisplayName + "::" + text)) { ManualLogSource log = Log; if (log != null) { string[] obj = new string[7] { "[MoreSkillTrees] Could not resolve '", text, "' on '", null, null, null, null }; GearInfo info = gear.Info; obj[3] = ((info != null) ? info.Name : null); obj[4] = "' (API: "; GearInfo info2 = gear.Info; obj[5] = ((info2 != null) ? info2.APIName : null); obj[6] = ")."; log.LogWarning((object)string.Concat(obj)); } } list.Add(new ResolvedNode { DisplayName = text, Layer = 0, Upgrade = null, MinSpentRequired = 0, State = NodeState.Unresolved }); } else if (hashSet.Add(value)) { AddResolvedNode(list, gear, value, value.Name ?? text); } } } SortResolvedNodes(list); return list; } private static void ResolveAllGearUpgrades(IUpgradable gear, List<ResolvedNode> result) { GearInfo info = gear.Info; List<Upgrade> list = ((info != null) ? info.Upgrades : null); if (list == null) { return; } HashSet<Upgrade> hashSet = new HashSet<Upgrade>(); for (int i = 0; i < list.Count; i++) { Upgrade val = list[i]; if ((Object)(object)val == (Object)null) { continue; } try { if (val.IsSkin()) { continue; } } catch { } if (hashSet.Add(val)) { AddResolvedNode(result, gear, val, val.Name ?? val.APIName ?? "Upgrade"); } } } private static void AddResolvedNode(List<ResolvedNode> result, IUpgradable gear, Upgrade upgrade, string displayName) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) int layer = MoreSkillTreeData.LayerFromRarity(upgrade.Rarity); result.Add(new ResolvedNode { DisplayName = displayName, Layer = layer, Upgrade = upgrade, MinSpentRequired = GetMinSpentForLayer(layer), State = GetNodeState(gear, upgrade, layer) }); } private static void SortResolvedNodes(List<ResolvedNode> result) { result.Sort(delegate(ResolvedNode a, ResolvedNode b) { int num = a.Layer.CompareTo(b.Layer); return (num != 0) ? num : string.Compare(a.DisplayName, b.DisplayName, StringComparison.OrdinalIgnoreCase); }); } public static void RefreshStates(IUpgradable gear, List<ResolvedNode> nodes) { if (nodes == null) { return; } foreach (ResolvedNode node in nodes) { if ((Object)(object)node.Upgrade == (Object)null) { node.State = NodeState.Unresolved; } else { node.State = GetNodeState(gear, node.Upgrade, node.Layer); } } } public static Upgrade FindUpgrade(IUpgradable gear, string displayName) { if (gear == null || string.IsNullOrEmpty(displayName)) { return null; } Dictionary<string, Upgrade> upgradeMap = GetUpgradeMap(gear); if (upgradeMap.TryGetValue(NameNormalize.Normalize(displayName), out var value)) { return value; } return FuzzyFind(upgradeMap, displayName); } public static void ClearCache() { UpgradeCache.Clear(); } private static Dictionary<string, Upgrade> GetUpgradeMap(IUpgradable gear) { int iD = gear.Info.ID; if (UpgradeCache.TryGetValue(iD, out var value)) { return value; } Dictionary<string, Upgrade> dictionary = new Dictionary<string, Upgrade>(StringComparer.OrdinalIgnoreCase); List<Upgrade> upgrades = gear.Info.Upgrades; if (upgrades != null) { for (int i = 0; i < upgrades.Count; i++) { Upgrade val = upgrades[i]; if (!((Object)(object)val == (Object)null) && !val.IsSkin()) { AddKey(dictionary, val.Name, val); AddKey(dictionary, val.APIName, val); AddKey(dictionary, NameNormalize.Normalize(val.Name), val); AddKey(dictionary, NameNormalize.Normalize(val.APIName), val); } } } UpgradeCache[iD] = dictionary; return dictionary; } private static void AddKey(Dictionary<string, Upgrade> map, string key, Upgrade u) { if (!string.IsNullOrEmpty(key)) { if (!map.ContainsKey(key)) { map[key] = u; } string key2 = NameNormalize.Normalize(key); if (!map.ContainsKey(key2)) { map[key2] = u; } } } private static Upgrade FuzzyFind(Dictionary<string, Upgrade> map, string displayName) { string text = NameNormalize.Normalize(displayName); Upgrade result = null; foreach (KeyValuePair<string, Upgrade> item in map) { string text2 = NameNormalize.Normalize(item.Key); if (text2 == text) { return item.Value; } if (text2.Contains(text) || text.Contains(text2)) { result = item.Value; } } return result; } } public class MoreSkillTreeUI : MonoBehaviour { private static MoreSkillTreeUI _instance; private readonly List<SkillTreeNodeButton> _buttons = new List<SkillTreeNodeButton>(); private Transform _content; private IUpgradable _gear; private List<ResolvedNode> _nodes; private GearDetailsWindow _parentWindow; private TextMeshProUGUI _pointsText; private RectTransform _root; private TextMeshProUGUI _statusText; private TextMeshProUGUI _titleText; private MoreSkillTreeData.Tree _tree; private void Update() { if (((Component)this).gameObject.activeSelf) { Keyboard current = Keyboard.current; if (current != null && ((ButtonControl)current.escapeKey).wasPressedThisFrame) { Hide(); } } } public static void Open(GearDetailsWindow parent, IUpgradable gear) { GearSkillTreeController.Open(parent, gear); } public static void CloseIfOpen() { if ((Object)(object)_instance != (Object)null && ((Component)_instance).gameObject.activeSelf) { _instance.Hide(); } } private void BuildShell() { //IL_003a: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_0102: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02db: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Expected O, but got Unknown //IL_04a0: Unknown result type (might be due to invalid IL or missing references) //IL_04b5: Unknown result type (might be due to invalid IL or missing references) //IL_04ca: Unknown result type (might be due to invalid IL or missing references) //IL_04df: Unknown result type (might be due to invalid IL or missing references) //IL_053d: Unknown result type (might be due to invalid IL or missing references) //IL_057b: Unknown result type (might be due to invalid IL or missing references) //IL_0591: Unknown result type (might be due to invalid IL or missing references) //IL_05a7: Unknown result type (might be due to invalid IL or missing references) //IL_05b3: Unknown result type (might be due to invalid IL or missing references) //IL_05c9: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown GameObject gameObject = ((Component)this).gameObject; Canvas obj = gameObject.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 5000; gameObject.AddComponent<CanvasScaler>().uiScaleMode = (ScaleMode)1; gameObject.GetComponent<CanvasScaler>().referenceResolution = new Vector2(1920f, 1080f); gameObject.AddComponent<GraphicRaycaster>(); if ((Object)(object)EventSystem.current == (Object)null) { Object.DontDestroyOnLoad((Object)new GameObject("EventSystem", new Type[2] { typeof(EventSystem), typeof(StandaloneInputModule) })); } _root = gameObject.GetComponent<RectTransform>(); _root.anchorMin = Vector2.zero; _root.anchorMax = Vector2.one; _root.offsetMin = Vector2.zero; _root.offsetMax = Vector2.zero; RectTransform obj2 = SkillTreeUIHelpers.CreateUIObject("Dim", (Transform)(object)_root); ((Graphic)((Component)obj2).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.72f); SkillTreeUIHelpers.Stretch(obj2); Button obj3 = ((Component)obj2).gameObject.AddComponent<Button>(); ((Selectable)obj3).transition = (Transition)0; ((UnityEvent)obj3.onClick).AddListener(new UnityAction(Hide)); RectTransform val = SkillTreeUIHelpers.CreateUIObject("Panel", (Transform)(object)_root); val.anchorMin = new Vector2(0.5f, 0.5f); val.anchorMax = new Vector2(0.5f, 0.5f); val.pivot = new Vector2(0.5f, 0.5f); val.sizeDelta = new Vector2(1100f, 720f); ((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = new Color(0.07f, 0.08f, 0.1f, 0.97f); _titleText = SkillTreeUIHelpers.CreateText((Transform)(object)val, "Title", 32f, (FontStyles)1, (TextAlignmentOptions)514); RectTransform rectTransform = ((TMP_Text)_titleText).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(1f, 1f); rectTransform.pivot = new Vector2(0.5f, 1f); rectTransform.anchoredPosition = new Vector2(0f, -16f); rectTransform.sizeDelta = new Vector2(-40f, 44f); _pointsText = SkillTreeUIHelpers.CreateText((Transform)(object)val, "Points", 22f, (FontStyles)0, (TextAlignmentOptions)514); RectTransform rectTransform2 = ((TMP_Text)_pointsText).rectTransform; rectTransform2.anchorMin = new Vector2(0f, 1f); rectTransform2.anchorMax = new Vector2(1f, 1f); rectTransform2.pivot = new Vector2(0.5f, 1f); rectTransform2.anchoredPosition = new Vector2(0f, -58f); rectTransform2.sizeDelta = new Vector2(-40f, 30f); _statusText = SkillTreeUIHelpers.CreateText((Transform)(object)val, "Status", 18f, (FontStyles)2, (TextAlignmentOptions)514); RectTransform rectTransform3 = ((TMP_Text)_statusText).rectTransform; rectTransform3.anchorMin = new Vector2(0f, 0f); rectTransform3.anchorMax = new Vector2(1f, 0f); rectTransform3.pivot = new Vector2(0.5f, 0f); rectTransform3.anchoredPosition = new Vector2(0f, 12f); rectTransform3.sizeDelta = new Vector2(-40f, 28f); ((Graphic)_statusText).color = new Color(0.75f, 0.75f, 0.75f, 1f); RectTransform obj4 = SkillTreeUIHelpers.CreateUIObject("Close", (Transform)(object)val); obj4.anchorMin = new Vector2(1f, 1f); obj4.anchorMax = new Vector2(1f, 1f); obj4.pivot = new Vector2(1f, 1f); obj4.anchoredPosition = new Vector2(-10f, -10f); obj4.sizeDelta = new Vector2(40f, 40f); Image val2 = ((Component)obj4).gameObject.AddComponent<Image>(); ((Graphic)val2).color = new Color(0.35f, 0.12f, 0.12f, 1f); Button obj5 = ((Component)obj4).gameObject.AddComponent<Button>(); ((Selectable)obj5).targetGraphic = (Graphic)(object)val2; ((UnityEvent)obj5.onClick).AddListener(new UnityAction(Hide)); TextMeshProUGUI obj6 = SkillTreeUIHelpers.CreateText((Transform)(object)obj4, "X", 22f, (FontStyles)1, (TextAlignmentOptions)514); SkillTreeUIHelpers.Stretch(((TMP_Text)obj6).rectTransform); ((TMP_Text)obj6).text = "X"; RectTransform val3 = SkillTreeUIHelpers.CreateUIObject("Scroll", (Transform)(object)val); val3.anchorMin = new Vector2(0f, 0f); val3.anchorMax = new Vector2(1f, 1f); val3.offsetMin = new Vector2(20f, 50f); val3.offsetMax = new Vector2(-20f, -100f); ScrollRect obj7 = ((Component)val3).gameObject.AddComponent<ScrollRect>(); obj7.horizontal = true; obj7.vertical = true; obj7.movementType = (MovementType)2; RectTransform val4 = SkillTreeUIHelpers.CreateUIObject("Viewport", (Transform)(object)val3); SkillTreeUIHelpers.Stretch(val4); ((Graphic)((Component)val4).gameObject.AddComponent<Image>()).color = new Color(1f, 1f, 1f, 0.02f); ((Component)val4).gameObject.AddComponent<Mask>().showMaskGraphic = false; obj7.viewport = val4; RectTransform val5 = SkillTreeUIHelpers.CreateUIObject("Content", (Transform)(object)val4); val5.anchorMin = new Vector2(0f, 1f); val5.anchorMax = new Vector2(0f, 1f); val5.pivot = new Vector2(0f, 1f); val5.anchoredPosition = Vector2.zero; val5.sizeDelta = new Vector2(1040f, 560f); obj7.content = val5; _content = (Transform)(object)val5; ((Component)this).gameObject.SetActive(false); } private void Show() { RebuildNodes(); RefreshHeader(); ((Component)this).gameObject.SetActive(true); ((TMP_Text)_statusText).text = "Click a node to unlock. Owned upgrades are free. Still equip on hex grid."; } private void Hide() { ((Component)this).gameObject.SetActive(false); } private void RefreshHeader() { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) IUpgradable gear = _gear; object obj; if (gear == null) { obj = null; } else { GearInfo info = gear.Info; obj = ((info != null) ? info.Name : null); } if (obj == null) { obj = _tree.WeaponDisplayName; } string text = (string)obj; ((TMP_Text)_titleText).text = text + " Skill Tree"; int num = ((PlayerData.Instance != null) ? PlayerData.Instance.GetResource(Global.Instance.SkillPointResource) : 0); PlayerData instance = PlayerData.Instance; int num2 = ((instance != null) ? instance.TotalSkillPointsSpent : 0); ((TMP_Text)_pointsText).text = $"Skill Points: {num} | Total Spent: {num2} | Branch locks: 0 / 2 / 7"; ((Graphic)_pointsText).color = ((num > 0) ? new Color(0.55f, 0.9f, 1f) : new Color(0.7f, 0.7f, 0.7f)); } private void RebuildNodes() { //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Expected O, but got Unknown for (int num = _content.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)_content.GetChild(num)).gameObject); } _buttons.Clear(); Dictionary<int, List<ResolvedNode>> dictionary = new Dictionary<int, List<ResolvedNode>>(); foreach (ResolvedNode node in _nodes) { if (!dictionary.TryGetValue(node.Layer, out var value)) { value = new List<ResolvedNode>(); dictionary[node.Layer] = value; } value.Add(node); } int num2 = 0; foreach (KeyValuePair<int, List<ResolvedNode>> item2 in dictionary) { if (item2.Value.Count > num2) { num2 = item2.Value.Count; } } int num3 = 0; foreach (int item3 in SortedLayers(dictionary.Keys)) { float num4 = 10f + (float)num3 * 360f; List<ResolvedNode> list = dictionary[item3]; Transform content = _content; TextMeshProUGUI obj = SkillTreeUIHelpers.CreateText((content is RectTransform) ? content : null, $"Branch {item3 + 1}", 20f, (FontStyles)1, (TextAlignmentOptions)514); RectTransform rectTransform = ((TMP_Text)obj).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(0f, 1f); rectTransform.pivot = new Vector2(0f, 1f); rectTransform.anchoredPosition = new Vector2(num4, -10f); rectTransform.sizeDelta = new Vector2(340f, 36f); int num5 = MoreSkillTreeData.MinSpentForLayer(item3); bool flag = MoreSkillTreeService.IsLayerUnlocked(item3); ((TMP_Text)obj).text = (flag ? $"Branch {item3 + 1}" : $"Branch {item3 + 1} (need {num5} spent)"); ((Graphic)obj).color = (Color)(flag ? Color.white : new Color(1f, 1f, 1f, 0.35f)); for (int i = 0; i < list.Count; i++) { float y = -54f - (float)i * 72f; ResolvedNode captured = list[i]; SkillTreeNodeButton item = SkillTreeUIHelpers.CreateNodeButton(_content, captured, num4, y, 340f, 64f, (UnityAction)delegate { OnNodeClicked(captured); }); _buttons.Add(item); } num3++; } float num6 = 10f + (float)num3 * 360f + 10f; float num7 = 56f + (float)num2 * 72f + 20f; ((RectTransform)_content).sizeDelta = new Vector2(Mathf.Max(num6, 1040f), Mathf.Max(num7, 560f)); } private void OnNodeClicked(ResolvedNode node) { if ((Object)(object)node.Upgrade == (Object)null) { ((TMP_Text)_statusText).text = "Could not resolve '" + node.DisplayName + "' to an upgrade."; return; } node.State = MoreSkillTreeService.GetNodeState(_gear, node.Upgrade, node.Layer); if (node.State == NodeState.Claimed) { ((TMP_Text)_statusText).text = "'" + node.Upgrade.Name + "' is already owned."; RefreshAll(); return; } if (node.State != NodeState.Available) { ((TMP_Text)_statusText).text = ((node.State == NodeState.LayerLocked) ? $"Branch locked. Need {node.MinSpentRequired} total skill points spent." : "Not enough skill points."); RefreshAll(); return; } if (MoreSkillTreeService.TryUnlock(_gear, node.Upgrade, node.Layer, out var message)) { ((TMP_Text)_statusText).text = "Unlocked " + node.Upgrade.Name + ". Equip it on the hex grid to use."; } else { ((TMP_Text)_statusText).text = message ?? "Unlock failed."; } RefreshAll(); } private void RefreshAll() { MoreSkillTreeService.RefreshStates(_gear, _nodes); RebuildNodes(); RefreshHeader(); } private static List<int> SortedLayers(IEnumerable<int> keys) { List<int> list = new List<int>(keys); list.Sort(); return list; } } internal static class NameNormalize { public static string Normalize(string s, bool stripRichTextTags = true) { if (string.IsNullOrEmpty(s)) { return string.Empty; } char[] array = new char[s.Length]; int length = 0; bool flag = false; foreach (char c in s) { if (stripRichTextTags) { switch (c) { case '<': flag = true; continue; case '>': flag = false; continue; } if (flag) { continue; } } if (char.IsLetterOrDigit(c)) { array[length++] = char.ToLowerInvariant(c); } } return new string(array, 0, length); } } public enum NodeState { Claimed, LayerLocked, Available, CannotAfford, Unresolved } public sealed class ResolvedNode { public string DisplayName; public int Layer; public int MinSpentRequired; public NodeState State; public Upgrade Upgrade; } [BepInPlugin("sparroh.moreskilltrees", "MoreSkillTrees", "1.1.0")] [MycoMod(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGUID = "sparroh.moreskilltrees"; public const string PluginName = "MoreSkillTrees"; public const string PluginVersion = "1.1.0"; internal static ManualLogSource Log; private Harmony _harmony; private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; MoreSkillTreeService.Log = ((BaseUnityPlugin)this).Logger; try { _harmony = new Harmony("sparroh.moreskilltrees"); _harmony.PatchAll(typeof(Plugin).Assembly); HasUnlockActionPatch.Apply(_harmony); Log.LogInfo((object)"MoreSkillTrees v1.1.0 loaded."); } catch (Exception arg) { Log.LogError((object)$"Failed to patch: {arg}"); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } public static class SkillTreeCatalog { public static readonly MoreSkillTreeData.Tree[] AllTrees = new MoreSkillTreeData.Tree[20] { new MoreSkillTreeData.Tree("Cycler", new string[4] { "cycler", "cartridgesmg", "cartridge_smg", "smg" }, new MoreSkillTreeData.Branch(0, "Bigazine", "Bulging Cartridge", "Doublestack Cartridge", "Compact Cartridge", "Mass Acceleration", "Dump Charge", "Infinity Burn", "Cycling Repairs", "Equipment Siphon", "Extralight Frame"), new MoreSkillTreeData.Branch(1, "Charged Cartridges", "Corrosive Plasma", "Heated Battery", "Decay Energy", "Intense Reaction", "Superheat Reaction", "Toxin Recycling", "Corrode Siphon", "Shock Recursion", "Scorching Detonation", "Violent Ignition", "Energy Convergence"), new MoreSkillTreeData.Branch(2, "Adrenaline Reload", "Smart Slide", "Rocket Burst", "Full Range", "Focused Lenses", "Precision Fire", "Stability Module", "Charge Shield", "Elemental Discharge", "Condensed Ejection", "Overclocked Firing Mechanism", "Double Shot", "Ricochet", "Momentum Overload")), new MoreSkillTreeData.Tree("Jackrabbit", new string[4] { "jackrabbit", "bounceshotgun", "bounce_shotgun", "shotgun" }, new MoreSkillTreeData.Branch(0, "Reinforced Coating", "Power Ricochet", "Friction Compensators", "Ghosting", "Opening Charge", "Shell Packer", "Double Barrel", "Double Time", "Slam Fire", "Pummeler"), new MoreSkillTreeData.Branch(1, "Melting Point", "Wild Fire", "Heavy", "Hot Potato", "Hot Reload", "Reactive Coating", "Fire In My Heart", "Stand the Heat", "Immolator", "Molotov", "Pesticide", "Delicious Cores"), new MoreSkillTreeData.Branch(2, "Mag Extender", "Simplest Solution", "Focus Spread", "Steadier Aim", "Steady Aim", "Stable Grip", "Slideshot", "All Powdered Up")), new MoreSkillTreeData.Tree("Swarm Launcher", new string[4] { "swarmgun", "swarm_launcher", "swarmlauncher", "swarm" }, new MoreSkillTreeData.Branch(0, "Autoswarm", "Guidance Array", "Remote Control", "Wait Charging", "High Caliber Pellets", "Quick Grouping", "Scatterburst", "Explosive Pellets", "Electrified Pellets", "Mitosis"), new MoreSkillTreeData.Branch(1, "Atmospheric Energizers", "Large Energy Storage", "Swarm Reserves", "The Hive Must Grow", "Tool for the Job", "Breeding Season", "Cross Pollination", "Portable Solar Array", "Munition Siphon"), new MoreSkillTreeData.Branch(2, "Blitz Planting", "Quick Release", "Migration", "Crop Duster", "Power Redistribution", "Over Extended", "Sprinkler", "Tight Planting", "Rapid Pollination", "Precise Targeting", "Static Reload", "Overload Contingency")), new MoreSkillTreeData.Tree("DMLR", new string[4] { "dmlr", "chargesniper", "charge_sniper", "sniper" }, new MoreSkillTreeData.Branch(0, "Heavy Hitting", "Kinetic Amplifier", "Shredder", "Trifecta", "Triple", "Long Scope", "Overcharge Cycling", "Aux Reserves", "Quickswap Cartridge"), new MoreSkillTreeData.Branch(1, "Beam Amplifier", "Feedback Amplifier", "Rapid Charge", "Coronal Ejection", "Two Way Charging", "Arc Lightning", "Concussive Wave", "Power Core", "Hard-Light Bypass", "Corrosive Laser", "Incendiary Laser", "Shocking Laser", "Tainted Exhaust"), new MoreSkillTreeData.Branch(2, "Hot Swap", "Autocycler", "Kinetic Impossibility", "Photon Surge", "Sturdy", "Engineering Nanites", "Assist Charge", "Hazard Recycling", "Reorganized Reserves", "Voltaic Battery", "Demonstrator's Trick")), new MoreSkillTreeData.Tree("Lead Flinger", new string[3] { "leadflinger", "lead_flinger", "revolver" }, new MoreSkillTreeData.Branch(0, "Hallucinated Space", "Bandolier", "Feeling Lucky", "Self Storage", "Practice Makes Perfect", "Fresh Bullet Frenzy", "Modded Auto", "Phantom Limb", "Lucky Bastard", "Lucky Last"), new MoreSkillTreeData.Branch(1, "Lead Poisoning", "High Caliber", "Just Add More Gunpowder", "Fan Fire", "Shrapnel Loading", "Double Action", "Big Fat Doobie", "Residue", "Volatile Munitions", "Blood-Rush", "Juiced Up"), new MoreSkillTreeData.Branch(2, "Adrenaline Rush", "Delirium", "Outlaw", "Ride the High", "Burning Tips", "Chemical Symbiosis", "Controlled Substance", "Home Cooking", "Ralph's Conundrum", "Unnatural Focus", "Breathe Deep")), new MoreSkillTreeData.Tree("Plate Launcher", new string[3] { "platelauncher", "plate_launcher", "plate" }, new MoreSkillTreeData.Branch(0, "Aerodynamic Plates", "Rail-Tuning", "Weight Rebalanced", "Simple Inertia", "Tungsten Cube", "Sharper Edges", "Shish Kebab", "Decay Plates", "Electrified Plates", "Bouncy Plates", "Salad Plates"), new MoreSkillTreeData.Branch(1, "Pole Alignment", "Power Recall", "Auto-Demolition", "Compressed Plate Storage", "Fencing Construction", "Damage Arc", "Clearing Plasma", "Becall", "Shockwave", "Improvised Explosives"), new MoreSkillTreeData.Branch(2, "Double A", "Storage Surplus", "High Ground", "Impulse Redirection", "Nice Catch", "Charge Recycling", "Painter's Attachment", "Slap-Job")), new MoreSkillTreeData.Tree("Gunship Cannon", new string[4] { "gunshipcannon", "gunship_cannon", "gunship", "minigun" }, new MoreSkillTreeData.Branch(0, "Industrial Feed Mechanism", "Overclocked Firing Chamber", "Thumper", "Safety \"Regulations\"", "Frantic Fingers", "Adaptive Stabilizers", "Stabilizers", "Blowback Redirect", "Magnetic Loader", "Cargo Storage"), new MoreSkillTreeData.Branch(1, "Higher Caliber", "Heavy Munitions", "Hull Piercer", "Point Demolition", "Elemental Munitions", "Missile Bay", "Ballistic Charger", "Tinderbox", "Drag Caps", "Sawed Off"), new MoreSkillTreeData.Branch(2, "Gunship", "Firmly Planted", "Hold-Plating", "Unarmored", "Lagrange Halo", "Hard Ricochet")), new MoreSkillTreeData.Tree("Trident", new string[1] { "trident" }, new MoreSkillTreeData.Branch(0, "Compressed Ammunition", "Increased Load", "Top Deck Storage", "Squadron", "Broadside", "Lone Cannoneer", "Gunner's Precision", "Energy Condenser", "Shredify", "Ungovernable"), new MoreSkillTreeData.Branch(1, "Fire Shot", "Acid Shot", "Fire in the Hold", "Corrosive Reaction", "Rot Advantage", "Heaven's Fury", "Compatible Ammunition", "Plunder", "Gunpowder Finale"), new MoreSkillTreeData.Branch(2, "Cargo Hold", "Bottom Heavy", "Discount Marksman", "Spyglass", "Line er' Up", "Cross-Deck", "Tailwind", "Hornet Hunting", "Thrill of the Fight", "Bailing Water", "Tread the Line")), new MoreSkillTreeData.Tree("Globbler", new string[3] { "globbler", "acidthrower", "acid_thrower" }, new MoreSkillTreeData.Branch(0, "Forceful Expulsion", "Gunpowder Packing", "Heavy Globs", "Instant Detonation", "The Glob", "Triagon", "Volatile Acid", "Glob Balloons", "Flood", "Flash Flood"), new MoreSkillTreeData.Branch(1, "Auto-Replicator", "Glorb", "Improved Replication", "Globulous Excitement", "Globulous Siphon", "Pressure Cooker", "Impact Funnel", "Volatile Element", "Replicator Resistance"), new MoreSkillTreeData.Branch(2, "Pocket Replication", "Slipper Shoes", "Full Spectrum", "Pack Eater", "Shrunken Container")), new MoreSkillTreeData.Tree("Carver", new string[1] { "carver" }, new MoreSkillTreeData.Branch(0, "Aim For The Liver", "Swinging Technique", "Blade Extenders", "Overheat System", "Safety Warning", "Rush", "Blood Rampage", "Rage"), new MoreSkillTreeData.Branch(1, "Blood Efficiency", "Blood Bucket", "Blood Coating", "Bloody Jumping", "Slippery Blood", "Blood Lightning", "Super Magnet", "Lockdown"), new MoreSkillTreeData.Branch(2, "Deflector", "Big Deflector", "Nutrition Sampler", "Sharing Lunch", "Repairing Exhaust", "Ignition Recharge", "Shocking Adrenaline", "Corrosive Coating", "Additional RAM Stick", "RAM Storage", "Greedy Fuck", "Heavy Pockets")), new MoreSkillTreeData.Tree("Shocklance", new string[2] { "shocklance", "shock_lance" }, new MoreSkillTreeData.Branch(0, "Skewer", "Swing Through", "Railshot", "Splintered Lance", "Compressor", "Coil Extension", "Coated Coils", "Crescendo", "Micro Detonators", "Fester", "Fwoosh"), new MoreSkillTreeData.Branch(1, "Ready and Waiting", "Flurrying Configuration", "Half Cocked", "Battery Recursion", "Black Market Battery", "Auxiliary Chargers", "Extra Capacitors", "Forward Charge"), new MoreSkillTreeData.Branch(2, "Auger Subroutine", "Centripetal Cornering", "Gearshift", "Killing Field", "Subway", "Storm's Eye", "Laying Cable", "Fisticuffs", "Triple A", "Gladiator's Pockets", "Squire Supplier")), new MoreSkillTreeData.Tree("Accelerator", new string[2] { "accelerator", "acceleratorgun" }, new MoreSkillTreeData.Branch(0, "Full-Auto Trigger", "Number 5 To Go", "Three-In-One", "Ruptured Spleen", "Hair Trigger", "Feedback Loop", "Size Them Up", "Inertia Accelerant", "Momentum Impact"), new MoreSkillTreeData.Branch(1, "Payload Amplifier", "Kinetic Optimization", "Wasp Gun", "Awaken The Hive", "Honey Sweet", "Requeening", "Sweet Heavens", "Combustive Rounds", "Queen's Cannons", "Oxythane's Promise", "Slipspace Bullet Transfer"), new MoreSkillTreeData.Branch(2, "Shake The Nest", "Quick Reset", "Shocker", "Remote Charging", "The Royal Jelly of Hazaran", "Miniaturized Warp Core", "Payback", "Energy Cohesion", "Flash Charge", "Shaved Projectiles")), new MoreSkillTreeData.Tree("Incendiary Grenade", new string[5] { "incendiarygrenade", "incendiary_grenade", "incendiary", "firegrenade", "fire_grenade" }, new MoreSkillTreeData.Branch(0, "Large Ignition", "Home Brew Combustion", "Volatile Explosives", "Cluster Bomb", "Napalm", "Violent Reaction", "Give and Take", "Maniac Maneuver"), new MoreSkillTreeData.Branch(1, "Heat Sink", "Internal Combustion", "Hearth & Home", "Cheap Material", "Fire Gel", "Restoration Protocol", "Impact Cascade", "Hot Boxing"), new MoreSkillTreeData.Branch(2, "Heated Charge", "Two's Company", "Gambler's Bargain", "In for a Penny", "Grenade Belt", "Welding Heat")), new MoreSkillTreeData.Tree("Shock Grenade", new string[6] { "shockgrenade", "shock_grenade", "voltaicgrenade", "voltaic_grenade", "voltaic", "electricgrenade" }, new MoreSkillTreeData.Branch(0, "Engorge", "Higher Voltage", "Flash Storm", "Excited Plasma", "Stun", "Electromagnet", "Phase Housing"), new MoreSkillTreeData.Branch(1, "Live Wire", "Livelier", "Launch Charge", "Thunder Pressure", "Cloud Skip", "Marathon", "Static Charge", "System Overload", "Emergency Evac"), new MoreSkillTreeData.Branch(2, "Fastball", "Insulated Gloves", "Shock Funnel", "In for a Penny", "Grenade Belt", "Illegal Pocket Grenade")), new MoreSkillTreeData.Tree("Acid Grenade", new string[4] { "acidgrenade", "acid_grenade", "acid nade", "acidnade" }, new MoreSkillTreeData.Branch(0, "Gas Puddle", "Deteriorate", "Universal Solvent", "Odd Cocktail", "Exothermic Reaction", "Vacuum Tube", "Overcharge"), new MoreSkillTreeData.Branch(1, "Gas Valves", "Defensive Spurt", "Sloth's Day Out", "Cooling System", "Base Coating", "Polymer Coating", "Greased Mixture"), new MoreSkillTreeData.Branch(2, "Glub Glub", "Saxonite Coating", "Lightspeed Material Transfer", "In for a Penny", "Connected Systems", "Heavy Support", "Grenade Belt", "Overclock")), new MoreSkillTreeData.Tree("Photon Disc", new string[6] { "photondisc", "photon_disc", "photon", "disc", "photondisk", "photon_disk" }, new MoreSkillTreeData.Branch(0, "Enhanced Spooling", "Steel Frame", "Magnetic Shard", "Linked List", "Splinter", "Molecular Inversion", "Explosive Packing", "Photon Lattice", "Disc Array"), new MoreSkillTreeData.Branch(1, "Perfectly Attuned", "Elemental Obsession", "Erratic Systems", "Harmonizer", "Syzygy", "Reactive Overload"), new MoreSkillTreeData.Branch(2, "USB C", "Flurry", "Reflex Override", "Propulsion Drive", "Stimulus Package", "In For A Penny", "Grenade Belt", "Pocket Grenade (Wait Why is This One Legal?)", "Bullet Time")), MoreSkillTreeData.Tree.AllUpgrades("Heavy Nuke", "heavynuke", "heavy_nuke", "nuke", "heavynuclear"), MoreSkillTreeData.Tree.AllUpgrades("Heavy Shotgun", "heavyshotgun", "heavy_shotgun"), MoreSkillTreeData.Tree.AllUpgrades("Heavy Laser", "heavylaser", "heavy_laser"), MoreSkillTreeData.Tree.AllUpgrades("Heavy Railgun", "heavyrailgun", "heavy_railgun", "heavysniper", "heavy_sniper", "railgun") }; } internal static class SkillTreeUIHelpers { public static RectTransform CreateUIObject(string name, Transform parent) { //IL_0014: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); return (RectTransform)val.transform; } public static TextMeshProUGUI CreateText(Transform parent, string name, float size, FontStyles style, TextAlignmentOptions align) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Invalid comparison between Unknown and I4 TextMeshProUGUI val = ((Component)CreateUIObject(name, parent)).gameObject.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val).fontSize = size; ((TMP_Text)val).fontStyle = style; ((TMP_Text)val).alignment = align; ((Graphic)val).color = Color.white; ((Graphic)val).raycastTarget = false; ((TMP_Text)val).enableWordWrapping = true; ((TMP_Te