Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of HarrisonEpicClassSystem v0.0.21
BepInEx/plugins/HarrisonEpicClassSystem/HarrisonEpicClassSystem.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using HarrisonEpicClassSystem.Altar; using HarrisonEpicClassSystem.Assets; using HarrisonEpicClassSystem.Compatibility; using HarrisonEpicClassSystem.Config; using HarrisonEpicClassSystem.Core; using HarrisonEpicClassSystem.Items; using HarrisonEpicClassSystem.Models; using HarrisonEpicClassSystem.Persistence; using HarrisonEpicClassSystem.Requirements; using HarrisonEpicClassSystem.UI; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Harrison")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Class progression and altar awakening system for Valheim integrated with WackyEpicMMOSystem.")] [assembly: AssemblyFileVersion("0.0.21.0")] [assembly: AssemblyInformationalVersion("0.0.21")] [assembly: AssemblyProduct("HarrisonEpicClassSystem")] [assembly: AssemblyTitle("HarrisonEpicClassSystem")] [assembly: AssemblyVersion("0.0.21.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 HarrisonEpicClassSystem { [BepInPlugin("com.harrison.valheim.epicclasssystem", "HarrisonEpicClassSystem", "0.0.21")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class HarrisonEpicClassSystemPlugin : BaseUnityPlugin { public const string ModGuid = "com.harrison.valheim.epicclasssystem"; public const string ModName = "HarrisonEpicClassSystem"; public const string ModVersion = "0.0.21"; public const string WackyEpicMmoGuid = "WackyMole.EpicMMOSystem"; public const string ConfigFileName = "HarrisonEpicClassSystem.cfg"; internal static ManualLogSource Log = null; internal static HarrisonEpicClassSystemPlugin Instance = null; private Harmony? _harmony; private ConfigFile? _classConfigFile; internal static string PluginDirectory { get; private set; } = string.Empty; private void Awake() { //IL_005c: 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_006d: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? Paths.PluginPath; Log.LogInfo((object)"HarrisonEpicClassSystem 0.0.21 loading..."); string text = Path.Combine(Paths.ConfigPath, "HarrisonEpicClassSystem.cfg"); _classConfigFile = new ConfigFile(text, true, ((BaseUnityPlugin)this).Info.Metadata) { SaveOnConfigSet = true }; ClassConfig.Initialize(_classConfigFile); _classConfigFile.Save(); Log.LogInfo((object)("Config ready: " + text)); if (!ClassConfig.Validate()) { Log.LogError((object)"Promotion config is invalid. Awakening will remain unavailable until config is corrected."); } if (!WackyEpicMmoApi.Initialize()) { Log.LogError((object)"Could not initialize the WackyEpicMMOSystem compatibility API."); return; } ClassRegistry.Initialize(); bool saveOnConfigSet = _classConfigFile.SaveOnConfigSet; _classConfigFile.SaveOnConfigSet = false; try { ClassBalanceConfig.Initialize(_classConfigFile); ClassAwakeningMaterials.Initialize(_classConfigFile); } finally { _classConfigFile.SaveOnConfigSet = saveOnConfigSet; } _classConfigFile.Save(); ClassRuntimeService.Initialize(); ClassProgressionService.Initialize(); VisualAssetService.Initialize(PluginDirectory); ClassAltarUI.Initialize(); AltarRegistrar.Register(); DivineLightItem.Initialize(); AwakeningStoneItems.Initialize(); _harmony = new Harmony("com.harrison.valheim.epicclasssystem"); _harmony.PatchAll(); Log.LogInfo((object)("HarrisonEpicClassSystem loaded. Awakening levels: " + $"First={ClassConfig.FirstPromotionLevelValue}, " + $"Second={ClassConfig.SecondPromotionLevelValue}, " + $"Mythic={ClassConfig.MythicPromotionLevelValue}")); } private void Update() { ClassRuntimeService.Update(); ClassProgressionService.Update(); ClassAltarUI.Update(); } private void OnDestroy() { AltarRegistrar.Shutdown(); DivineLightItem.Shutdown(); AwakeningStoneItems.Shutdown(); ClassAltarUI.Shutdown(); VisualAssetService.Shutdown(); ClassRuntimeService.Shutdown(); Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } } namespace HarrisonEpicClassSystem.UI { internal sealed class AltarButtonSound : MonoBehaviour { private MonoBehaviour? _source; private MethodInfo? _click; private bool _bound; private int _lastFrame = -1; public void Bind(Button button) { //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown if (_bound) { return; } _bound = true; for (int i = 0; i < ((UnityEventBase)button.onClick).GetPersistentEventCount(); i++) { if (((object)((UnityEventBase)button.onClick).GetPersistentTarget(i))?.GetType().Name == "ButtonSfx") { ((UnityEventBase)button.onClick).SetPersistentListenerState(i, (UnityEventCallState)0); } } MonoBehaviour[] componentsInChildren = ((Component)button).GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren) { if (((object)val).GetType().Name != "ButtonSfx") { continue; } MethodInfo method = ((object)val).GetType().GetMethod("OnClick", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method == null)) { UnityAction val2 = (UnityAction)Delegate.CreateDelegate(typeof(UnityAction), val, method); ((UnityEvent)button.onClick).RemoveListener(val2); ((Behaviour)val).enabled = false; if ((Object)(object)_source == (Object)null) { _source = val; _click = method; } } } if ((Object)(object)_source != (Object)null) { ((UnityEvent)button.onClick).AddListener(new UnityAction(Play)); } } private void Play() { if (_lastFrame == Time.frameCount || (Object)(object)_source == (Object)null) { return; } _lastFrame = Time.frameCount; try { _click?.Invoke(_source, null); } catch (Exception ex) { HarrisonEpicClassSystemPlugin.Log.LogWarning((object)("Altar click sound failed: " + ex.Message)); } } } public sealed class AltarGuiScale : MonoBehaviour { private Vector3 _designScale; private bool _initialized; private float _nextCheck; private static MethodInfo? _getFloat; private static bool _resolved; private static float ReadGuiScale() { if (!_resolved) { _resolved = true; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type type; try { type = assembly.GetTypes().FirstOrDefault((Type type2) => type2.Name == "PlatformPrefs"); } catch (ReflectionTypeLoadException ex) { type = ex.Types.FirstOrDefault((Type type2) => type2?.Name == "PlatformPrefs"); } if (!(type == null)) { _getFloat = type.GetMethod("GetFloat", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(string), typeof(float) }, null); if (_getFloat != null) { break; } } } if (_getFloat == null) { HarrisonEpicClassSystemPlugin.Log.LogWarning((object)"PlatformPrefs.GetFloat was not found; using legacy GUI Scale preference."); } } if (!(_getFloat != null)) { return PlayerPrefs.GetFloat("GuiScale", 1f); } return Convert.ToSingle(_getFloat.Invoke(null, new object[2] { "GuiScale", 1f })); } private void OnEnable() { Apply(); } public void Apply() { //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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_005c: 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) if (!_initialized) { _designScale = ((Component)this).transform.localScale; _initialized = true; } float num = ReadGuiScale(); if (float.IsNaN(num) || float.IsInfinity(num) || num <= 0f) { num = 1f; } Vector3 val = _designScale * num; if (((Component)this).transform.localScale != val) { ((Component)this).transform.localScale = val; } _nextCheck = Time.unscaledTime + 0.25f; } private void Update() { if (Time.unscaledTime >= _nextCheck) { Apply(); } } } public static class ClassAltarUI { [CompilerGenerated] private static class <>O { public static Action <0>__OnCustomGUIAvailable; public static Action<PlayerClassData> <1>__OnClassDataChanged; public static Action<PlayerClassData, ClassStage> <2>__OnAwakeningAvailable; public static Action<PlayerClassData, ClassStage> <3>__OnAwakeningCompleted; public static UnityAction <4>__Close; public static UnityAction <5>__OnAwakenClicked; public static UnityAction <6>__OnChangeClassClicked; public static UnityAction <7>__ShowPreviousBaseClassPage; public static UnityAction <8>__ShowNextBaseClassPage; public static UnityAction <9>__ChooseCurrentBaseClassPage; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__61_1; public static UnityAction <>9__77_0; public static UnityAction <>9__82_1; public static UnityAction <>9__83_0; public static UnityAction <>9__84_0; internal void <RenderBaseClassConfirmation>b__61_1() { _pendingBaseClass = null; Refresh(); } internal void <RenderAwakeningBrowser>b__77_0() { _showAwakening = false; Refresh(); } internal void <RenderCurrentClass>b__82_1() { _respecConfirmationPending = false; _showAwakening = true; Refresh(); } internal void <RenderResetConfirmation>b__83_0() { _respecConfirmationPending = false; Refresh(); } internal void <RenderAbilities>b__84_0() { _abilitiesClass = null; Refresh(); } } private static GameObject? _panel; private static Player? _player; private static bool _polished; private static bool _respecConfirmationPending; private static BaseClass? _pendingBaseClass; private static int _escapeConsumedFrame = -1; private static readonly List<GameObject> DynamicObjects = new List<GameObject>(); private static readonly BaseClass[] BaseClassPages = new BaseClass[5] { BaseClass.Warrior, BaseClass.Mage, BaseClass.Hunter, BaseClass.Rogue, BaseClass.Paladin }; private static int _baseClassPageIndex; private static bool _showAwakening; private static ClassId? _abilitiesClass; private static GameObject? _currentClassText; private static GameObject? _currentLevelText; private static GameObject? _targetClassText; private static GameObject? _requirementsText; private static GameObject? _statusText; private static Image? _classIcon; private static Button? _awakenButton; private static Button? _changeClassButton; private static GameObject? _baseClassNameText; private static GameObject? _baseClassDescriptionText; private static GameObject? _baseClassPathsText; private static GameObject? _classPageText; private static Image? _baseClassPreviewImage; private static Button? _previousClassButton; private static Button? _nextClassButton; private static Button? _chooseClassButton; private static readonly Button?[] BranchButtons = (Button?[])(object)new Button[3]; private static readonly GameObject?[] BranchLabels = (GameObject?[])(object)new GameObject[3]; private static int _awakeningPage; private static string _awakeningContext = string.Empty; private static string _materialSnapshot = string.Empty; private static float _nextMaterialCheck; public static bool IsOpen { get { if ((Object)(object)_panel != (Object)null && _panel.activeSelf) { return (Object)(object)_player != (Object)null; } return false; } } public static bool ShouldSuppressVanillaMenuThisFrame { get { if (_escapeConsumedFrame != Time.frameCount) { if (IsOpen) { return Input.GetKeyDown((KeyCode)27); } return false; } return true; } } public static void Initialize() { GUIManager.OnCustomGUIAvailable += OnCustomGUIAvailable; ClassEvents.ClassChanged += OnClassDataChanged; ClassEvents.AwakeningAvailable += OnAwakeningAvailable; ClassEvents.AwakeningCompleted += OnAwakeningCompleted; } public static void Shutdown() { GUIManager.OnCustomGUIAvailable -= OnCustomGUIAvailable; ClassEvents.ClassChanged -= OnClassDataChanged; ClassEvents.AwakeningAvailable -= OnAwakeningAvailable; ClassEvents.AwakeningCompleted -= OnAwakeningCompleted; CloseImmediate(); if ((Object)(object)_panel != (Object)null) { Object.Destroy((Object)(object)_panel); } _panel = null; NorseUiTheme.Shutdown(); } public static void Update() { if (IsOpen) { CheckMaterialChanges(); if (Input.GetKeyDown((KeyCode)27)) { _escapeConsumedFrame = Time.frameCount; Close(); } } } public static void Open(Player player) { _pendingBaseClass = null; _player = player; EnsurePanel(); if (!((Object)(object)_panel == (Object)null)) { (_panel.GetComponent<AltarGuiScale>() ?? _panel.AddComponent<AltarGuiScale>()).Apply(); _respecConfirmationPending = false; _showAwakening = false; _abilitiesClass = null; PlayerClassData? current = ClassManager.Current; if (current != null && current.BaseClass == BaseClass.None) { _baseClassPageIndex = 0; } GetOrAddFade(_panel).Show(); Refresh(); GUIManager.BlockInput(true); } } public static void Close() { _pendingBaseClass = null; if ((Object)(object)_panel != (Object)null && _panel.activeSelf) { GetOrAddFade(_panel).Hide(); } _player = null; _respecConfirmationPending = false; GUIManager.BlockInput(false); } internal static void CloseAfterSuccess() { CloseImmediate(); } private static void CloseImmediate() { _pendingBaseClass = null; if ((Object)(object)_panel != (Object)null) { _panel.SetActive(false); } _player = null; _respecConfirmationPending = false; GUIManager.BlockInput(false); } private static void OnClassDataChanged(PlayerClassData data) { _showAwakening = false; _abilitiesClass = null; if (IsOpen) { Refresh(); } } private static void OnAwakeningAvailable(PlayerClassData data, ClassStage stage) { if (IsOpen) { Refresh(); } } private static void OnAwakeningCompleted(PlayerClassData data, ClassStage stage) { if (IsOpen) { CloseAfterSuccess(); } } private static void OnCustomGUIAvailable() { _panel = null; _polished = false; ClearPolishedReferences(); DynamicObjects.Clear(); EnsurePanel(); } private static void EnsurePanel() { if ((Object)(object)_panel != (Object)null || GUIManager.Instance == null || (Object)(object)GUIManager.CustomGUIFront == (Object)null) { return; } GameObject val = VisualAssetService.Load<GameObject>("HECS_ClassAltarCanvas"); if ((Object)(object)val != (Object)null) { _panel = Object.Instantiate<GameObject>(val, GUIManager.CustomGUIFront.transform, false); ((Object)_panel).name = "HECS_ClassAltarPanel"; _panel.SetActive(false); _polished = BindPolishedUi(_panel); if (_polished) { Image val2 = FindComponent<Image>(_panel.transform, "NorseFrame"); if ((Object)(object)val2 != (Object)null) { NorseUiTheme.ApplyBackground(val2); } HarrisonEpicClassSystemPlugin.Log.LogInfo((object)"Using polished AssetBundle Altar UI."); return; } HarrisonEpicClassSystemPlugin.Log.LogWarning((object)"HECS_ClassAltarCanvas was loaded but required named controls were missing. Falling back to generated UI."); Object.Destroy((Object)(object)_panel); _panel = null; } BuildFallbackPanel(); } private static bool BindPolishedUi(GameObject root) { //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Expected O, but got Unknown //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Expected O, but got Unknown //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Expected O, but got Unknown //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_0394: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Expected O, but got Unknown //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_03d3: Expected O, but got Unknown //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_0406: Unknown result type (might be due to invalid IL or missing references) //IL_040c: Expected O, but got Unknown Button val = FindComponent<Button>(root.transform, "CloseButton"); _awakenButton = FindComponent<Button>(root.transform, "AwakenButton"); _changeClassButton = FindComponent<Button>(root.transform, "ChangeClassButton"); _currentClassText = FindGameObject(root.transform, "CurrentClassText"); _currentLevelText = FindGameObject(root.transform, "CurrentLevelText"); _targetClassText = FindGameObject(root.transform, "TargetClassText"); _requirementsText = FindGameObject(root.transform, "RequirementsText"); _statusText = FindGameObject(root.transform, "StatusText"); _classIcon = FindComponent<Image>(root.transform, "ClassIcon"); _baseClassNameText = FindGameObject(root.transform, "BaseClassNameText"); _baseClassDescriptionText = FindGameObject(root.transform, "BaseClassDescriptionText"); _baseClassPathsText = FindGameObject(root.transform, "BaseClassPathsText"); _classPageText = FindGameObject(root.transform, "ClassPageText"); _baseClassPreviewImage = FindComponent<Image>(root.transform, "ClassPreviewImage"); _previousClassButton = FindComponent<Button>(root.transform, "PreviousClassButton"); _nextClassButton = FindComponent<Button>(root.transform, "NextClassButton"); _chooseClassButton = FindComponent<Button>(root.transform, "ChooseClassButton"); for (int i = 0; i < 3; i++) { BranchButtons[i] = FindComponent<Button>(root.transform, $"BranchButton{i + 1}"); BranchLabels[i] = FindGameObject(root.transform, $"BranchLabel{i + 1}"); } if ((Object)(object)val == (Object)null || (Object)(object)_awakenButton == (Object)null || (Object)(object)_changeClassButton == (Object)null || (Object)(object)_currentClassText == (Object)null || (Object)(object)_currentLevelText == (Object)null || (Object)(object)_targetClassText == (Object)null || (Object)(object)_requirementsText == (Object)null || (Object)(object)_statusText == (Object)null || (Object)(object)_classIcon == (Object)null || (Object)(object)_baseClassNameText == (Object)null || (Object)(object)_baseClassDescriptionText == (Object)null || (Object)(object)_baseClassPathsText == (Object)null || (Object)(object)_classPageText == (Object)null || (Object)(object)_baseClassPreviewImage == (Object)null || (Object)(object)_previousClassButton == (Object)null || (Object)(object)_nextClassButton == (Object)null || (Object)(object)_chooseClassButton == (Object)null) { return false; } Button[] componentsInChildren = root.GetComponentsInChildren<Button>(true); for (int j = 0; j < componentsInChildren.Length; j++) { NorseUiTheme.ApplyButton(componentsInChildren[j]); } ((UnityEventBase)val.onClick).RemoveAllListeners(); ButtonClickedEvent onClick = val.onClick; object obj = <>O.<4>__Close; if (obj == null) { UnityAction val2 = Close; <>O.<4>__Close = val2; obj = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj); ((UnityEventBase)_awakenButton.onClick).RemoveAllListeners(); ButtonClickedEvent onClick2 = _awakenButton.onClick; object obj2 = <>O.<5>__OnAwakenClicked; if (obj2 == null) { UnityAction val3 = OnAwakenClicked; <>O.<5>__OnAwakenClicked = val3; obj2 = (object)val3; } ((UnityEvent)onClick2).AddListener((UnityAction)obj2); ((UnityEventBase)_changeClassButton.onClick).RemoveAllListeners(); ButtonClickedEvent onClick3 = _changeClassButton.onClick; object obj3 = <>O.<6>__OnChangeClassClicked; if (obj3 == null) { UnityAction val4 = OnChangeClassClicked; <>O.<6>__OnChangeClassClicked = val4; obj3 = (object)val4; } ((UnityEvent)onClick3).AddListener((UnityAction)obj3); ((UnityEventBase)_previousClassButton.onClick).RemoveAllListeners(); ButtonClickedEvent onClick4 = _previousClassButton.onClick; object obj4 = <>O.<7>__ShowPreviousBaseClassPage; if (obj4 == null) { UnityAction val5 = ShowPreviousBaseClassPage; <>O.<7>__ShowPreviousBaseClassPage = val5; obj4 = (object)val5; } ((UnityEvent)onClick4).AddListener((UnityAction)obj4); ((UnityEventBase)_nextClassButton.onClick).RemoveAllListeners(); ButtonClickedEvent onClick5 = _nextClassButton.onClick; object obj5 = <>O.<8>__ShowNextBaseClassPage; if (obj5 == null) { UnityAction val6 = ShowNextBaseClassPage; <>O.<8>__ShowNextBaseClassPage = val6; obj5 = (object)val6; } ((UnityEvent)onClick5).AddListener((UnityAction)obj5); ((UnityEventBase)_chooseClassButton.onClick).RemoveAllListeners(); ButtonClickedEvent onClick6 = _chooseClassButton.onClick; object obj6 = <>O.<9>__ChooseCurrentBaseClassPage; if (obj6 == null) { UnityAction val7 = ChooseCurrentBaseClassPage; <>O.<9>__ChooseCurrentBaseClassPage = val7; obj6 = (object)val7; } ((UnityEvent)onClick6).AddListener((UnityAction)obj6); SetOptionalNamedObject(root.transform, "WarriorButton", active: false); SetOptionalNamedObject(root.transform, "MageButton", active: false); SetOptionalNamedObject(root.transform, "HunterButton", active: false); SetOptionalNamedObject(root.transform, "RogueButton", active: false); SetOptionalNamedObject(root.transform, "PaladinButton", active: false); return true; } private static void BuildFallbackPanel() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0141: 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_014c: Expected O, but got Unknown _polished = false; _panel = new GameObject("HECS_ClassAltarPanel", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); _panel.transform.SetParent(GUIManager.CustomGUIFront.transform, false); RectTransform component = _panel.GetComponent<RectTransform>(); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); component.pivot = val; Vector2 anchorMin = (component.anchorMax = val); component.anchorMin = anchorMin; component.anchoredPosition = Vector2.zero; component.sizeDelta = new Vector2(950f, 775f); NorseUiTheme.ApplyBackground(_panel.GetComponent<Image>()); ((Object)_panel).name = "HECS_ClassAltarPanel"; _panel.SetActive(false); GameObject obj = GUIManager.Instance.CreateButton("X", _panel.transform, new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-30f, -30f), 45f, 45f); ButtonClickedEvent onClick = obj.GetComponent<Button>().onClick; object obj2 = <>O.<4>__Close; if (obj2 == null) { UnityAction val3 = Close; <>O.<4>__Close = val3; obj2 = (object)val3; } ((UnityEvent)onClick).AddListener((UnityAction)obj2); NorseUiTheme.ApplyButton(obj.GetComponent<Button>()); } private static void Refresh() { if (!((Object)(object)_panel == (Object)null) && !((Object)(object)_player == (Object)null)) { if (_polished) { Object.Destroy((Object)(object)_panel); _panel = null; BuildFallbackPanel(); (_panel.GetComponent<AltarGuiScale>() ?? _panel.AddComponent<AltarGuiScale>()).Apply(); GetOrAddFade(_panel).Show(); } if (_polished) { RefreshPolished(); } else { RefreshFallback(); } } } private static void RefreshPolished() { PlayerClassData current = ClassManager.Current; if (current == null) { TMProBridge.SetText(_statusText, "Class data is not loaded."); return; } int level = WackyEpicMmoApi.GetLevel(); TMProBridge.SetText(_currentClassText, (current.CurrentClass == ClassId.None) ? "No Class" : current.CurrentClass.ToString()); TMProBridge.SetText(_currentLevelText, $"Level: {level}"); TMProBridge.SetText(_statusText, string.Empty); SetClassIcon(current.CurrentClass); SetNamedGroup("BaseClassSelection", current.BaseClass == BaseClass.None); SetNamedGroup("AwakeningPanel", current.BaseClass != BaseClass.None); if ((Object)(object)_changeClassButton != (Object)null) { ((Component)_changeClassButton).gameObject.SetActive(current.BaseClass != BaseClass.None); ((Selectable)_changeClassButton).interactable = current.BaseClass != BaseClass.None; TMProBridge.SetText(FindGameObject(((Component)_changeClassButton).transform, "Text") ?? ((Component)_changeClassButton).gameObject, _respecConfirmationPending ? "Confirm Reset Class" : "Change Class"); } if (current.BaseClass == BaseClass.None) { TMProBridge.SetText(_targetClassText, "Choose a starting class"); TMProBridge.SetText(_requirementsText, "Browse each class, review its role and promotion paths, then confirm your choice."); ((Selectable)_awakenButton).interactable = false; SetBranches(Array.Empty<ClassProgressionPath>(), canAwaken: false); RefreshBaseClassPagePolished(); return; } ClassStage? availableAwakening = ClassProgressionService.GetAvailableAwakening(current, level); if (!availableAwakening.HasValue) { SetBranches(Array.Empty<ClassProgressionPath>(), canAwaken: false); ((Selectable)_awakenButton).interactable = false; if (current.CurrentStage == ClassStage.MythicPromotion) { TMProBridge.SetText(_targetClassText, "Mythic Awakening Complete"); TMProBridge.SetText(_requirementsText, "No further awakening is available."); return; } ClassStage stage = current.CurrentStage + 1; int requiredLevel = ClassConfig.GetRequiredLevel(stage); TMProBridge.SetText(_targetClassText, stage.ToString()); TMProBridge.SetText(_requirementsText, $"Required Level: {level}/{requiredLevel}"); return; } AwakeningCheckResult awakeningCheckResult = AwakeningRequirementService.Check(_player, availableAwakening.Value); List<string> list = new List<string> { $"Level: {awakeningCheckResult.CurrentLevel}/{awakeningCheckResult.RequiredLevel}" }; foreach (ResourceRequirement requirement in awakeningCheckResult.Requirements) { int playerItemCount = AwakeningRequirementService.GetPlayerItemCount(_player, requirement.PrefabName); list.Add($"{requirement.PrefabName}: {playerItemCount}/{requirement.Amount}"); } TMProBridge.SetText(_requirementsText, string.Join("\n", list)); if (availableAwakening == ClassStage.FirstPromotion) { IReadOnlyList<ClassProgressionPath> paths = ClassRegistry.GetPaths(current.BaseClass); TMProBridge.SetText(_targetClassText, "Choose First Promotion"); SetBranches(paths, awakeningCheckResult.CanAwaken); ((Selectable)_awakenButton).interactable = false; } else { SetBranches(Array.Empty<ClassProgressionPath>(), canAwaken: false); ClassId classId = ClassRegistry.GetPath(current.SelectedPathId)?.GetClassForStage(availableAwakening.Value) ?? ClassId.None; TMProBridge.SetText(_targetClassText, (classId == ClassId.None) ? availableAwakening.Value.ToString() : classId.ToString()); ((Selectable)_awakenButton).interactable = awakeningCheckResult.CanAwaken && classId != ClassId.None; TMProBridge.SetText(FindGameObject(((Component)_awakenButton).transform, "Text") ?? ((Component)_awakenButton).gameObject, $"Awaken to {classId}"); } } private static void OnChangeClassClicked() { if ((Object)(object)_player == (Object)null || ClassManager.Current == null) { return; } if (!_respecConfirmationPending) { _respecConfirmationPending = true; TMProBridge.SetText(_statusText, "Changing class will reset all HECS class progression. Click Confirm Reset Class to continue."); if ((Object)(object)_changeClassButton != (Object)null) { TMProBridge.SetText(FindGameObject(((Component)_changeClassButton).transform, "Text") ?? ((Component)_changeClassButton).gameObject, "Confirm Reset Class"); } Refresh(); } else if (!ClassRespecService.ResetToUnassigned(_player)) { ((Character)_player).Message((MessageType)2, "Class reset requires Light of the God and coins. Check the required amounts.", 0, (Sprite)null, false); Refresh(); } } private static void OnAwakenClicked() { if ((Object)(object)_player == (Object)null) { return; } PlayerClassData current = ClassManager.Current; if (current != null) { int level = WackyEpicMmoApi.GetLevel(); ClassStage? availableAwakening = ClassProgressionService.GetAvailableAwakening(current, level); if (availableAwakening.HasValue && availableAwakening != ClassStage.FirstPromotion) { ClassAwakeningService.TryAwaken(_player, availableAwakening.Value); } } } private static void SetBranches(IReadOnlyList<ClassProgressionPath> paths, bool canAwaken) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown for (int i = 0; i < BranchButtons.Length; i++) { Button val = BranchButtons[i]; GameObject val2 = BranchLabels[i]; bool flag = i < paths.Count && (Object)(object)val != (Object)null; if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(flag); ((UnityEventBase)val.onClick).RemoveAllListeners(); } if ((Object)(object)val2 != (Object)null) { val2.SetActive(flag); } if (!flag) { continue; } ClassProgressionPath classProgressionPath = paths[i]; ((Selectable)val).interactable = canAwaken; TMProBridge.SetText(val2 ?? ((Component)val).gameObject, classProgressionPath.FirstPromotionClass.ToString()); string pathId = classProgressionPath.Id; ((UnityEvent)val.onClick).AddListener((UnityAction)delegate { if ((Object)(object)_player != (Object)null) { ClassAwakeningService.TryAwaken(_player, ClassStage.FirstPromotion, pathId); } }); } } private static void SetClassIcon(ClassId id) { if (!((Object)(object)_classIcon == (Object)null)) { Sprite classIcon = VisualAssetService.GetClassIcon(id); _classIcon.sprite = classIcon; ((Behaviour)_classIcon).enabled = (Object)(object)classIcon != (Object)null; _classIcon.preserveAspect = true; } } private static void SetNamedGroup(string name, bool active) { GameObject val = FindGameObject(_panel.transform, name); if ((Object)(object)val != (Object)null) { val.SetActive(active); } } private static void RefreshFallback() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_00b8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panel == (Object)null || (Object)(object)_player == (Object)null) { return; } foreach (GameObject dynamicObject in DynamicObjects) { if ((Object)(object)dynamicObject != (Object)null) { dynamicObject.SetActive(false); Object.Destroy((Object)(object)dynamicObject); } } DynamicObjects.Clear(); AddText("HARRISON CLASS ALTAR", new Vector2(0f, 310f), 30, GUIManager.Instance.ValheimOrange, 800f, 50f); PlayerClassData current2 = ClassManager.Current; if (current2 == null) { AddText("Class data is not loaded.", new Vector2(0f, 100f), 22, Color.white, 600f, 40f); } else if (_abilitiesClass.HasValue) { RenderAbilities(_abilitiesClass.Value); } else if (current2.BaseClass == BaseClass.None) { if (_pendingBaseClass.HasValue) { RenderBaseClassConfirmation(_pendingBaseClass.Value); } else { RenderFallbackBaseClassSelection(); } } else if (_showAwakening) { RenderFallbackAwakening(current2); } else { RenderCurrentClass(current2); } } private static void RenderFallbackBaseClassSelection() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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) //IL_008c: 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_00bb: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Expected O, but got Unknown //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Expected O, but got Unknown //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Expected O, but got Unknown BaseClass currentBaseClassPage = GetCurrentBaseClassPage(); ClassId classId = ClassRegistry.GetBaseClassId(currentBaseClassPage); ClassDefinition? classDefinition = ClassRegistry.GetClass(classId); AddText("CHOOSE YOUR STARTING CLASS", new Vector2(0f, 205f), 24, Color.white, 650f, 42f); AddFallbackClassPreviewImage(classId, new Vector2(-225f, 70f), 200f, 200f); RenderEquipmentGuidance(classId); ((UnityEvent)AddButton("Class Effects", new Vector2(0f, -175f), 220f, 36f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { ShowAbilities(classId); }); AddText(classDefinition?.DisplayName ?? currentBaseClassPage.ToString(), new Vector2(110f, 120f), 28, GUIManager.Instance.ValheimOrange, 410f, 42f); AddText(classDefinition?.Description ?? string.Empty, new Vector2(110f, 65f), 17, Color.white, 410f, 90f); AddText(BuildPathSummary(currentBaseClassPage), new Vector2(110f, -45f), 16, Color.white, 410f, 125f); ButtonClickedEvent onClick = AddButton("< Previous", new Vector2(-225f, -225f), 190f, 48f).GetComponent<Button>().onClick; object obj = <>O.<7>__ShowPreviousBaseClassPage; if (obj == null) { UnityAction val = ShowPreviousBaseClassPage; <>O.<7>__ShowPreviousBaseClassPage = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); ButtonClickedEvent onClick2 = AddButton($"Choose {currentBaseClassPage}", new Vector2(0f, -225f), 220f, 52f).GetComponent<Button>().onClick; object obj2 = <>O.<9>__ChooseCurrentBaseClassPage; if (obj2 == null) { UnityAction val2 = ChooseCurrentBaseClassPage; <>O.<9>__ChooseCurrentBaseClassPage = val2; obj2 = (object)val2; } ((UnityEvent)onClick2).AddListener((UnityAction)obj2); ButtonClickedEvent onClick3 = AddButton("Next >", new Vector2(225f, -225f), 190f, 48f).GetComponent<Button>().onClick; object obj3 = <>O.<8>__ShowNextBaseClassPage; if (obj3 == null) { UnityAction val3 = ShowNextBaseClassPage; <>O.<8>__ShowNextBaseClassPage = val3; obj3 = (object)val3; } ((UnityEvent)onClick3).AddListener((UnityAction)obj3); } private static void RenderFallbackAwakening(PlayerClassData data) { RenderAwakeningBrowser(data); } private static BaseClass GetCurrentBaseClassPage() { if (_baseClassPageIndex < 0 || _baseClassPageIndex >= BaseClassPages.Length) { _baseClassPageIndex = 0; } return BaseClassPages[_baseClassPageIndex]; } private static void ShowPreviousBaseClassPage() { _baseClassPageIndex = (_baseClassPageIndex - 1 + BaseClassPages.Length) % BaseClassPages.Length; Refresh(); } private static void ShowNextBaseClassPage() { _baseClassPageIndex = (_baseClassPageIndex + 1) % BaseClassPages.Length; Refresh(); } private static void ChooseCurrentBaseClassPage() { _pendingBaseClass = GetCurrentBaseClassPage(); Refresh(); } private static void RenderBaseClassConfirmation(BaseClass selected) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: 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_00f5: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown ClassId baseClassId = ClassRegistry.GetBaseClassId(selected); AddFallbackClassPreviewImage(baseClassId, new Vector2(-225f, 70f), 200f, 200f); RenderEquipmentGuidance(baseClassId); AddText($"Choose {selected}?", new Vector2(110f, 155f), 28, GUIManager.Instance.ValheimOrange, 410f, 50f); AddText("Choose carefully. Changing class later requires rare materials.\n\nConfirm this class or Cancel to keep browsing.", new Vector2(110f, 70f), 19, Color.white, 410f, 115f); ((UnityEvent)AddButton($"Confirm {selected}", new Vector2(110f, -210f), 250f, 52f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { if (_pendingBaseClass == selected && (Object)(object)_player == (Object)(object)Player.m_localPlayer) { PlayerClassData? current = ClassManager.Current; if (current != null && current.BaseClass == BaseClass.None && !ClassProgressionService.SelectBaseClassAtAltar(selected)) { _pendingBaseClass = null; Refresh(); } } }); ButtonClickedEvent onClick = AddButton("Cancel", new Vector2(-225f, -210f), 190f, 48f).GetComponent<Button>().onClick; object obj = <>c.<>9__61_1; if (obj == null) { UnityAction val = delegate { _pendingBaseClass = null; Refresh(); }; <>c.<>9__61_1 = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); } private static string BuildPathSummary(BaseClass baseClass) { IReadOnlyList<ClassProgressionPath> paths = ClassRegistry.GetPaths(baseClass); if (paths.Count == 0) { return "No promotion paths are configured."; } List<string> list = new List<string> { "Promotion Paths:" }; foreach (ClassProgressionPath item in paths) { list.Add($"• {item.FirstPromotionClass} → {item.SecondPromotionClass} → {item.MythicPromotionClass}"); } return string.Join("\n", list); } private static void RefreshBaseClassPagePolished() { BaseClass currentBaseClassPage = GetCurrentBaseClassPage(); ClassId baseClassId = ClassRegistry.GetBaseClassId(currentBaseClassPage); ClassDefinition classDefinition = ClassRegistry.GetClass(baseClassId); TMProBridge.SetText(_baseClassNameText, classDefinition?.DisplayName ?? currentBaseClassPage.ToString()); TMProBridge.SetText(_baseClassDescriptionText, (classDefinition?.Description ?? string.Empty) + "\n\n" + SuggestedEquipmentText(baseClassId)); TMProBridge.SetText(_baseClassPathsText, BuildPathSummary(currentBaseClassPage)); TMProBridge.SetText(_classPageText, string.Empty); GameObject? classPageText = _classPageText; if (classPageText != null) { classPageText.SetActive(false); } TMProBridge.SetText(FindGameObject(((Component)_chooseClassButton).transform, "Text") ?? ((Component)_chooseClassButton).gameObject, $"Choose {currentBaseClassPage}"); Sprite classIcon = VisualAssetService.GetClassIcon(baseClassId); _baseClassPreviewImage.sprite = classIcon; ((Behaviour)_baseClassPreviewImage).enabled = (Object)(object)classIcon != (Object)null; _baseClassPreviewImage.preserveAspect = true; } private static void AddFallbackClassPreviewImage(ClassId classId, Vector2 position, float width, float height) { //IL_0022: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) Sprite classIcon = VisualAssetService.GetClassIcon(classId); if ((Object)(object)classIcon == (Object)null || (Object)(object)_panel == (Object)null) { AddText("Class image unavailable", position, 15, Color.gray, width, 35f); return; } GameObject val = new GameObject("HECS_BaseClassPreview", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val.transform.SetParent(_panel.transform, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = position; component.sizeDelta = new Vector2(width, height); Image component2 = val.GetComponent<Image>(); component2.sprite = classIcon; component2.preserveAspect = true; ((Graphic)component2).raycastTarget = false; DynamicObjects.Add(val); } private static void SetOptionalNamedObject(Transform root, string name, bool active) { GameObject val = FindGameObject(root, name); if ((Object)(object)val != (Object)null) { val.SetActive(active); } } private static GameObject AddButton(string text, Vector2 position, float width, float height) { //IL_001a: 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_002e: Unknown result type (might be due to invalid IL or missing references) GameObject val = GUIManager.Instance.CreateButton(text, _panel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), position, width, height); NorseUiTheme.ApplyButton(val.GetComponent<Button>()); DynamicObjects.Add(val); return val; } private static GameObject AddText(string text, Vector2 position, int fontSize, Color color, float width, float height) { //IL_001a: 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_002e: 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_003c: Unknown result type (might be due to invalid IL or missing references) GameObject val = GUIManager.Instance.CreateText(text, _panel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), position, GUIManager.Instance.AveriaSerifBold, fontSize, color, true, Color.black, width, height, false); DynamicObjects.Add(val); return val; } private static UiFadeController GetOrAddFade(GameObject target) { return target.GetComponent<UiFadeController>() ?? target.AddComponent<UiFadeController>(); } private static T? FindComponent<T>(Transform root, string name) where T : Component { GameObject val = FindGameObject(root, name); if (!((Object)(object)val != (Object)null)) { return default(T); } return val.GetComponent<T>(); } private static GameObject? FindGameObject(Transform root, string name) { if (((Object)root).name == name) { return ((Component)root).gameObject; } for (int i = 0; i < root.childCount; i++) { GameObject val = FindGameObject(root.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static void ClearPolishedReferences() { _currentClassText = null; _currentLevelText = null; _targetClassText = null; _requirementsText = null; _statusText = null; _classIcon = null; _awakenButton = null; _changeClassButton = null; _baseClassNameText = null; _baseClassDescriptionText = null; _baseClassPathsText = null; _classPageText = null; _baseClassPreviewImage = null; _previousClassButton = null; _nextClassButton = null; _chooseClassButton = null; for (int i = 0; i < 3; i++) { BranchButtons[i] = null; BranchLabels[i] = null; } } private static IReadOnlyList<ClassProgressionPath> GetAwakeningPaths(PlayerClassData data) { if (data.CurrentStage == ClassStage.Base) { return ClassRegistry.GetPaths(data.BaseClass); } ClassProgressionPath path = ClassRegistry.GetPath(data.SelectedPathId); if (path == null || path.RootClass != data.BaseClass) { return Array.Empty<ClassProgressionPath>(); } return new ClassProgressionPath[1] { path }; } private static void RenderAwakeningBrowser(PlayerClassData data) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_028d: 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_02bc: Expected O, but got Unknown //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Unknown result type (might be due to invalid IL or missing references) //IL_0457: Unknown result type (might be due to invalid IL or missing references) //IL_0461: Expected O, but got Unknown //IL_0480: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Expected O, but got Unknown //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_0511: Unknown result type (might be due to invalid IL or missing references) //IL_051b: Expected O, but got Unknown AddText($"Current Class: {data.CurrentClass}\nLevel: {WackyEpicMmoApi.GetLevel()}", new Vector2(-225f, 205f), 16, Color.white, 235f, 55f); ButtonClickedEvent onClick = AddButton("Back to Current Class", new Vector2(0f, -270f), 260f, 42f).GetComponent<Button>().onClick; object obj = <>c.<>9__77_0; if (obj == null) { UnityAction val = delegate { _showAwakening = false; Refresh(); }; <>c.<>9__77_0 = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); if (data.CurrentStage == ClassStage.MythicPromotion) { AddFallbackClassPreviewImage(data.CurrentClass, new Vector2(-225f, 70f), 200f, 200f); RenderEquipmentGuidance(data.CurrentClass); AddText(data.CurrentClass.ToString(), new Vector2(110f, 135f), 28, GUIManager.Instance.ValheimOrange, 410f, 45f); AddText("Mythic awakening complete.\nNo further awakening is available.", new Vector2(110f, 45f), 20, Color.white, 410f, 100f); return; } ClassStage stage = data.CurrentStage + 1; IReadOnlyList<ClassProgressionPath> paths = GetAwakeningPaths(data); string text = $"{data.PlayerId}:{data.BaseClass}:{stage}:{data.SelectedPathId}"; if (_awakeningContext != text) { _awakeningContext = text; _awakeningPage = 0; } if (paths.Count == 0) { AddText("No valid promotion path is available.", Vector2.zero, 20, Color.white, 650f, 50f); return; } _awakeningPage = Mathf.Clamp(_awakeningPage, 0, paths.Count - 1); ClassProgressionPath path = paths[_awakeningPage]; ClassId target = path.GetClassForStage(stage); AwakeningCheckResult awakeningCheckResult = AwakeningRequirementService.Check(_player, stage, path.Id); AddFallbackClassPreviewImage(target, new Vector2(-225f, 70f), 200f, 200f); RenderEquipmentGuidance(target); ((UnityEvent)AddButton("Class Effects", new Vector2(0f, -160f), 240f, 36f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { ShowAbilities(target); }); AddText(target.ToString(), new Vector2(110f, 155f), 28, GUIManager.Instance.ValheimOrange, 410f, 45f); string text2 = ((stage == ClassStage.FirstPromotion) ? "First Promotion" : ((stage == ClassStage.SecondPromotion) ? "Second Promotion" : "Mythic Promotion")); AddText($"{text2}\n{path.FirstPromotionClass} → {path.SecondPromotionClass} → {path.MythicPromotionClass}", new Vector2(110f, 95f), 17, Color.white, 410f, 70f); AddText($"Required Level: {awakeningCheckResult.CurrentLevel} / {awakeningCheckResult.RequiredLevel}", new Vector2(110f, 40f), 18, awakeningCheckResult.LevelMet ? new Color(0.6f, 0.9f, 0.65f) : new Color(1f, 0.5f, 0.4f), 410f, 30f); RenderMaterialIcons(awakeningCheckResult.Requirements); Button component = AddButton("< Previous", new Vector2(-225f, -210f), 190f, 48f).GetComponent<Button>(); ((Selectable)component).interactable = paths.Count > 1; ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { ChangeAwakeningPage(-1, paths.Count); }); Button component2 = AddButton($"Awaken to {target}", new Vector2(0f, -210f), 240f, 52f).GetComponent<Button>(); ((Selectable)component2).interactable = awakeningCheckResult.CanAwaken && target != ClassId.None; ((UnityEvent)component2.onClick).AddListener((UnityAction)delegate { if ((Object)(object)_player != (Object)null && !ClassAwakeningService.TryAwaken(_player, stage, path.Id)) { Refresh(); } }); Button component3 = AddButton("Next >", new Vector2(225f, -210f), 190f, 48f).GetComponent<Button>(); ((Selectable)component3).interactable = paths.Count > 1; ((UnityEvent)component3.onClick).AddListener((UnityAction)delegate { ChangeAwakeningPage(1, paths.Count); }); _materialSnapshot = BuildMaterialSnapshot(); } private static void ChangeAwakeningPage(int delta, int count) { _awakeningPage = (_awakeningPage + delta + count) % count; Refresh(); } private static void RenderEquipmentGuidance(ClassId id) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) Text[] componentsInChildren = AddText(SuggestedEquipmentText(id), new Vector2(-225f, -90f), 16, Color.white, 200f, 115f).GetComponentsInChildren<Text>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].alignment = (TextAnchor)1; } } private static string SuggestedEquipmentText(ClassId id) { ClassEquipmentProfile profile = ClassEquipmentSuitability.GetProfile(id); if (profile == null) { return string.Empty; } return "Suggested Weapon:\n" + profile.Weapons + "\nSuggested Armor:\n" + (profile.HeavyArmor ? "Heavy chest + legs" : "Light chest + legs / robes"); } private static void ShowAbilities(ClassId id) { _respecConfirmationPending = false; _abilitiesClass = id; Refresh(); } private static void RenderCurrentClass(PlayerClassData data) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Expected O, but got Unknown //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Expected O, but got Unknown //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0351: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Expected O, but got Unknown if (_respecConfirmationPending) { RenderResetConfirmation(data); return; } ClassDefinition? classDefinition = ClassRegistry.GetClass(data.CurrentClass); AddText(_respecConfirmationPending ? "Reset class progression? Your level is kept. Click Confirm Reset." : $"CURRENT CLASS | Level {WackyEpicMmoApi.GetLevel()}", new Vector2(0f, 235f), 18, Color.white, 800f, 40f); AddFallbackClassPreviewImage(data.CurrentClass, new Vector2(-225f, 70f), 200f, 200f); RenderEquipmentGuidance(data.CurrentClass); AddText(classDefinition?.DisplayName ?? data.CurrentClass.ToString(), new Vector2(110f, 165f), 28, GUIManager.Instance.ValheimOrange, 410f, 45f); AddText("Stage: " + StageLabel(data.CurrentStage), new Vector2(110f, 115f), 18, Color.white, 410f, 35f); string text = classDefinition?.Description ?? string.Empty; if (string.IsNullOrEmpty(text)) { text = ClassRegistry.GetClass(ClassRegistry.GetBaseClassId(data.BaseClass))?.Description ?? string.Empty; } ClassProgressionPath path = ClassRegistry.GetPath(data.SelectedPathId); AddText(text, new Vector2(110f, 40f), 18, Color.white, 410f, 95f); string text2 = ((data.CurrentStage == ClassStage.MythicPromotion) ? "Mythic awakening complete." : $"Next awakening: level {ClassConfig.GetRequiredLevel(data.CurrentStage + 1)}.\nSelect Awaken to review the next class and materials."); if (path != null) { text2 += $"\n{path.FirstPromotionClass} → {path.SecondPromotionClass} → {path.MythicPromotionClass}"; } AddText(text2, new Vector2(110f, -85f), 17, Color.white, 410f, 105f); ButtonClickedEvent onClick = AddButton(_respecConfirmationPending ? "Confirm Reset Class" : "Change Class", new Vector2(-225f, -270f), 210f, 48f).GetComponent<Button>().onClick; object obj = <>O.<6>__OnChangeClassClicked; if (obj == null) { UnityAction val = OnChangeClassClicked; <>O.<6>__OnChangeClassClicked = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); ((UnityEvent)AddButton("Class Effects", new Vector2(0f, -270f), 200f, 48f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { ShowAbilities(data.CurrentClass); }); Button component = AddButton("Awaken", new Vector2(225f, -270f), 210f, 48f).GetComponent<Button>(); ((Selectable)component).interactable = data.CurrentStage != ClassStage.MythicPromotion; ButtonClickedEvent onClick2 = component.onClick; object obj2 = <>c.<>9__82_1; if (obj2 == null) { UnityAction val2 = delegate { _respecConfirmationPending = false; _showAwakening = true; Refresh(); }; <>c.<>9__82_1 = val2; obj2 = (object)val2; } ((UnityEvent)onClick2).AddListener((UnityAction)obj2); } private static void RenderResetConfirmation(PlayerClassData data) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_012b: Unknown result type (might be due to invalid IL or missing references) //IL_014b: 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_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Expected O, but got Unknown //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Expected O, but got Unknown IReadOnlyList<ResourceRequirement> requirements = ClassRespecService.GetRequirements(data.CurrentStage); AddText("RESET CLASS", new Vector2(0f, 235f), 26, GUIManager.Instance.ValheimOrange, 800f, 40f); AddFallbackClassPreviewImage(data.CurrentClass, new Vector2(-225f, 65f), 200f, 200f); AddText(data.CurrentClass.ToString(), new Vector2(-225f, -85f), 22, Color.white, 260f, 45f); AddText(StageLabel(data.CurrentStage) + " reset\nYour class, branch and awakenings will be cleared.\nYour level and attributes are kept.", new Vector2(110f, 125f), 18, Color.white, 410f, 115f); AddText("Items consumed on confirmation:", new Vector2(110f, 40f), 18, Color.white, 410f, 35f); RenderMaterialIcons(requirements); bool flag = AwakeningRequirementService.HasAllRequirements(_player, requirements); Text[] componentsInChildren = AddText(flag ? "Ready to reset. Spent awakening materials are not refunded." : "Bring all required materials to reset your class.", new Vector2(0f, -175f), 17, (Color)(flag ? Color.white : new Color(1f, 0.5f, 0.4f)), 780f, 55f).GetComponentsInChildren<Text>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].alignment = (TextAnchor)4; } Button component = AddButton("Confirm Reset Class", new Vector2(-160f, -270f), 270f, 48f).GetComponent<Button>(); ((Selectable)component).interactable = flag; ButtonClickedEvent onClick = component.onClick; object obj = <>O.<6>__OnChangeClassClicked; if (obj == null) { UnityAction val = OnChangeClassClicked; <>O.<6>__OnChangeClassClicked = val; obj = (object)val; } ((UnityEvent)onClick).AddListener((UnityAction)obj); ButtonClickedEvent onClick2 = AddButton("Cancel", new Vector2(160f, -270f), 210f, 48f).GetComponent<Button>().onClick; object obj2 = <>c.<>9__83_0; if (obj2 == null) { UnityAction val2 = delegate { _respecConfirmationPending = false; Refresh(); }; <>c.<>9__83_0 = val2; obj2 = (object)val2; } ((UnityEvent)onClick2).AddListener((UnityAction)obj2); _materialSnapshot = BuildMaterialSnapshot(); } private static void RenderAbilities(ClassId id) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_011b: Expected O, but got Unknown //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_0325: 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_0330: Expected O, but got Unknown AddText($"CLASS EFFECTS: {id}", new Vector2(0f, 235f), 26, GUIManager.Instance.ValheimOrange, 800f, 45f); string text = ClassEquipmentSuitability.Describe(id); BaseClass family = ClassRegistry.GetClass(id)?.RootClass ?? BaseClass.None; text = text + "\n\nAttribute passive:\n" + ClassEffectsDescription.AttributePassive(family, id); GameObject val = MaterialImage("AbilityDetails", _panel.transform, new Vector2(0f, -5f), new Vector2(790f, 405f), null, raycast: true); ((Graphic)val.GetComponent<Image>()).color = new Color(0.025f, 0.03f, 0.035f, 0.65f); val.AddComponent<RectMask2D>(); ScrollRect val2 = val.AddComponent<ScrollRect>(); val2.horizontal = false; val2.movementType = (MovementType)2; val2.scrollSensitivity = 80f; val2.inertia = false; val2.viewport = val.GetComponent<RectTransform>(); GameObject val3 = new GameObject("EquipmentDetails", new Type[1] { typeof(RectTransform) }); val3.transform.SetParent(val.transform, false); RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = Vector2.one; component.pivot = new Vector2(0.5f, 1f); int num = 0; string[] array = text.Split(new char[1] { '\n' }); foreach (string text2 in array) { num += Mathf.Max(1, Mathf.CeilToInt((float)text2.Length / 70f)); } float num2 = Mathf.Max(405f, (float)num * 24f + 25f); component.sizeDelta = new Vector2(0f, num2); component.anchoredPosition = Vector2.zero; val2.content = component; GameObject val4 = MaterialText(ClassEffectFormatting.HighlightNumbers(text), val3.transform, new Vector2(0f, (0f - num2) / 2f), 18, Color.white, 760f, num2 - 12f); Text[] componentsInChildren = val3.GetComponentsInChildren<Text>(true); foreach (Text val5 in componentsInChildren) { val5.alignment = (TextAnchor)0; val5.supportRichText = true; val5.horizontalOverflow = (HorizontalWrapMode)0; num2 = Mathf.Max(405f, val5.preferredHeight + 20f); } component.sizeDelta = new Vector2(0f, num2); RectTransform component2 = val4.GetComponent<RectTransform>(); component2.sizeDelta = new Vector2(760f, num2 - 12f); component2.anchoredPosition = new Vector2(0f, (0f - num2) / 2f); DynamicObjects.Add(val); ButtonClickedEvent onClick = AddButton("Back", new Vector2(0f, -280f), 220f, 48f).GetComponent<Button>().onClick; object obj = <>c.<>9__84_0; if (obj == null) { UnityAction val6 = delegate { _abilitiesClass = null; Refresh(); }; <>c.<>9__84_0 = val6; obj = (object)val6; } ((UnityEvent)onClick).AddListener((UnityAction)obj); } private static string StageLabel(ClassStage stage) { return stage switch { ClassStage.FirstPromotion => "First Promotion", ClassStage.SecondPromotion => "Second Promotion", ClassStage.MythicPromotion => "Mythic Promotion", _ => "Base", }; } private static GameObject MaterialImage(string name, Transform parent, Vector2 position, Vector2 size, Sprite? sprite, bool raycast, bool top = false) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_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_007b: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, top ? 1f : 0.5f); component.anchorMax = val2; component.anchorMin = val2; component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = position; component.sizeDelta = size; Image component2 = val.GetComponent<Image>(); component2.sprite = sprite; component2.preserveAspect = (Object)(object)sprite != (Object)null; ((Graphic)component2).raycastTarget = raycast; return val; } private static GameObject MaterialText(string text, Transform parent, Vector2 position, int size, Color color, float width, float height) { //IL_0011: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) GameObject val = GUIManager.Instance.CreateText(text, parent, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), position, GUIManager.Instance.AveriaSerifBold, size, color, true, Color.black, width, height, false); Graphic[] componentsInChildren = val.GetComponentsInChildren<Graphic>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].raycastTarget = false; } return val; } private static void RenderMaterialIcons(IReadOnlyList<ResourceRequirement> requirements) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) GameObject val = MaterialImage("AwakeningMaterials", _panel.transform, new Vector2(110f, -55f), new Vector2(410f, 145f), null, raycast: true); ((Graphic)val.GetComponent<Image>()).color = new Color(0.025f, 0.03f, 0.035f, 0.65f); val.AddComponent<RectMask2D>(); ScrollRect val2 = val.AddComponent<ScrollRect>(); val2.horizontal = false; val2.movementType = (MovementType)2; val2.scrollSensitivity = 100f; val2.inertia = false; val2.viewport = val.GetComponent<RectTransform>(); GameObject val3 = new GameObject("MaterialRows", new Type[1] { typeof(RectTransform) }); val3.transform.SetParent(val.transform, false); RectTransform component = val3.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = Vector2.one; component.pivot = new Vector2(0.5f, 1f); component.sizeDelta = new Vector2(0f, Mathf.Max(145f, (float)requirements.Count * 44f)); component.anchoredPosition = Vector2.zero; val2.content = component; DynamicObjects.Add(val); if (requirements.Count == 0) { MaterialText("No materials required.", val3.transform, new Vector2(0f, -25f), 17, Color.white, 390f, 40f); return; } for (int i = 0; i < requirements.Count; i++) { ResourceRequirement resourceRequirement = requirements[i]; float num = -24f - (float)i * 44f; Sprite itemIcon = AwakeningRequirementService.GetItemIcon(resourceRequirement.PrefabName); ((Behaviour)MaterialImage("Material_" + resourceRequirement.PrefabName, val3.transform, new Vector2(-175f, num), new Vector2(32f, 32f), itemIcon, raycast: false, top: true).GetComponent<Image>()).enabled = (Object)(object)itemIcon != (Object)null; if ((Object)(object)itemIcon == (Object)null) { MaterialText("?", val3.transform, new Vector2(-175f, num), 20, Color.gray, 32f, 32f); } int playerItemCount = AwakeningRequirementService.GetPlayerItemCount(_player, resourceRequirement.PrefabName); MaterialText(string.Format("{0} {1} / {2}", (resourceRequirement.PrefabName == "HECS_LightOfTheGod") ? "Light of the God" : AwakeningStonePolicy.ItemName(resourceRequirement.PrefabName), playerItemCount, resourceRequirement.Amount), val3.transform, new Vector2(20f, num), 17, (playerItemCount >= resourceRequirement.Amount) ? new Color(0.6f, 0.9f, 0.65f) : new Color(1f, 0.5f, 0.4f), 330f, 38f); } } private static string? SnapshotPathId(PlayerClassData data) { IReadOnlyList<ClassProgressionPath> awakeningPaths = GetAwakeningPaths(data); if (awakeningPaths.Count <= 0) { return null; } return awakeningPaths[Mathf.Clamp(_awakeningPage, 0, awakeningPaths.Count - 1)].Id; } private static string BuildMaterialSnapshot() { PlayerClassData current = ClassManager.Current; if ((Object)(object)_player == (Object)null || current == null || current.BaseClass == BaseClass.None || (!_respecConfirmationPending && current.CurrentStage == ClassStage.MythicPromotion)) { return string.Empty; } ClassStage stage = current.CurrentStage + 1; List<string> list = new List<string> { WackyEpicMmoApi.GetLevel().ToString() }; foreach (ResourceRequirement item in _respecConfirmationPending ? ClassRespecService.GetRequirements(current.CurrentStage) : AwakeningRequirementService.GetRequirements(stage, SnapshotPathId(current))) { list.Add($"{item.PrefabName}:{item.Amount}:{AwakeningRequirementService.GetPlayerItemCount(_player, item.PrefabName)}"); } return string.Join("|", list); } private static void CheckMaterialChanges() { if (!(Time.unscaledTime < _nextMaterialCheck)) { _nextMaterialCheck = Time.unscaledTime + 0.5f; string text = BuildMaterialSnapshot(); if (text != _materialSnapshot) { _materialSnapshot = text; Refresh(); } } } } public static class ClassHudUI { public static void Initialize() { } public static void Shutdown() { } } internal static class NorseUiTheme { private static Sprite? _background; private static Texture2D? _texture; private static bool _attempted; private static Sprite? _buttonSprite; private static Texture2D? _buttonTexture; private static bool _buttonAttempted; public static void ApplyButton(Button button) { //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: 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_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) (((Component)button).GetComponent<AltarButtonSound>() ?? ((Component)button).gameObject.AddComponent<AltarButtonSound>()).Bind(button); if (!_buttonAttempted) { _buttonAttempted = true; try { using Stream stream = typeof(NorseUiTheme).Assembly.GetManifestResourceStream("HECS.altar_button.png"); if (stream != null) { using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); _buttonTexture = new Texture2D(2, 2, (TextureFormat)4, false); object obj = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) })?.Invoke(null, new object[3] { _buttonTexture, memoryStream.ToArray(), true }); if (!(obj is bool) || !(bool)obj) { throw new InvalidDataException("Could not decode button PNG."); } ((Texture)_buttonTexture).wrapMode = (TextureWrapMode)1; Rect val = new Rect(0f, (float)((Texture)_buttonTexture).height * 0.16f, (float)((Texture)_buttonTexture).width, (float)((Texture)_buttonTexture).height * 0.68f); _buttonSprite = Sprite.Create(_buttonTexture, val, new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(((Rect)(ref val)).width * 0.11f, ((Rect)(ref val)).height * 0.11f, ((Rect)(ref val)).width * 0.11f, ((Rect)(ref val)).height * 0.11f)); } } catch (Exception ex) { HarrisonEpicClassSystemPlugin.Log.LogWarning((object)("Could not load Norse button texture: " + ex.Message)); } } Image component = ((Component)button).GetComponent<Image>(); if (!((Object)(object)component == (Object)null)) { if ((Object)(object)_buttonSprite != (Object)null) { component.sprite = _buttonSprite; component.type = (Type)1; component.pixelsPerUnitMultiplier = 10f; } ((Graphic)component).color = Color.white; ((Selectable)button).targetGraphic = (Graphic)(object)component; ((Selectable)button).transition = (Transition)1; ColorBlock colors = default(ColorBlock); ((ColorBlock)(ref colors)).normalColor = new Color(0.88f, 0.85f, 0.78f, 1f); ((ColorBlock)(ref colors)).highlightedColor = new Color(1.18f, 1.1f, 0.9f, 1f); ((ColorBlock)(ref colors)).selectedColor = new Color(1.12f, 1.04f, 0.86f, 1f); ((ColorBlock)(ref colors)).pressedColor = new Color(0.65f, 0.58f, 0.45f, 1f); ((ColorBlock)(ref colors)).disabledColor = new Color(0.38f, 0.38f, 0.38f, 0.65f); ((ColorBlock)(ref colors)).colorMultiplier = 1f; ((ColorBlock)(ref colors)).fadeDuration = 0.12f; ((Selectable)button).colors = colors; Text[] componentsInChildren = ((Component)button).GetComponentsInChildren<Text>(true); foreach (Text obj2 in componentsInChildren) { ((Graphic)obj2).color = new Color(0.96f, 0.88f, 0.69f, 1f); ((Graphic)obj2).raycastTarget = false; } Transform[] componentsInChildren2 = ((Component)button).GetComponentsInChildren<Transform>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { TMProBridge.SetColor(((Component)componentsInChildren2[i]).gameObject, new Color(0.96f, 0.88f, 0.69f, 1f)); } } } public static void ApplyBackground(Image image) { //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) if (!_attempted) { _attempted = true; try { using Stream stream = typeof(NorseUiTheme).Assembly.GetManifestResourceStream("HECS.altar_background.png"); if (stream != null) { using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); _texture = new Texture2D(2, 2, (TextureFormat)4, false); object obj = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) })?.Invoke(null, new object[3] { _texture, memoryStream.ToArray(), true }); if (!(obj is bool) || !(bool)obj) { throw new InvalidDataException("Could not decode altar background PNG."); } ((Texture)_texture).wrapMode = (TextureWrapMode)1; _background = Sprite.Create(_texture, new Rect(0f, 0f, (float)((Texture)_texture).width, (float)((Texture)_texture).height), new Vector2(0.5f, 0.5f)); } } catch (Exception ex) { HarrisonEpicClassSystemPlugin.Log.LogWarning((object)("Could not load Norse UI background: " + ex.Message)); } } image.sprite = _background; image.type = (Type)0; image.preserveAspect = false; ((Graphic)image).color = (Color)(((Object)(object)_background != (Object)null) ? Color.white : new Color(0.07f, 0.08f, 0.09f, 0.98f)); } public static void Shutdown() { if ((Object)(object)_buttonSprite != (Object)null) { Object.Destroy((Object)(object)_buttonSprite); } if ((Object)(object)_buttonTexture != (Object)null) { Object.Destroy((Object)(object)_buttonTexture); } _buttonSprite = null; _buttonTexture = null; _buttonAttempted = false; if ((Object)(object)_background != (Object)null) { Object.Destroy((Object)(object)_background); } if ((Object)(object)_texture != (Object)null) { Object.Destroy((Object)(object)_texture); } _background = null; _texture = null; _attempted = false; } } internal static class TMProBridge { private static readonly Type? TmpTextType = ResolveTmpType(); private static readonly PropertyInfo? TmpTextProperty = TmpTextType?.GetProperty("text", BindingFlags.Instance | BindingFlags.Public); private static readonly PropertyInfo? TmpColorProperty = TmpTextType?.GetProperty("color", BindingFlags.Instance | BindingFlags.Public); public static bool SetText(GameObject? target, string value) { if ((Object)(object)target == (Object)null) { return false; } Text component = target.GetComponent<Text>(); if ((Object)(object)component != (Object)null) { component.text = value; return true; } Component tmpComponent = GetTmpComponent(target); if ((Object)(object)tmpComponent == (Object)null || TmpTextProperty == null) { return false; } TmpTextProperty.SetValue(tmpComponent, value, null); return true; } public static void SetColor(GameObject? target, Color color) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)target == (Object)null) { return; } Text component = target.GetComponent<Text>(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = color; return; } Component tmpComponent = GetTmpComponent(target); if ((Object)(object)tmpComponent != (Object)null && TmpColorProperty != null) { TmpColorProperty.SetValue(tmpComponent, color, null); } } private static Component? GetTmpComponent(GameObject target) { if (TmpTextType == null) { return null; } return target.GetComponent(TmpTextType); } private static Type? ResolveTmpType() { return Type.GetType("TMPro.TMP_Text, Unity.TextMeshPro") ?? Type.GetType("TMPro.TextMeshProUGUI, Unity.TextMeshPro") ?? Type.GetType("TMPro.TMP_Text, TMPro") ?? Type.GetType("TMPro.TextMeshProUGUI, TMPro"); } } public sealed class UiFadeController : MonoBehaviour { private CanvasGroup? _group; private Coroutine? _routine; private void Awake() { EnsureCanvasGroup(); } private void EnsureCanvasGroup() { _group = ((Component)this).GetComponent<CanvasGroup>(); if ((Object)(object)_group == (Object)null) { _group = ((Component)this).gameObject.AddComponent<CanvasGroup>(); } } public void Show(float duration = 0.18f) { ((Component)this).gameObject.SetActive(true); EnsureCanvasGroup(); StartFade(1f, duration, disableWhenDone: false); } public void Hide(float duration = 0.14f) { EnsureCanvasGroup(); StartFade(0f, duration, disableWhenDone: true); } private void StartFade(float target, float duration, bool disableWhenDone) { if (_routine != null) { ((MonoBehaviour)this).StopCoroutine(_routine); } _routine = ((MonoBehaviour)this).StartCoroutine(Fade(target, duration, disableWhenDone)); } private IEnumerator Fade(float target, float duration, bool disableWhenDone) { if (!((Object)(object)_group == (Object)null)) { _group.interactable = target > 0.5f; _group.blocksRaycasts = target > 0.5f; float start = _group.alpha; float elapsed = 0f; duration = Mathf.Max(0.01f, duration); while (elapsed < duration) { elapsed += Time.unscaledDeltaTime; float num = Mathf.SmoothStep(0f, 1f, elapsed / duration); _group.alpha = Mathf.Lerp(start, target, num); yield return null; } _group.alpha = target; _routine = null; if (disableWhenDone) { ((Component)this).gameObject.SetActive(false); } } } } } namespace HarrisonEpicClassSystem.Requirements { public sealed class AwakeningCheckResult { public int CurrentLevel { get; set; } public int RequiredLevel { get; set; } public bool LevelMet { get; set; } public bool MaterialsMet { get; set; } public IReadOnlyList<ResourceRequirement> Requirements { get; set; } = Array.Empty<ResourceRequirement>(); public bool CanAwaken { get { if (LevelMet) { return MaterialsMet; } return false; } } } public static class AwakeningRequirementService { public static IReadOnlyList<ResourceRequirement> GetRequirements(ClassStage stage, string? selectedPathId = null) { string text = stage switch { ClassStage.FirstPromotion => ClassConfig.FirstPromotionRequirements.Value, ClassStage.SecondPromotion => ClassConfig.SecondPromotionRequirements.Value, ClassStage.MythicPromotion => ClassConfig.MythicPromotionRequirements.Value, _ => string.Empty, }; int num = AwakeningStonePolicy.Amount(stage, ClassConfig.FirstAwakeningStones.Value, ClassConfig.SecondAwakeningStones.Value, ClassConfig.MythicAwakeningStones.Value); string text2 = AwakeningStonePolicy.PrefabName(ClassManager.Current?.BaseClass ?? BaseClass.None); string text3 = ((num > 0 && text2.Length > 0) ? $"{text2}:{num}" : string.Empty); PlayerClassData current = ClassManager.Current; ClassProgressionPath path = ClassRegistry.GetPath((stage == ClassStage.FirstPromotion) ? (selectedPathId ?? string.Empty) : (current?.SelectedPathId ?? string.Empty)); if (path != null && path.RootClass == current?.BaseClass) { string text4 = ClassAwakeningMaterials.Get(path.GetClassForStage(stage)); if (!string.IsNullOrWhiteSpace(text4)) { text3 = text3 + ((text3.Length > 0) ? "," : string.Empty) + text4; } } if (ClassConfig.IncludeExtraAwakeningMaterials.Value && !string.IsNullOrWhiteSpace(text)) { text3 = text3 + ((text3.Length > 0) ? "," : string.Empty) + text; } return RequirementParser.Parse(text3); } public static AwakeningCheckResult Check(Player player, ClassStage stage, string? selectedPathId = null) { int level = WackyEpicMmoApi.GetLevel(); int requiredLevel = ClassConfig.GetRequiredLevel(stage); IReadOnlyList<ResourceRequirement> requirements = GetRequirements(stage, selectedPathId); AwakeningCheckResult obj = new AwakeningCheckResult { CurrentLevel = level, RequiredLevel = requiredLevel, LevelMet = (level >= requiredLevel), Requirements = requirements }; int materialsMet; if ((Object)(object)player == (Object)(object)Player.m_localPlayer) { BaseClass? baseClass = ClassManager.Current?.BaseClass; if ((baseClass ?? BaseClass.None) != BaseClass.None) { materialsMet = (HasAllRequirements(player, requirements) ? 1 : 0); goto IL_0089; } } materialsMet = 0; goto IL_0089; IL_0089: obj.MaterialsMet = (byte)materialsMet != 0; return obj; } public static bool HasAllRequirements(Player player, IReadOnlyList<ResourceRequirement> requirements) { foreach (ResourceRequirement requirement in requirements) { if (GetPlayerItemCount(player, requirement.PrefabName) < requirement.Amount) { return false; } } return true; } public static int GetPlayerItemCount(Player player, string prefabName) { string text = ResolveSharedItemName(prefabName); if (string.IsNullOrEmpty(text)) { return 0; } return ((Humanoid)player).GetInventory().CountItems(text, -1, true); } public static bool ConsumeRequirements(Player player, IReadOnlyList<ResourceRequirement> requirements) { if (!HasAllRequirements(player, requirements)) { return false; } Inventory inventory = ((Humanoid)player).GetInventory(); foreach (ResourceRequirement requirement in requirements) { string text = ResolveSharedItemName(requirement.PrefabName); if (string.IsNullOrEmpty(text)) { return false; } inventory.RemoveItem(text, requirement.Amount, -1, true); } return true; } public static Sprite? GetItemIcon(string prefabName) { ObjectDB instance = ObjectDB.instance; GameObject obj = ((instance != null) ? instance.GetItemPrefab(prefabName) : null); ItemDrop obj2 = ((obj != null) ? obj.GetComponent<ItemDrop>() : null); if (obj2 == null) { return null; } return obj2.m_itemData.GetIcon(); } private static string? ResolveSharedItemName(string prefabName) { ObjectDB instance = ObjectDB.instance; GameObject obj = ((instance != null) ? instance.GetItemPrefab(prefabName) : null); return ((obj != null) ? obj.GetComponent<ItemDrop>() : null)?.m_itemData?.m_shared?.m_name; } } public static class RequirementParser { public static IReadOnlyList<ResourceRequirement> Parse(string? raw) { if (string.IsNullOrWhiteSpace(raw)) { return Array.Empty<ResourceRequirement>(); } string? obj = raw ?? string.Empty; List<ResourceRequirement> list = new List<ResourceRequirement>(); string[] array = obj.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); string[] array2 = text.Split(new char[1] { ':' }); if (array2.Length != 2) { HarrisonEpicClassSystemPlugin.Log.LogWarning((object)("Invalid requirement '" + text + "'. Expected PrefabName:Amount.")); continue; } string text2 = array2[0].Trim(); if (string.IsNullOrWhiteSpace(text2) || !int.TryParse(array2[1].Trim(), out var result) || result <= 0) { HarrisonEpicClassSystemPlugin.Log.LogWarning((object)("Invalid requirement '" + text + "'. Amount must be a positive integer.")); } else { list.Add(new ResourceRequirement(text2, result)); } } return (from g in list.GroupBy<ResourceRequirement, string>((ResourceRequirement x) => x.PrefabName, StringComparer.OrdinalIgnoreCase) select new ResourceRequirement(g.Key, g.Sum((ResourceRequirement x) => x.Amount))).ToList(); } } public sealed class ResourceRequirement { public string PrefabName { get; } public int Amount { get; } public ResourceRequirement(string prefabName, int amount) { PrefabName = prefabName; Amount = amount; } public override string ToString() { return $"{PrefabName}:{Amount}"; } } } namespace HarrisonEpicClassSystem.Persistence { public interface IClassPersistence { PlayerClassData Load(Player player); void Save(Player player, PlayerClassData data); } public sealed class JsonClassPersistence : IClassPersistence { private readonly string _directory; public JsonClassPersistence() { _directory = Path.Combine(Paths.ConfigPath, "HarrisonEpicClassSystem", "players"); Directory.CreateDirectory(_directory); } public PlayerClassData Load(Player player) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) long playerID = player.GetPlayerID(); string path = GetPath(playerID); if (!File.Exists(path)) { return CreateNew(player); } try { using FileStream fileStream = File.OpenRead(path); return (((XmlObjectSerializer)new DataContractJsonSerializer(typeof(PlayerClassData))).ReadObject((Stream)fileStream) as PlayerClassData) ?? CreateNew(player); } catch (Exception arg) { HarrisonEpicClassSystemPlugin.Log.LogError((object)$"Failed to load class save '{path}': {arg}"); return CreateNew(player); } } public void Save(Player player, PlayerClassData data) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) string path = GetPath(player.GetPlayerID()); string text = path + ".tmp"; try { using (FileStream fileStream = File.Create(text)) { ((XmlObjectSerializer)new DataContractJsonSerializer(typeof(PlayerClassData))).WriteObject((Stream)fileStream, (object)data); } if (File.Exists(path)) { File.Delete(path); } File.Move(text, path); } catch (Exception arg) { HarrisonEpicClassSystemPlugin.Log.LogError((object)$"Failed to save class data '{path}': {arg}"); } finally { if (File.Exists(text)) { try { File.Delete(text); } catch { } } } } private string GetPath(long playerId) { return Path.Combine(_directory, $"{playerId}.json"); } private static PlayerClassData CreateNew(Player player) { return new PlayerClassData { PlayerId = player.GetPlayerID(), CharacterName = player.GetPlayerName(), BaseClass = BaseClass.None, CurrentClass = ClassId.None, CurrentStage = ClassStage.Base }; } } } namespace HarrisonEpicClassSystem.Patches { [HarmonyPatch] internal static class CharacterDamagePatch { private static MethodBase? TargetMethod() { return AccessTools.Method(typeof(Character), "Damage", new Type[1] { typeof(HitData) }, (Type[])null); } private static bool Prepare() { if (TargetMethod() == null) { HarrisonEpicClassSystemPlugin.Log.LogWarning((object)"Character.Damage(HitData) was not found. Class combat modifiers are disabled, progression remains active."); return false; } return true; } [HarmonyPrefix] private static void Prefix(ref HitData hit) { try { if (hit != null) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null && !((Object)(object)val != (Object)(object)Player.m_localPlayer)) { hit = hit.Clone(); ClassCombatModifier.Apply(val, hit); } } } catch (Exception arg) { HarrisonEpicClassSystemPlugin.Log.LogError((object)$"Class damage modifier failed: {arg}"); } } } [HarmonyPatch(typeof(TextsDialog), "AddActiveEffects")] internal static class ClassCompendiumPatch { [HarmonyPostfix] private static void Postfix(List<TextInfo> ___m_texts) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown try { ___m_texts.RemoveAll((TextInfo entry) => entry.m_topic == "Class Effects"); ___m_texts.Add(new TextInfo("Class Effects", ClassEffectsDescription.Build(Player.m_localPlayer))); } catch (Exception ex) { HarrisonE