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 NorseDemigodsUI v0.8.2
plugins/DemigodPanel.dll
Decompiled 5 hours 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.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using System.Text; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DemigodPanel.Diagnostics; using DemigodPanel.Logic; using DemigodPanel.Nd; using DemigodPanel.Runestone; using DemigodPanel.Ui; using HarmonyLib; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using NorseDemigods; using NorseDemigods.Abilities; using NorseDemigods.Attributes; using NorseDemigods.Demigods; using NorseDemigods.StatusEffects; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Profiling; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("NorseDemigodsUI")] [assembly: AssemblyDescription("Ability bar and Demigod panel for Norse Demigods.")] [assembly: AssemblyCompany("RDMods")] [assembly: AssemblyProduct("DemigodPanel")] [assembly: AssemblyCopyright("Copyright © RDMods 2026")] [assembly: ComVisible(false)] [assembly: AssemblyFileVersion("0.8.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.8.2.0")] namespace DemigodPanel { internal sealed class ConfigMigration { private readonly Dictionary<ConfigDefinition, string> _orphans; private readonly HashSet<ConfigDefinition> _inFileAtStart = new HashSet<ConfigDefinition>(); public bool CanRead => _orphans != null; public ConfigMigration(ConfigFile config) { _orphans = AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(config) as Dictionary<ConfigDefinition, string>; if (_orphans == null) { Plugin.Log.LogWarning((object)"Could not read old config lines; moved settings start at their defaults."); } else { _inFileAtStart.UnionWith(_orphans.Keys); } } public bool InFile(string section, string key) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if (_orphans != null) { return _orphans.ContainsKey(new ConfigDefinition(section, key)); } return false; } public void Move(string oldSection, string oldKey, ConfigEntryBase entry) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ConfigDefinition key = new ConfigDefinition(oldSection, oldKey); if (_orphans != null && entry != null && _orphans.TryGetValue(key, out var value)) { _orphans.Remove(key); if (!_inFileAtStart.Contains(entry.Definition)) { entry.SetSerializedValue(value); Plugin.Log.LogInfo((object)("Config: moved [" + oldSection + "] " + oldKey + " to [" + entry.Definition.Section + "] " + entry.Definition.Key + ".")); } } } public void DropSections(params string[] sections) { if (_orphans == null) { return; } List<ConfigDefinition> list = new List<ConfigDefinition>(); foreach (ConfigDefinition key in _orphans.Keys) { if (Array.IndexOf(sections, key.Section) >= 0) { list.Add(key); } } foreach (ConfigDefinition item in list) { _orphans.Remove(item); } } } [HarmonyPatch] internal static class ConfigSaveFence { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(ZNet), "Start", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(ZNet), "OnDestroy", (Type[])null, (Type[])null); } [HarmonyPriority(800)] private static void Prefix() { ConfigSaver.WaitForWrite(); } } internal static class ConfigSaver { private sealed class Pending { public ConfigFile File; public float Due; public Action Written; } private const float Delay = 1f; private static readonly List<Pending> Queue = new List<Pending>(); private static int _writing; private static volatile bool _mainThread; private static int _busyInARow; private const int BusyWarnAfter = 10; public static bool Writing => Volatile.Read(in _writing) > 0; public static void Request(ConfigFile file, Action written = null) { float due = Time.realtimeSinceStartup + 1f; foreach (Pending item in Queue) { if (item.File == file) { item.Due = due; return; } } Queue.Add(new Pending { File = file, Due = due, Written = written }); } public static void Tick() { if (Queue.Count == 0) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; for (int num = Queue.Count - 1; num >= 0; num--) { Pending pending = Queue[num]; if (realtimeSinceStartup >= pending.Due) { Queue.RemoveAt(num); Write(pending); } } } public static void FlushNow() { WaitForWrite(); foreach (Pending item in Queue) { Save(item); } Queue.Clear(); } public static void WaitForWrite() { if (Writing) { Stopwatch stopwatch = Stopwatch.StartNew(); while (Writing && stopwatch.ElapsedMilliseconds < 3000) { Thread.Sleep(1); } } } private static void Write(Pending p) { if (_mainThread) { Save(p); return; } Interlocked.Increment(ref _writing); if (!ThreadPool.QueueUserWorkItem(delegate { Background(p); })) { Interlocked.Decrement(ref _writing); Save(p); } } private static void Background(Pending p) { try { Stopwatch stopwatch = Stopwatch.StartNew(); int num = GC.CollectionCount(0); p.File.Save(); p.Written?.Invoke(); Interlocked.Exchange(ref _busyInARow, 0); double totalMilliseconds = stopwatch.Elapsed.TotalMilliseconds; if (totalMilliseconds > 100.0 || Perf.On) { Plugin.Log.LogInfo((object)($"[DGP-SAVE] {Path.GetFileName(p.File.ConfigFilePath)} written in {totalMilliseconds:0.0} ms " + $"on a worker thread (garbage collections meanwhile: {GC.CollectionCount(0) - num}).")); } } catch (IOException ex) { Plugin.Log.LogDebug((object)("Config save postponed: " + ex.Message)); if (Interlocked.Increment(ref _busyInARow) == 10) { Plugin.Log.LogWarning((object)(Path.GetFileName(p.File.ConfigFilePath) + " could not be saved for about " + $"{10} s ({ex.Message}); still retrying. Settings apply but may not be kept.")); } RetryOnMainThread(p); } catch (Exception ex2) { _mainThread = true; Plugin.Log.LogWarning((object)("Saving the config on a worker thread failed (" + ex2.GetType().Name + ": " + ex2.Message + "); it is saved on the game thread from now on.")); RetryOnMainThread(p); } finally { Interlocked.Decrement(ref _writing); } } private static void RetryOnMainThread(Pending p) { ThreadingHelper.Instance.StartSyncInvoke((Action)delegate { Request(p.File, p.Written); }); } private static void Save(Pending p) { try { p.File.Save(); p.Written?.Invoke(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not save " + Path.GetFileName(p.File.ConfigFilePath) + ": " + ex.Message)); } } } internal sealed class ConfigWatcher : IDisposable { private readonly ConfigFile _config; private readonly FileSystemWatcher _watcher; private readonly object _known = new object(); private DateTime _knownWrite; private long _knownLength = -1L; private bool _reloading; public int Reloads { get; private set; } public ConfigWatcher(ConfigFile config) { _config = config; Remember(); _config.SettingChanged += OnSettingChanged; _watcher = new FileSystemWatcher(Path.GetDirectoryName(config.ConfigFilePath), Path.GetFileName(config.ConfigFilePath)) { NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite), SynchronizingObject = ThreadingHelper.SynchronizingObject }; _watcher.Changed += OnFileEvent; _watcher.Created += OnFileEvent; _watcher.Renamed += OnFileEvent; _watcher.EnableRaisingEvents = true; } public void Dispose() { _config.SettingChanged -= OnSettingChanged; _watcher.EnableRaisingEvents = false; _watcher.Dispose(); } private void OnSettingChanged(object sender, SettingChangedEventArgs e) { if (!_reloading) { ConfigSaver.Request(_config, Remember); } } private void OnFileEvent(object sender, FileSystemEventArgs e) { try { if (ConfigSaver.Writing) { return; } FileInfo fileInfo = new FileInfo(_config.ConfigFilePath); bool flag; lock (_known) { flag = fileInfo.Exists && fileInfo.LastWriteTimeUtc == _knownWrite && fileInfo.Length == _knownLength; } if (!fileInfo.Exists || flag) { return; } Reloads++; Plugin.Log.LogInfo((object)("Reloading " + Path.GetFileName(_config.ConfigFilePath))); Remember(); _reloading = true; try { _config.Reload(); } finally { _reloading = false; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not read " + Path.GetFileName(_config.ConfigFilePath) + "; check its entries. (" + ex.Message + ")")); } } private void Remember() { try { FileInfo fileInfo = new FileInfo(_config.ConfigFilePath); lock (_known) { _knownWrite = (fileInfo.Exists ? fileInfo.LastWriteTimeUtc : DateTime.MinValue); _knownLength = (fileInfo.Exists ? fileInfo.Length : (-1)); } } catch (IOException) { lock (_known) { _knownLength = -1L; } } } } internal sealed class Guard { private const int MaxFailures = 5; private const float Window = 120f; private static readonly float[] RetryDelays = new float[4] { 1f, 4f, 15f, 60f }; private static readonly List<Guard> Shared = new List<Guard>(); private readonly string _name; private readonly bool _keepTrying; private int _failures; private float _windowStart = float.NegativeInfinity; private float _retryAt; public bool Off { get; private set; } public bool Ready { get { if (!Off) { return Time.realtimeSinceStartup >= _retryAt; } return false; } } public Guard(string name, bool shared = false, bool keepTrying = false) { _name = name; _keepTrying = keepTrying; if (shared) { Shared.Add(this); } } public static void ResetShared() { foreach (Guard item in Shared) { item.Off = false; item._failures = 0; item._windowStart = float.NegativeInfinity; item._retryAt = 0f; } } public bool Fail(Exception ex) { float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup - _windowStart > 120f) { _failures = 0; _windowStart = realtimeSinceStartup; } _failures++; if (_failures >= 5) { if (_keepTrying) { _retryAt = realtimeSinceStartup + RetryDelays[RetryDelays.Length - 1]; if (_failures == 5) { Plugin.Log.LogError((object)(_name + ": keeps failing, retrying every minute. Last error in " + Where(ex) + ": " + ex?.Message)); } return false; } Off = true; Plugin.Log.LogError((object)(_name + ": switched off after repeated errors. Last error in " + Where(ex) + ": " + ex?.Message)); return true; } float num = RetryDelays[Math.Min(_failures - 1, RetryDelays.Length - 1)]; _retryAt = realtimeSinceStartup + num; if (_failures == 1) { Plugin.Log.LogError((object)$"{_name}: error, paused for {num:0} s and then retried: {ex}"); } else { Plugin.Log.LogWarning((object)$"{_name}: error again ({_failures}), retrying in {num:0} s: {ex?.Message}"); } return false; } private static string Where(Exception ex) { MethodBase methodBase = ex?.TargetSite; if (!(methodBase != null)) { return "?"; } return ((methodBase.DeclaringType != null) ? (methodBase.DeclaringType.Name + ".") : string.Empty) + methodBase.Name; } } internal enum MeterStyle { DemigodPanel, NorseDemigods } [BepInPlugin("com.rdmods.norsedemigodsui", "NorseDemigodsUI", "0.8.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "com.rdmods.norsedemigodsui"; public const string Name = "NorseDemigodsUI"; public const string Version = "0.8.2"; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> RunestoneRequired; internal static ConfigEntry<bool> InfusionSpoilers; internal static ConfigEntry<KeyboardShortcut> PanelKey; internal static ConfigEntry<bool> ShowAbilityBar; internal static ConfigEntry<bool> ShowSpecialAttacks; internal static ConfigEntry<Vector2> BarOffset; internal static ConfigEntry<float> BarScale; internal static ConfigEntry<MeterStyle> Meters; internal static ConfigEntry<bool> ShowEnergyBar; internal static ConfigEntry<bool> ShowXpBar; internal static ConfigEntry<bool> ShowCompanionBars; internal static ConfigEntry<Vector2> CompanionsOffset; internal static ConfigEntry<float> CompanionsScale; internal static ConfigEntry<Vector2> MetersOffset; internal static ConfigEntry<float> MetersScale; internal static ConfigEntry<int> EnergyBarWidth; internal static ConfigEntry<int> XpBarWidth; internal static ConfigEntry<int> CompanionBarWidth; private Harmony _harmony; private GameObject _uiRoot; private ConfigWatcher _watcher; private const string General = "01 - General"; private const string Runestone = "02 - Runestone"; private const string Bar = "03 - Ability Bar"; private const string MetersSection = "04 - Meters"; private const string Companions = "05 - Companions"; internal const string DiagnosticsSection = "06 - Diagnostics"; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; if (GUIManager.IsHeadless()) { ((Behaviour)this).enabled = false; Log.LogInfo((object)"NorseDemigodsUI 0.8.2 is client-only; it does nothing on a dedicated server."); return; } BindConfig(); Loc.Register(); _harmony = new Harmony("com.rdmods.norsedemigodsui"); Hook(typeof(NdEvents), "god change events (a 10/s check takes over)"); Hook(typeof(GodChosenMessage), "the god chosen message"); Hook(typeof(NdMeterVisibility), "hiding its meters at god setup"); Hook(typeof(StatusIcons.CooldownHook), "cooldown icons"); Hook(typeof(StatusIcons.WolfHook), "the wolf's status icon"); Hook(typeof(StatusIcons.ShieldHook), "the elemental shield's status icon"); Hook(typeof(RunestoneRules.SpawnGiftHook), "the runestone spawn gift"); Hook(typeof(RunestoneRules.OldRunestoneHook), "opening the panel from an old runestone"); Hook(typeof(HuginTip), "the Hugin tip"); Hook(typeof(ConfigSaveFence), "waiting for a config save when joining or leaving a world"); GUIManager.OnCustomGUIAvailable += BuildUi; Step(RunestoneRules.Init, "the runestone rules"); Step(CheckNdVersion, "the version check"); Step(NdBridge.Init, "god switching from the panel"); Log.LogInfo((object)"NorseDemigodsUI 0.8.2 loaded."); } private void BindConfig() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; ConfigMigration configMigration = new ConfigMigration(((BaseUnityPlugin)this).Config); bool num = !configMigration.CanRead || configMigration.InFile("04 - Meters", "Position") || configMigration.InFile("5 - Meters", "Offset"); Enabled = Bind("01 - General", "Enabled", value: true, "Shows the ability bar, the Energy, XP and companion bars and the Demigod panel. Only affects you."); PanelKey = Bind<KeyboardShortcut>("01 - General", "Panel Key", new KeyboardShortcut((KeyCode)107, Array.Empty<KeyCode>()), "Opens and closes the Demigod panel. Norse Demigods uses P for its Teleport ability by default."); InfusionSpoilers = Bind("01 - General", "Infusion Spoilers", value: false, "Off: how to infuse each god's abilities is a riddle. On: the panel names the exact item, its recipe and the workstation. Only affects you."); RunestoneRequired = Bind("02 - Runestone", "Runestone Required", value: false, "Off: you get no runestone and can't craft one; you choose and change gods in the Demigod panel. On: Norse Demigods gives the runestone at first spawn and it can be crafted, and using it opens the panel. Only affects you."); ShowAbilityBar = Bind("03 - Ability Bar", "Show Ability Bar", value: true, "Shows your god's abilities, keys, costs and cooldowns above the bottom of the screen."); ShowSpecialAttacks = Bind("03 - Ability Bar", "Show Special Attacks", value: true, "Adds small slots for weapon special attacks and Teleport after the four ability slots."); BarScale = Bind("03 - Ability Bar", "Scale", 1f, "Size of the ability bar (1 = normal).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f)); BarOffset = Bind<Vector2>("03 - Ability Bar", "Position", new Vector2(0f, 150f), "The bar's centre, in UI units from the bottom centre of the screen. Set it by dragging the bar while the inventory or the menu is open.", null, advanced: true); Meters = Bind("04 - Meters", "Meter Style", MeterStyle.DemigodPanel, "DemigodPanel: our Energy, XP and companion bars replace Norse Demigods' meters. NorseDemigods: Norse Demigods' own meters, and ours are off."); ShowEnergyBar = Bind("04 - Meters", "Show Energy Bar", value: true, "Shows the Energy bar (Meter Style DemigodPanel)."); ShowXpBar = Bind("04 - Meters", "Show XP Bar", value: true, "Shows the XP bar (Meter Style DemigodPanel)."); MetersScale = Bind("04 - Meters", "Scale", 1f, "Size of the Energy and XP bars (1 = normal).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f)); MetersOffset = Bind<Vector2>("04 - Meters", "Position", new Vector2(0f, 94f), "The Energy and XP bars' centre, in UI units from the bottom centre of the screen. Set it by dragging the bars while the inventory or the menu is open.", null, advanced: true); EnergyBarWidth = Bind("04 - Meters", "Energy Bar Width", 216, "Width of the Energy bar, in UI units (before Scale).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(80, 600), advanced: true); XpBarWidth = Bind("04 - Meters", "XP Bar Width", 216, "Width of the XP bar, in UI units (before Scale).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(80, 600), advanced: true); ShowCompanionBars = Bind("05 - Companions", "Show Companion Bars", value: true, "Shows bars for your wolf, minions, necks, Stone Golem and surtlings (Meter Style DemigodPanel)."); CompanionsScale = Bind("05 - Companions", "Scale", 1f, "Size of the companion bars (1 = normal).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f)); CompanionsOffset = Bind<Vector2>("05 - Companions", "Position", new Vector2(-150f, 215f), "The companion bars' lower-left corner, in UI units from the bottom centre of the screen. Set it by dragging the bars while a companion is out and the inventory or the menu is open.", null, advanced: true); CompanionBarWidth = Bind("05 - Companions", "Bar Width", 156, "Width of each companion bar, in UI units (before Scale; the icon is extra).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(80, 400), advanced: true); Perf.Bind(((BaseUnityPlugin)this).Config, "06 - Diagnostics"); Migrate(configMigration); if (!num) { MetersScale.Value = BarScale.Value; MetersOffset.Value = BarOffset.Value + new Vector2(0f, -56f * BarScale.Value); } ((BaseUnityPlugin)this).Config.Save(); _watcher = new ConfigWatcher(((BaseUnityPlugin)this).Config); RunestoneRequired.SettingChanged += OnRunestoneSetting; InfusionSpoilers.SettingChanged += OnTextSetting; } private static void OnTextSetting(object sender, EventArgs e) { NdEvents.MarkConfigChanged(); } private ConfigEntry<T> Bind<T>(string section, string key, T value, string description, AcceptableValueBase range = null, bool advanced = false) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) return ConfigFileExtensions.BindConfigInOrder<T>(((BaseUnityPlugin)this).Config, section, key, value, description, false, false, true, range, (Action<ConfigEntryBase>)null, (!advanced) ? ((ConfigurationManagerAttributes)null) : new ConfigurationManagerAttributes { IsAdvanced = true }); } private void Migrate(ConfigMigration m) { m.Move("4 - Ability Bar", "Meter Style", (ConfigEntryBase)(object)Meters); m.Move("4 - Ability Bar", "Show Energy Bar", (ConfigEntryBase)(object)ShowEnergyBar); m.Move("4 - Ability Bar", "Show XP Bar", (ConfigEntryBase)(object)ShowXpBar); m.Move("4 - Ability Bar", "Show Companion Bars", (ConfigEntryBase)(object)ShowCompanionBars); m.Move("4 - Ability Bar", "Companions Offset", (ConfigEntryBase)(object)CompanionsOffset); m.Move("5 - Diagnostics", "Enabled", (ConfigEntryBase)(object)Perf.EnabledEntry); m.Move("1 - General", "Enabled", (ConfigEntryBase)(object)Enabled); m.Move("3 - Panel", "Panel Key", (ConfigEntryBase)(object)PanelKey); m.Move("2 - Runestone", "Runestone Required", (ConfigEntryBase)(object)RunestoneRequired); m.Move("4 - Ability Bar", "Show Ability Bar", (ConfigEntryBase)(object)ShowAbilityBar); m.Move("4 - Ability Bar", "Show Special Attacks", (ConfigEntryBase)(object)ShowSpecialAttacks); m.Move("4 - Ability Bar", "Scale", (ConfigEntryBase)(object)BarScale); m.Move("4 - Ability Bar", "Offset", (ConfigEntryBase)(object)BarOffset); m.Move("5 - Meters", "Meter Style", (ConfigEntryBase)(object)Meters); m.Move("5 - Meters", "Show Energy Bar", (ConfigEntryBase)(object)ShowEnergyBar); m.Move("5 - Meters", "Show XP Bar", (ConfigEntryBase)(object)ShowXpBar); m.Move("5 - Meters", "Scale", (ConfigEntryBase)(object)MetersScale); m.Move("5 - Meters", "Offset", (ConfigEntryBase)(object)MetersOffset); m.Move("5 - Meters", "Energy Bar Width", (ConfigEntryBase)(object)EnergyBarWidth); m.Move("5 - Meters", "XP Bar Width", (ConfigEntryBase)(object)XpBarWidth); m.Move("6 - Companions", "Show Companion Bars", (ConfigEntryBase)(object)ShowCompanionBars); m.Move("6 - Companions", "Scale", (ConfigEntryBase)(object)CompanionsScale); m.Move("6 - Companions", "Offset", (ConfigEntryBase)(object)CompanionsOffset); m.Move("6 - Companions", "Bar Width", (ConfigEntryBase)(object)CompanionBarWidth); m.Move("7 - Diagnostics", "Enabled", (ConfigEntryBase)(object)Perf.EnabledEntry); m.DropSections("1 - General", "2 - Runestone", "3 - Panel", "4 - Ability Bar", "5 - Meters", "6 - Companions", "7 - Diagnostics", "5 - Diagnostics"); } private void Hook(Type group, string feature) { try { _harmony.PatchAll(group); } catch (Exception ex) { Log.LogWarning((object)("Could not hook Norse Demigods for " + feature + "; that part is off, everything else works. (" + ex.GetType().Name + ": " + ex.Message + ")")); } } private static void Step(Action step, string feature) { try { step(); } catch (Exception ex) { Log.LogWarning((object)("Norse Demigods setup for " + feature + " failed; that part is off. (" + ex.GetType().Name + ": " + ex.Message + ")")); } } private static void OnRunestoneSetting(object sender, EventArgs e) { RunestoneRules.Apply(); } private static void CheckNdVersion() { if (Chainloader.PluginInfos.TryGetValue("NorseDemigods", out var value)) { Version version = value.Metadata.Version; if (version.Major != 1 || version.Minor != 7) { Log.LogWarning((object)$"Built for Norse Demigods 1.7.x, found {version}. If something breaks, the panel switches itself off."); } } } private void BuildUi() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown if (!((Object)(object)_uiRoot != (Object)null) && !((Object)(object)GUIManager.CustomGUIFront == (Object)null) && Utils.InMainScene()) { _uiRoot = new GameObject("DemigodPanel"); _uiRoot.AddComponent<UiHost>(); } } private void Update() { ConfigSaver.Tick(); } private void OnApplicationQuit() { ConfigSaver.FlushNow(); } private void OnDestroy() { if (RunestoneRequired == null) { return; } ConfigSaver.FlushNow(); GUIManager.OnCustomGUIAvailable -= BuildUi; RunestoneRequired.SettingChanged -= OnRunestoneSetting; if (InfusionSpoilers != null) { InfusionSpoilers.SettingChanged -= OnTextSetting; } RunestoneRules.Shutdown(); _watcher?.Dispose(); if ((Object)(object)_uiRoot != (Object)null) { Object.Destroy((Object)(object)_uiRoot); } try { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception arg) { Log.LogError((object)$"Unpatch failed: {arg}"); } } } internal static class Loc { private const string Resource = "DemigodPanel.Assets.Translations.English.json"; public static void Register() { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DemigodPanel.Assets.Translations.English.json"); if (stream == null) { Plugin.Log.LogWarning((object)"English translation resource missing."); return; } using StreamReader streamReader = new StreamReader(stream); LocalizationManager.Instance.GetLocalization().AddJsonFile("English", streamReader.ReadToEnd()); KeyLabel.Translate = KeyName; } private static string KeyName(string keyCode) { string text = "$dgp_keyname_" + keyCode; string text2 = T(text); if (!Missing(text2) && !(text2 == text)) { return text2; } return null; } public static string T(string token) { if (Localization.instance == null) { return token; } return Localization.instance.Localize(token); } public static string F(string token, params object[] args) { string text = T(token); try { return string.Format(text, args); } catch (FormatException) { return text; } } public static string KeyHint(string label) { return "[<color=yellow><b>" + label + "</b></color>]"; } public static bool Missing(string text) { if (text != null) { if (text.StartsWith("[")) { return text.EndsWith("]"); } return false; } return true; } } internal static class Utils { private static GameObject _selected; private static InputField _field; private static TMP_InputField _tmpField; public static bool InMainScene() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).name == "main"; } public static bool HotkeysAllowed() { if ((Object)(object)Player.m_localPlayer == (Object)null || Menu.IsVisible() || InventoryGui.IsVisible() || StoreGui.IsVisible() || Minimap.IsOpen() || TextInput.IsVisible() || Console.IsVisible() || Minimap.InTextInput()) { return false; } Chat instance = Chat.instance; if ((Object)(object)instance != (Object)null && instance.HasFocus()) { return false; } EventSystem current = EventSystem.current; GameObject val = (((Object)(object)current != (Object)null) ? current.currentSelectedGameObject : null); if ((Object)(object)val == (Object)null) { _selected = null; return true; } if ((Object)(object)val != (Object)(object)_selected) { _selected = val; _field = val.GetComponent<InputField>(); _tmpField = val.GetComponent<TMP_InputField>(); } if (!((Object)(object)_field != (Object)null) || !_field.isFocused) { if ((Object)(object)_tmpField != (Object)null) { return !_tmpField.isFocused; } return true; } return false; } public static bool Pressed(KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, false)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers) { if (!ZInput.GetKey(modifier, false)) { return false; } } return true; } public static Sprite ToSprite(Texture2D texture) { //IL_0022: 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) if (!((Object)(object)texture == (Object)null)) { return Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0); } return null; } public static byte[] ReadResource(string name) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name); if (stream == null) { return null; } byte[] array = new byte[stream.Length]; int i; int num; for (i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num <= 0) { break; } } return (i == array.Length) ? array : null; } } } namespace DemigodPanel.Ui { internal sealed class AbilitiesTab : PanelTab { private readonly NumberSheet _sheet = new NumberSheet(); private const int PerRow = 5; private const float CellW = 84f; private const float CellH = 104f; private const float Tile = 56f; private RectTransform _list; private DetailsCard _details; private FigureView _figure; private Demigod _god; private readonly List<object> _items = new List<object>(); private readonly List<Image> _marks = new List<Image>(); private readonly List<Text> _keyLabels = new List<Text>(); private readonly List<Type> _layout = new List<Type>(); private readonly List<Type> _now = new List<Type>(); private int _abilityCount; private int _pinned = -1; private int _hovered = -1; private readonly HoverHold _hold = new HoverHold(); private object _shownSubject; private int _shownLevel = -1; private int _shownCooldown = -1; private int _shownEnergy = -1; private int _shownGear; private int _shownActiveMask = -1; private int _shownConfig = -1; private int _shownUnarmed = -1; private int _shownTrophies = -1; private bool _shownActive; private bool _shownInfused; public override void Build(DemigodPanelView view, RectTransform root) { UiKit.Inset((Transform)(object)root, "LeftBg", 30f, 190f, 430f, 520f); _list = UiKit.Box((Transform)(object)root, "List", 30f, 190f, 430f, 520f); _details = new DetailsCard((Transform)(object)root, 475f, 190f, 520f, 520f); _figure = new FigureView((Transform)(object)root, 1010f, 190f, 360f, 520f); } public override void Rebuild(Demigod god) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) _god = god; _shownSubject = null; _shownLevel = -1; if ((Object)(object)god == (Object)null) { Clear(); _figure.Show(null, string.Empty); return; } _figure.Show(god.DemigodName, NdBridge.GodDisplayName(god.DemigodName)); List<DemigodAbility> list = AbilityView.Sorted(god.Abilities?.Values); if (SameLayout(list, god.DefaultAttributes)) { Rebind(list, god.DefaultAttributes); return; } Clear(); float num = 10f; UiKit.Text((Transform)(object)_list, Loc.T("$dgp_active"), 18, UiKit.Orange, (TextAnchor)0, 14f, num, 402f, 24f, bold: true); num += 32f; for (int i = 0; i < list.Count; i++) { AddTile(list[i], 8f + (float)(i % 5) * 84f, num + (float)(i / 5) * 104f); } _abilityCount = list.Count; num += (float)((list.Count + 5 - 1) / 5) * 104f + 4f; UiKit.Text((Transform)(object)_list, Loc.T("$dgp_passive"), 18, UiKit.Orange, (TextAnchor)0, 14f, num, 402f, 24f, bold: true); num += 30f; if (god.DefaultAttributes != null) { foreach (DemigodAttribute value in god.DefaultAttributes.Values) { if (value != null) { AddTraitRow(value, num); num += 27f; } } } _pinned = ((list.Count <= 0) ? (-1) : 0); UpdateHighlights(); } private void Clear() { _items.Clear(); _marks.Clear(); _keyLabels.Clear(); _layout.Clear(); _abilityCount = 0; _pinned = -1; _hovered = -1; for (int num = ((Transform)_list).childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)((Transform)_list).GetChild(num)).gameObject); } } private bool SameLayout(List<DemigodAbility> abilities, Dictionary<Type, DemigodAttribute> traits) { _now.Clear(); foreach (DemigodAbility ability in abilities) { _now.Add(((object)ability).GetType()); } if (traits != null) { foreach (DemigodAttribute value in traits.Values) { if (value != null) { _now.Add(((object)value).GetType()); } } } return RowLayout.Same(_layout, _now); } private void Rebind(List<DemigodAbility> abilities, Dictionary<Type, DemigodAttribute> traits) { for (int i = 0; i < abilities.Count; i++) { _items[i] = abilities[i]; } if (traits != null) { int count = abilities.Count; foreach (DemigodAttribute value in traits.Values) { if (value != null) { _items[count++] = value; } } } RefreshKeyLabels(); UpdateHighlights(); } private void AddTile(DemigodAbility ability, float x, float y) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) int index = _items.Count; RectTransform obj = UiKit.Box((Transform)(object)_list, ((object)ability).GetType().Name, x, y, 84f, 100f); Image val = ((Component)obj).gameObject.AddComponent<Image>(); val.sprite = UiKit.White; ((Graphic)val).color = Color.clear; DemigodPanelView.Place(SlotArt.Socket((Transform)(object)obj, "Socket", AbilityView.Icon(ability), 56f, out var _), 14f, 4f, 56f, 56f); Text item = UiKit.Text((Transform)(object)obj, AbilityView.KeyLabelOf(ability), 11, UiKit.Gold, (TextAnchor)1, 0f, 62f, 84f, 14f, bold: true); UiKit.Text((Transform)(object)obj, ability.DisplayName, 12, Color.white, (TextAnchor)1, 0f, 76f, 84f, 30f).lineSpacing = 0.85f; _items.Add(ability); _marks.Add(val); _keyLabels.Add(item); _layout.Add(((object)ability).GetType()); UiKit.Hover(((Component)obj).gameObject, delegate { Hover(index); }, delegate { Unhover(index); }, delegate { Pin(index); }); } private void AddTraitRow(DemigodAttribute trait, float y) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) int index = _items.Count; RectTransform obj = UiKit.Box((Transform)(object)_list, ((object)trait).GetType().Name, 8f, y, 414f, 25f); Image val = ((Component)obj).gameObject.AddComponent<Image>(); val.sprite = UiKit.White; ((Graphic)val).color = UiKit.Row; UiKit.Text((Transform)(object)obj, "◆ " + trait.DisplayName, 15, UiKit.Ice, (TextAnchor)3, 10f, 0f, 394f, 25f); _items.Add(trait); _marks.Add(val); _layout.Add(((object)trait).GetType()); UiKit.Hover(((Component)obj).gameObject, delegate { Hover(index); }, delegate { Unhover(index); }, delegate { Pin(index); }); } private void Hover(int index) { _hold.Enter(); _hovered = index; UpdateHighlights(); Refresh(); } private void Unhover(int index) { if (_hovered == index) { _hold.Exit(); } } public override void Tick() { if (_hold.Expired() && _hovered >= 0) { _hovered = -1; UpdateHighlights(); Refresh(); } } public override void Hidden() { _hold.Enter(); _hovered = -1; UpdateHighlights(); } private void Pin(int index) { _pinned = index; UpdateHighlights(); Refresh(); } private void UpdateHighlights() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < _marks.Count; i++) { Image val = _marks[i]; if (!((Object)(object)val == (Object)null)) { Color val2 = ((i >= _abilityCount) ? UiKit.Row : Color.clear); ((Graphic)val).color = ((i == _pinned) ? UiKit.RowSelected : ((i == _hovered) ? UiKit.RowHover : val2)); } } } private void RefreshKeyLabels() { for (int i = 0; i < _keyLabels.Count && i < _items.Count; i++) { object obj = _items[i]; DemigodAbility val = (DemigodAbility)((obj is DemigodAbility) ? obj : null); if (val != null) { string text = AbilityView.KeyLabelOf(val); if (_keyLabels[i].text != text) { _keyLabels[i].text = text; } } } } private object Item(int index) { if (index < 0 || index >= _items.Count) { return null; } return _items[index]; } public override void Refresh() { if ((Object)(object)Root == (Object)null || !Root.activeInHierarchy) { return; } Player player = Player.m_localPlayer; if ((Object)(object)_god == (Object)null || (Object)(object)player == (Object)null) { _details.Show(null, null, string.Empty, string.Empty, string.Empty); return; } if (_shownConfig != NdEvents.ConfigVersion) { RefreshKeyLabels(); } object obj = Item(_hovered) ?? Item(_pinned); int level = Mathf.FloorToInt(NdBridge.Level(player)); bool infused = NdBridge.AbilitiesInfused(player); int num = -1; bool flag = false; DemigodAbility val = (DemigodAbility)((obj is DemigodAbility) ? obj : null); if (val != null) { StatusEffect statusEffect = ((Character)player).GetSEMan().GetStatusEffect(AbilityView.CooldownHash(val)); num = (((Object)(object)statusEffect != (Object)null) ? Mathf.CeilToInt(statusEffect.GetRemaningTime()) : (-1)); flag = val.IsActive; } SE_Demigod val2 = NdBridge.StatusOf(player); int num2 = (((Object)(object)val2 != (Object)null) ? val2.Energy : (-1)); int num3 = GearStamp(player); int num4 = ActiveMask(_god); int num5 = Mathf.FloorToInt(NdBridge.SkillLevel(player, (SkillType)11)); int count = player.m_trophies.Count; if (obj == _shownSubject && level == _shownLevel && num == _shownCooldown && flag == _shownActive && infused == _shownInfused && num2 == _shownEnergy && num3 == _shownGear && num4 == _shownActiveMask && _shownConfig == NdEvents.ConfigVersion && num5 == _shownUnarmed && count == _shownTrophies) { return; } bool flag2 = obj == _shownSubject && _shownLevel >= 0 && level > _shownLevel; _shownEnergy = num2; _shownGear = num3; _shownUnarmed = num5; _shownTrophies = count; _shownActiveMask = num4; _shownConfig = NdEvents.ConfigVersion; _shownSubject = obj; _shownLevel = level; _shownCooldown = num; _shownActive = flag; _shownInfused = infused; _sheet.SetPlayer(player, asOtherGod: false); if (!flag2) { _sheet.ForgetValues(); } string pulsed = null; DemigodAbility val3 = (DemigodAbility)((obj is DemigodAbility) ? obj : null); if (val3 == null) { DemigodAttribute val4 = (DemigodAttribute)((obj is DemigodAttribute) ? obj : null); if (val4 != null) { string god = (((Object)(object)_god != (Object)null) ? _god.DemigodName : null); string body = _sheet.BuildWithPulse(delegate { _sheet.Begin(); return Texts.TraitBody(val4, level, live: true, god, _sheet); }, out pulsed); _details.Show(val4, null, val4.DisplayName, Loc.T("$dgp_kind_trait"), body, _sheet, flag2 ? pulsed : null); } else { _details.Show(null, null, string.Empty, string.Empty, Loc.T("$dgp_hover_hint")); } } else { string body2 = _sheet.BuildWithPulse(delegate { _sheet.Begin(); return Texts.AbilityBody(val3, player, level, infused, _sheet); }, out pulsed); _details.Show(val3, AbilityView.Icon(val3), val3.DisplayName, Texts.KindLabel(val3) + " · " + AbilityView.KeyLabelOf(val3), body2, _sheet, flag2 ? pulsed : null, round: true); } } internal static int ActiveMask(Demigod god) { int num = 0; int num2 = 1; if (god?.Abilities != null) { foreach (DemigodAbility value in god.Abilities.Values) { if (value.IsActive) { num |= num2; } num2 <<= 1; } } return num; } internal static int GearStamp(Player p) { int num = ((17 * 31 + ((((Humanoid)p).m_helmetItem != null) ? RuntimeHelpers.GetHashCode(((Humanoid)p).m_helmetItem) : 0)) * 31 + ((((Humanoid)p).m_chestItem != null) ? RuntimeHelpers.GetHashCode(((Humanoid)p).m_chestItem) : 0)) * 31 + ((((Humanoid)p).m_legItem != null) ? RuntimeHelpers.GetHashCode(((Humanoid)p).m_legItem) : 0); ItemData currentWeapon = ((Humanoid)p).GetCurrentWeapon(); return num * 31 + ((currentWeapon != null) ? RuntimeHelpers.GetHashCode(currentWeapon) : 0); } } internal sealed class AbilityBar { private sealed class Slot { public DemigodAbility Ability; public int CooldownHash; public bool Small; public Image Icon; public Image Tint; public Image Sweep; public Image ActiveFrame; public TMP_Text CooldownText; public TMP_Text CostText; public Image CostBadge; public float CooldownEnd; public float CooldownTotal; public int SweepSteps; public int ShownStep; public int ShownSeconds = -1; public bool Dim; public bool Short; public EitrUse Eitr; public int EnergyNeeded; } private const float BigSize = 64f; private const float SmallSize = 42f; private const float Gap = 8f; private const float TickSeconds = 0.1f; private static readonly string[] Seconds = BuildSeconds(); private static readonly Color ShortTint = new Color(0.08f, 0.16f, 0.42f, 0.7f); private static readonly Color DimIcon = new Color(0.45f, 0.45f, 0.45f, 0.9f); private bool _costsInfused; private float _costsUnarmed = -1f; private readonly List<Slot> _slots = new List<Slot>(); private RectTransform _root; private float _tick; private Demigod _builtFor; private bool _anyCooldown; public bool HasGod => (Object)(object)_builtFor != (Object)null; public int Version { get; private set; } public RectTransform Root { get { if (!((Object)(object)_root != (Object)null) || !((Component)_root).gameObject.activeInHierarchy) { return null; } return _root; } } public int SlotCount => _slots.Count; public RectTransform Bounds => Root; public RectTransform SlotRect(int i) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown return (RectTransform)((Component)_slots[i].Icon).transform.parent; } public DemigodAbility SlotAbility(int i) { if (i < 0 || i >= _slots.Count) { return null; } return _slots[i].Ability; } public bool Shows(DemigodAbility ability) { if (ability == null || (Object)(object)Root == (Object)null) { return false; } Type type = ((object)ability).GetType(); foreach (Slot slot in _slots) { if (slot.Ability != null && ((object)slot.Ability).GetType() == type) { return true; } } return false; } public void Place(Vector2 offset) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root != (Object)null && _root.anchoredPosition != offset) { _root.anchoredPosition = offset; } } public void Rebuild(Demigod god) { long start = Perf.Begin(); long mem = Perf.BeginMem(); RebuildInner(god); Perf.End(Perf.Scope.BarRebuild, start, mem); } private void RebuildInner(Demigod god) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_00a4: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: 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_01e0: 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) Destroy(); _builtFor = god; Hud instance = Hud.instance; if ((Object)(object)god == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)instance.m_rootObject == (Object)null) { return; } GameObject val = new GameObject("DemigodAbilityBar", new Type[2] { typeof(RectTransform), typeof(Canvas) }); _root = (RectTransform)val.transform; ((Transform)_root).SetParent(instance.m_rootObject.transform, false); RectTransform root = _root; RectTransform root2 = _root; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0f); root2.anchorMax = val2; root.anchorMin = val2; _root.pivot = new Vector2(0.5f, 0.5f); List<DemigodAbility> list = AbilityView.Sorted(god.Abilities?.Values); float num = 0f; bool flag = false; foreach (DemigodAbility item in list) { bool flag2 = AbilityView.Kind(item) != AbilityKind.Slot; if (!flag2 || Plugin.ShowSpecialAttacks.Value) { if (flag2 && !flag) { num += 16f; flag = true; } float num2 = (flag2 ? 42f : 64f); _slots.Add(BuildSlot(item, num, num2, flag2)); num += num2 + 8f; } } float num3 = Mathf.Max(0f, num - 8f); _root.sizeDelta = new Vector2(num3, 86f); foreach (Slot slot in _slots) { RectTransform val3 = (RectTransform)((Component)slot.Icon).transform.parent; val3.anchoredPosition += new Vector2((0f - num3) * 0.5f, 0f); } _costsInfused = NdBridge.AbilitiesInfused(Player.m_localPlayer); RefreshCosts(Player.m_localPlayer); ApplyLayout(); Tick(Player.m_localPlayer); } private void RefreshCosts(Player player) { _costsUnarmed = (((Object)(object)player != (Object)null) ? NdBridge.SkillLevel(player, (SkillType)11) : 0f); foreach (Slot slot in _slots) { slot.Eitr = AbilityView.Eitr(slot.Ability, player, _costsInfused); slot.EnergyNeeded = AbilityView.EnergyNeeded(slot.Ability, _costsInfused); if ((Object)(object)slot.CostText != (Object)null) { string text = ((slot.EnergyNeeded > 0) ? slot.EnergyNeeded.ToString() : string.Empty); if (slot.CostText.text != text) { slot.CostText.text = text; } if ((Object)(object)slot.CostBadge != (Object)null && ((Behaviour)slot.CostBadge).enabled != text.Length > 0) { ((Behaviour)slot.CostBadge).enabled = text.Length > 0; } } } } public void Destroy() { ShowCooldownsInStatusList(); if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)((Component)_root).gameObject); } _root = null; _slots.Clear(); Version++; _builtFor = null; _anyCooldown = false; } public void ApplyLayout() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_root == (Object)null)) { float value = Plugin.BarScale.Value; ((Transform)_root).localScale = new Vector3(value, value, 1f); _root.anchoredPosition = UiKit.OnScreen(_root, Plugin.BarOffset.Value); } } public void SetVisible(bool visible) { if ((Object)(object)_root != (Object)null && ((Component)_root).gameObject.activeSelf != visible) { ((Component)_root).gameObject.SetActive(visible); if (!visible) { ShowCooldownsInStatusList(); } } } private void ShowCooldownsInStatusList() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || _slots.Count == 0) { return; } SEMan sEMan = ((Character)localPlayer).GetSEMan(); foreach (Slot slot in _slots) { StatusEffect statusEffect = sEMan.GetStatusEffect(slot.CooldownHash); if ((Object)(object)statusEffect != (Object)null && statusEffect.m_hidden) { statusEffect.m_hidden = false; } } } public void Update(Player player, float dt) { if (!((Object)(object)_root == (Object)null) && ((Component)_root).gameObject.activeInHierarchy) { _tick -= dt; if (_tick <= 0f) { _tick = 0.1f; long start = Perf.Begin(); long mem = Perf.BeginMem(); Tick(player); Perf.End(Perf.Scope.BarTick, start, mem); } if (_anyCooldown) { long start2 = Perf.Begin(); long mem2 = Perf.BeginMem(); Sweep(); Perf.End(Perf.Scope.BarSweep, start2, mem2); } } } private void Tick(Player player) { //IL_003c: 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_0150: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) SE_Demigod val = NdBridge.StatusOf(player); if ((Object)(object)player == (Object)null || (Object)(object)val == (Object)null) { return; } int energy = val.Energy; float eitr = player.m_eitr; ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); SkillType skill = (SkillType)((currentWeapon == null) ? 11 : ((int)currentWeapon.m_shared.m_skillType)); SEMan sEMan = ((Character)player).GetSEMan(); _anyCooldown = false; bool flag = NdBridge.AbilitiesInfused(player); float num = NdBridge.SkillLevel(player, (SkillType)11); if (flag != _costsInfused || num != _costsUnarmed) { _costsInfused = flag; RefreshCosts(player); } foreach (Slot slot in _slots) { DemigodAbility ability = slot.Ability; StatusEffect statusEffect = sEMan.GetStatusEffect(slot.CooldownHash); if ((Object)(object)statusEffect != (Object)null && !statusEffect.m_hidden) { statusEffect.m_hidden = true; } if ((Object)(object)statusEffect != (Object)null && statusEffect.m_ttl > 0f) { slot.CooldownEnd = Time.time + statusEffect.GetRemaningTime(); slot.CooldownTotal = statusEffect.m_ttl; _anyCooldown = true; } else if (slot.CooldownEnd > 0f) { slot.CooldownEnd = 0f; SetSweep(slot, 0f, -1); } long start = Perf.Begin(); long mem = Perf.BeginMem(); bool flag2 = !AbilityView.WeaponFits(ability, skill); bool flag3 = energy < slot.EnergyNeeded || (slot.Eitr.Any && !slot.Eitr.Affordable(eitr)); Perf.End(Perf.Scope.BarTint, start, mem); if (flag2 != slot.Dim) { slot.Dim = flag2; ((Graphic)slot.Icon).color = (flag2 ? DimIcon : Color.white); } if (flag3 != slot.Short) { slot.Short = flag3; ((Behaviour)slot.Tint).enabled = flag3; } if (((Behaviour)slot.ActiveFrame).enabled != ability.IsActive) { ((Behaviour)slot.ActiveFrame).enabled = ability.IsActive; } } } private void Sweep() { float time = Time.time; bool anyCooldown = false; foreach (Slot slot in _slots) { if (!(slot.CooldownEnd <= 0f)) { float num = slot.CooldownEnd - time; if (num <= 0f) { slot.CooldownEnd = 0f; SetSweep(slot, 0f, -1); } else { anyCooldown = true; SetSweep(slot, (slot.CooldownTotal > 0f) ? (num / slot.CooldownTotal) : 0f, Mathf.CeilToInt(num)); } } } _anyCooldown = anyCooldown; } private static void SetSweep(Slot slot, float fill, int seconds) { int num = ((!(fill <= 0f)) ? Mathf.CeilToInt(Mathf.Clamp01(fill) * (float)slot.SweepSteps) : 0); if (num != slot.ShownStep) { slot.ShownStep = num; slot.Sweep.fillAmount = (float)num / (float)slot.SweepSteps; } if (seconds != slot.ShownSeconds) { slot.ShownSeconds = seconds; slot.CooldownText.text = ((seconds < 0) ? string.Empty : ((seconds < Seconds.Length) ? Seconds[seconds] : "99+")); } } private Slot BuildSlot(DemigodAbility ability, float x, float size, bool small) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: 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_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) RectTransform obj = UiKit.Box((Transform)(object)_root, ((object)ability).GetType().Name, x, 0f, size, size); Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); obj.anchorMax = val; obj.anchorMin = val; obj.pivot = new Vector2(0f, 0f); obj.anchoredPosition = new Vector2(x, -22f); float num = size * 0.0711f; float margin = (0f - size) * 0.125f * 0.5f; UiKit.Fill(((Graphic)UiKit.Image((Transform)(object)obj, "Bg", SlotArt.Back, Color.white)).rectTransform, margin); Image val2 = UiKit.Image((Transform)(object)obj, "Icon", AbilityView.Icon(ability), Color.white); val2.preserveAspect = true; UiKit.Fill(((Graphic)val2).rectTransform, num); Image val3 = UiKit.Image((Transform)(object)obj, "NotEnough", SlotArt.Disc, ShortTint); UiKit.Fill(((Graphic)val3).rectTransform, num); ((Behaviour)val3).enabled = false; RectTransform val4 = UiKit.Box((Transform)(object)obj, "Live", 0f, 0f, size, size); UiKit.Fill(val4); ((Component)val4).gameObject.AddComponent<Canvas>(); Image val5 = UiKit.Image((Transform)(object)val4, "Cooldown", SlotArt.Disc, new Color(0f, 0f, 0f, 0.65f)); val5.type = (Type)3; val5.fillMethod = (FillMethod)4; val5.fillOrigin = 2; val5.fillClockwise = false; val5.fillAmount = 0f; UiKit.Fill(((Graphic)val5).rectTransform, num); UiKit.Fill(((Graphic)UiKit.Image((Transform)(object)val4, "Ring", SlotArt.Ring, Color.white)).rectTransform); Image val6 = UiKit.Image((Transform)(object)val4, "Active", SlotArt.Glow, Color.white); UiKit.Fill(((Graphic)val6).rectTransform, margin); ((Behaviour)val6).enabled = false; TextMeshProUGUI cooldownText = UiKit.Tmp((Transform)(object)val4, "Seconds", string.Empty, small ? 17f : 24f, Color.white, (TextAlignmentOptions)514, 0f, 0f, size, size); TextMeshProUGUI obj2 = UiKit.Tmp((Transform)(object)obj, "Key", AbilityView.KeyLabelOf(ability), small ? 11f : 13f, UiKit.Gold, (TextAlignmentOptions)258, -12f, size + 1f, size + 24f, 16f); ((TMP_Text)obj2).enableAutoSizing = true; ((TMP_Text)obj2).fontSizeMin = 7f; ((TMP_Text)obj2).fontSizeMax = (small ? 11f : 13f); TMP_Text costText = null; Image val7 = null; if (!small) { float num2 = Mathf.Round(size * 0.34f); val7 = UiKit.Image((Transform)(object)val4, "CostBadge", SlotArt.Badge, Color.white); RectTransform rectTransform = ((Graphic)val7).rectTransform; Vector2 val8 = (rectTransform.pivot = Vector2.one); val = (rectTransform.anchorMin = (rectTransform.anchorMax = val8)); rectTransform.anchoredPosition = new Vector2(2f, 2f); rectTransform.sizeDelta = new Vector2(num2, num2); ((Behaviour)val7).enabled = false; costText = (TMP_Text)(object)UiKit.Tmp((Transform)(object)rectTransform, "Cost", string.Empty, 14f, UiKit.Ice, (TextAlignmentOptions)514, 0f, 0f, num2, num2); } return new Slot { Ability = ability, CooldownHash = AbilityView.CooldownHash(ability), Small = small, Icon = val2, Tint = val3, Sweep = val5, SweepSteps = Mathf.Max(24, Mathf.CeilToInt((float)Math.PI * (size - 2f * num))), ActiveFrame = val6, CooldownText = (TMP_Text)(object)cooldownText, CostText = costText, CostBadge = val7 }; } private static string[] BuildSeconds() { string[] array = new string[100]; for (int i = 0; i < array.Length; i++) { array[i] = i.ToString(); } return array; } } internal sealed class BasicsView { private static readonly string[] Topics = new string[7] { "falls", "heavy", "cap", "energy", "switch", "burst", "unarmed" }; private readonly GameObject _root; private readonly Image[] _icons = (Image[])(object)new Image[Topics.Length]; private readonly TextMeshProUGUI[] _bodies = (TextMeshProUGUI[])(object)new TextMeshProUGUI[Topics.Length]; private readonly NumberSheet _sheet = new NumberSheet(); private int _shownLevel = -1; private int _shownTrophies = -1; private int _shownConfig = -1; private int _shownUnarmed = -1; public bool IsShown { get { if ((Object)(object)_root != (Object)null) { return _root.activeSelf; } return false; } } public BasicsView(Transform parent, float x, float y, float w, float h) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Expected O, but got Unknown RectTransform val = UiKit.Box(parent, "DemigodBasics", x, y, w, h); _root = ((Component)val).gameObject; UiKit.Inset((Transform)(object)val, "Bg", 0f, 0f, w, h); UiKit.Text((Transform)(object)val, Loc.T("$dgp_basics_title"), 22, UiKit.Orange, (TextAnchor)0, 16f, 12f, w - 32f, 30f, bold: true); RectTransform val2 = UiKit.Box((Transform)(object)val, "Scroll", 8f, 48f, w - 16f, h - 56f); ((Component)val2).gameObject.AddComponent<RectMask2D>(); Image obj = ((Component)val2).gameObject.AddComponent<Image>(); obj.sprite = UiKit.White; ((Graphic)obj).color = new Color(0f, 0f, 0f, 0f); ScrollRect val3 = ((Component)val2).gameObject.AddComponent<ScrollRect>(); val3.horizontal = false; val3.movementType = (MovementType)2; val3.scrollSensitivity = 0f; WheelStep wheelStep = ((Component)val2).gameObject.AddComponent<WheelStep>(); wheelStep.Scroll = val3; wheelStep.Step = 90f; RectTransform val4 = UiKit.Box((Transform)(object)val2, "Content", 0f, 0f, w - 30f, 10f); ((Component)val4).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; VerticalLayoutGroup obj2 = ((Component)val4).gameObject.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = (((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = true); ((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)obj2).spacing = 14f; ((LayoutGroup)obj2).padding = new RectOffset(4, 4, 4, 10); val3.content = val4; val3.viewport = val2; for (int i = 0; i < Topics.Length; i++) { BuildRow(val4, i, w - 38f); } _root.SetActive(false); } private void BuildRow(RectTransform content, int i, float width) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_0131: 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_013d: 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_0161: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Topic_" + Topics[i], new Type[1] { typeof(RectTransform) }); val.transform.SetParent((Transform)(object)content, false); HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>(); bool childControlWidth = (((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true); ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = childControlWidth; childControlWidth = (((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false); ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = childControlWidth; ((HorizontalOrVerticalLayoutGroup)obj).spacing = 12f; GameObject val2 = new GameObject("Icon", new Type[3] { typeof(RectTransform), typeof(Image), typeof(LayoutElement) }); val2.transform.SetParent(val.transform, false); LayoutElement component = val2.GetComponent<LayoutElement>(); float num = (component.minHeight = 34f); float num3 = (component.minWidth = num); float preferredWidth = (component.preferredHeight = num3); component.preferredWidth = preferredWidth; _icons[i] = val2.GetComponent<Image>(); _icons[i].preserveAspect = true; ((Graphic)_icons[i]).raycastTarget = false; GameObject val3 = new GameObject("Text", new Type[2] { typeof(RectTransform), typeof(LayoutElement) }); val3.SetActive(false); val3.transform.SetParent(val.transform, false); val3.GetComponent<LayoutElement>().preferredWidth = width - 46f; TextMeshProUGUI val4 = val3.AddComponent<TextMeshProUGUI>(); if ((Object)(object)UiFonts.Body != (Object)null) { ((TMP_Text)val4).font = UiFonts.Body; } ((TMP_Text)val4).fontSize = 16f; ((Graphic)val4).color = Color.white; ((TMP_Text)val4).richText = true; ((TMP_Text)val4).textWrappingMode = (TextWrappingModes)1; ((TMP_Text)val4).lineSpacing = 8f; ((Graphic)val4).raycastTarget = true; LinkHover linkHover = val3.AddComponent<LinkHover>(); linkHover.Text = val4; linkHover.Detail = _sheet.Detail; val3.SetActive(true); _bodies[i] = val4; } public void Show(bool show) { if (_root.activeSelf != show) { _root.SetActive(show); } if (show) { Refresh(force: true); } } public void Refresh(bool force = false) { Player localPlayer = Player.m_localPlayer; if (IsShown && !((Object)(object)localPlayer == (Object)null)) { int num = Mathf.FloorToInt(NdBridge.Level(localPlayer)); int count = localPlayer.m_trophies.Count; int num2 = Mathf.FloorToInt(NdBridge.SkillLevel(localPlayer, (SkillType)11)); if (force || num != _shownLevel || count != _shownTrophies || num2 != _shownUnarmed || _shownConfig != NdEvents.ConfigVersion) { _shownUnarmed = num2; _shownLevel = num; _shownTrophies = count; _shownConfig = NdEvents.ConfigVersion; long start = Perf.Begin(); long mem = Perf.BeginMem(); RefreshTexts(localPlayer, num); Perf.End(Perf.Scope.Basics, start, mem); } } } private void RefreshTexts(Player player, int level) { _sheet.SetPlayer(player, asOtherGod: false); _sheet.Begin(); for (int i = 0; i < Topics.Length; i++) { string text = ((Topics[i] == "cap") ? CapLadder(player, level) : _sheet.Render(Loc.T("$dgp_basics_" + Topics[i]))); ((TMP_Text)_bodies[i]).text = NumberStyle.Tint(Texts.Header(Loc.T("$dgp_basics_" + Topics[i] + "_h")) + "\n" + text); if ((Object)(object)_icons[i].sprite == (Object)null) { _icons[i].sprite = IconOf(Topics[i], player); ((Behaviour)_icons[i]).enabled = (Object)(object)_icons[i].sprite != (Object)null; } } } private static string CapLadder(Player player, int level) { StringBuilder stringBuilder = new StringBuilder(512); stringBuilder.Append(Loc.T("$dgp_basics_cap")).Append('\n'); CapState capState = NdBridge.Cap(player, level); if (capState.Cap <= 0 && capState.NextTier < 0) { return stringBuilder.Append(Loc.T("$dgp_growth_nocap")).ToString(); } int capTierCount = NdBridge.CapTierCount; for (int i = 0; i < capTierCount; i++) { int num = NdBridge.CapOfTier(i); string value = ((i == 0) ? Loc.T("$dgp_cap_tier_none") : NdBridge.TrophyName(i)); string value2 = ((num > 0) ? num.ToString() : Loc.T("$dgp_no_cap")); bool flag = i == capState.Tier; bool flag2 = i == capState.NextTier; string value3 = (flag ? NumberStyle.Fixed : (flag2 ? NumberStyle.Scaling : NumberStyle.Muted)); stringBuilder.Append("<color=#").Append(value3).Append('>') .Append((flag || flag2) ? "<b>" : string.Empty) .Append(value) .Append(": ") .Append(value2) .Append(flag ? (" " + Loc.T("$dgp_basics_cap_now")) : (flag2 ? (" " + Loc.T("$dgp_basics_cap_next")) : string.Empty)) .Append((flag || flag2) ? "</b>" : string.Empty) .Append("</color>\n"); } return stringBuilder.ToString().TrimEnd(new char[1] { '\n' }); } private static Sprite IconOf(string topic, Player player) { //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Invalid comparison between Unknown and I4 switch (topic) { case "falls": return StatusIcon("SlowFall"); case "heavy": return ItemIcon("ArmorIronChest"); case "cap": return ItemIcon("TrophyEikthyr"); case "energy": return StatusIcon("Lightning"); case "switch": return ItemIcon("DemigodRunestone") ?? AbilityView.Fallback(); case "burst": return StatusIcon("Burning"); default: if ((Object)(object)player.m_skills != (Object)null) { foreach (SkillDef skill in player.m_skills.m_skills) { if ((int)skill.m_skill == 11) { return skill.m_icon; } } } return null; } } private static Sprite StatusIcon(string name) { StatusEffect val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode(name)) : null); if (!((Object)(object)val != (Object)null)) { return null; } return val.m_icon; } private static Sprite ItemIcon(string prefab) { GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(prefab) : null); ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null); if (!((Object)(object)val2 != (Object)null)) { return null; } return val2.m_itemData.GetIcon(); } } internal sealed class CompanionBars { private enum Kind { Wolf, Minions, Ghost, Necks, Golem, Surtlings, Count } private sealed class Row { public RectTransform Rt; public Image Icon; public HudBar Bar; public int A = -1; public int B = -1; public int C = -1; public string Name; } private const float TickSeconds = 0.1f; private const float IconSize = 30f; private const float RowGap = 4f; private static readonly Color WolfColor = new Color(0.85f, 0.3f, 0.25f); private static readonly Color MinionColor = new Color(0.62f, 0.85f, 0.3f); private static readonly Color GhostColor = new Color(0.75f, 0.85f, 0.95f); private static readonly Color NeckColor = new Color(0.25f, 0.8f, 0.8f); private static readonly Color GolemColor = new Color(0.62f, 0.56f, 0.48f); private static readonly Color SurtlingColor = new Color(0.95f, 0.5f, 0.15f); private readonly Row[] _rows = new Row[6]; private RectTransform _root; private float _tick; private int _builtFor = -1; private bool _hasCompanions; private int _shownMask = -1; private string _wolfNameRaw; private string _wolfName; private string _neckActivityRaw; private string _neckActivity; private int _neckActivityStamp; public RectTransform Root { get { if (!((Object)(object)_root != (Object)null) || !((Component)_root).gameObject.activeInHierarchy || _shownMask <= 0) { return null; } return _root; } } public void Destroy() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)((Component)_root).gameObject); } _root = null; for (int i = 0; i < _rows.Length; i++) { _rows[i] = null; } _builtFor = -1; _shownMask = -1; } public void ApplyLayout() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_root == (Object)null)) { float value = Plugin.CompanionsScale.Value; ((Transform)_root).localScale = new Vector3(value, value, 1f); _root.anchoredPosition = UiKit.OnScreen(_root, Plugin.CompanionsOffset.Value); } } public void Place(Vector2 offset) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_root != (Object)null && _root.anchoredPosition != offset) { _root.anchoredPosition = offset; } } public void Update(Player player, Demigod god, int godVersion, float dt) { if (!((Object)(object)player != (Object)null) || !((Object)(object)god != (Object)null) || ((Character)player).IsDead() || !Plugin.ShowCompanionBars.Value || !NdMeters.OursReplaceNd) { SetVisible(visible: false); return; } if (godVersion != _builtFor) { Destroy(); _builtFor = godVersion; _hasCompanions = NdMeters.Minions(player) != null || HasAbility<AbilityWolf>(player) || HasAbility<AbilityNeck>(player) || HasAbility<AbilityElementalGolem>(player) || HasAbility<AbilitySurtling>(player); _shownMask = -1; } if (!_hasCompanions) { SetVisible(visible: false); return; } _tick -= dt; if (_tick > 0f) { AnimateRows(dt); return; } _tick = 0.1f; EnsureRoot(); if (!((Object)(object)_root == (Object)null)) { SetVisible(visible: true); int num = 0; long start = Perf.Begin(); long mem = Perf.BeginMem(); num |= (TickWolf(player, god) ? 1 : 0); Perf.End(Perf.Scope.CompanionWolf, start, mem); start = Perf.Begin(); mem = Perf.BeginMem(); num |= (TickMinions(player, god, out var ghost) ? 2 : 0); num |= (ghost ? 4 : 0); Perf.End(Perf.Scope.CompanionMinions, start, mem); start = Perf.Begin(); mem = Perf.BeginMem(); num |= (TickNecks(player, god) ? 8 : 0); Perf.End(Perf.Scope.CompanionNecks, start, mem); start = Perf.Begin(); mem = Perf.BeginMem(); num |= (TickGolem(player, god) ? 16 : 0); Perf.End(Perf.Scope.CompanionGolem, start, mem); start = Perf.Begin(); mem = Perf.BeginMem(); num |= (TickSurtlings(player, god) ? 32 : 0); Perf.End(Perf.Scope.CompanionSurtlings, start, mem); if (num != _shownMask) { _shownMask = num; Stack(num); } } } private static bool HasAbility<T>(Player player) where T : DemigodAbility { T val = default(T); return Helper.TryGetDemigodAbility<T>(player, ref val); } private bool TickWolf(Player player, Demigod god) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) AbilityWolf val = NdMeters.ActiveWolf(player); if (val == null) { return false; } Row row = RowFor(Kind.Wolf, (DemigodAbility)(object)val, god, "Wolf", WolfColor); if (row == null) { return false; } int num = Mathf.CeilToInt(val.WolfCharacter.GetHealthPercentage() * 100f); string text = WolfName(val); if (num != row.A || text != row.Name) { row.A = num; row.Name = text; row.Bar.Set((float)num / 100f, Loc.F("$dgp_pet_health", text ?? Loc.T("$dgp_pet_wolf"), num)); } return true; } private bool TickMinions(Player player, Demigod god, out bool ghost) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) ghost = false; AbilityMinions val = NdMeters.Minions(player); if (val == null) { return false; } int activeSkeletons = val.GetActiveSkeletons(); int maxSkeletons = val.GetMaxSkeletons(); Character ghostCharacter = val.ghostCharacter; ghost = (Object)(object)ghostCharacter != (Object)null; if (ghost) { Row row = RowFor(Kind.Ghost, (DemigodAbility)(object)val, god, "Ghost", GhostColor); int num = Mathf.CeilToInt(ghostCharacter.GetHealthPercentage() * 100f); if (row == null) { ghost = false; } else if (num != row.A) { row.A = num; row.Bar.Set((float)num / 100f, Loc.F("$dgp_pet_health", Loc.T("$dgp_pet_ghost"), num)); } } if (activeSkeletons <= 0) { return false; } Row row2 = RowFor(Kind.Minions, (DemigodAbility)(object)val, god, "Skeleton", MinionColor); if (row2 == null) { return false; } if (activeSkeletons != row2.A || maxSkeletons != row2.B) { row2.A = activeSkeletons; row2.B = maxSkeletons; row2.Bar.Set((maxSkeletons > 0) ? ((float)activeSkeletons / (float)maxSkeletons) : 0f, Loc.F("$dgp_pet_minions", activeSkeletons, maxSkeletons)); } return true; } private bool TickNecks(Player player, Demigod god) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) AbilityNeck val = NdMeters.Necks(player); if (val == null) { return false; } Row row = RowFor(Kind.Necks, (DemigodAbility)(object)val, god, "Neck", NeckColor); if (row == null) { return false; } int activeNecks = val.GetActiveNecks(); int maxNecks = val.GetMaxNecks(); string text = NeckActivity(val); if (activeNecks != row.A || maxNecks != row.B || _neckActivityStamp != row.C) { row.A = activeNecks; row.B = maxNecks; row.C = _neckActivityStamp; string text2 = ((text != null) ? Loc.F("$dgp_pet_necks_doing", activeNecks, maxNecks, text) : Loc.F("$dgp_pet_necks", activeNecks, maxNecks)); row.Bar.Set((maxNecks > 0) ? ((float)activeNecks / (float)maxNecks) : 0f, text2); } return true; } private string WolfName(AbilityWolf wolf) { ZNetView val = (((Object)(object)wolf.WolfTameable != (Object)null) ? wolf.WolfTameable.m_nview : null); ZDO val2 = (((Object)(object)val != (Object)null && val.IsValid()) ? val.GetZDO() : null); string text = ((val2 != null) ? val2.GetString(ZDOVars.s_tamedName, "") : null); if ((object)text != _wolfNameRaw) { _wolfNameRaw = text; _wolfName = (string.IsNullOrEmpty(text) ? null : StringExtensionMethods.RemoveRichTextTags(text)); } if (!string.IsNullOrEmpty(_wolfName)) { return _wolfName; } if (wolf.DataProperties == null || string.IsNullOrEmpty(wolf.DataProperties.Name)) { return null; } return wolf.DataProperties.Name; } private string NeckActivity(AbilityNeck necks) { string text; try { text = necks.GetCurrentActivityText(); } catch (Exception) { text = null; } if ((object)text == _neckActivityRaw) { return _neckActivity; } _neckActivityRaw = text; _neckActivityStamp++; string text2 = ((string.IsNullOrEmpty(text) || Loc.Missing(text)) ? null : text); if (text2 != null) { string text3 = Loc.T("$dgp_neck_" + text2.ToLowerInvariant()); text2 = ((Loc.Missing(text3) || text3.StartsWith("$")) ? text2 : text3); } _neckActivity = text2; return text2; } private bool TickGolem(Player player, Demigod god) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) AbilityElementalGolem val = default(AbilityElementalGolem); if (!Helper.TryGetDemigodAbility<AbilityElementalGolem>(player, ref val)) { return false; } Character stoneGolemCharacter = val.StoneGolemCharacter; if ((Object)(object)stoneGolemCharacter == (Object)null || stoneGolemCharacter.IsDead()) { return false; } Row row = RowFor(Kind.Golem, (DemigodAbility)(object)val, god, "Golem", GolemColor); if (row == null) { return false; } int num = Mathf.CeilToInt(stoneGolemCharacter.GetHealthPercentage() * 100f); if (num != row.A) { row.A = num; row.Bar.Set((float)num / 100f, Loc.F("$dgp_pet_health", Loc.T("$dgp_pet_golem"), num)); } return true; } private bool TickSurtlings(Player player, Demigod god) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) AbilitySurtling val = default(AbilitySurtling); if (!Helper.TryGetDemigodAbility<AbilitySurtling>(player, ref val)) { return false; } int num = 0; float num2 = 0f; float num3 = 0f; foreach (Character surtlingCharacter in val.SurtlingCharacters) { if ((Object)(object)surtlingCharacter != (Object)null && !surtlingCharacter.IsDead()) { num++; num2 += surtlingCharacter.GetHealth(); num3 += surtlingCharacter.GetMaxHealth(); } } if (num == 0) { return false; } Row row = RowFor(Kind.Surtlings, (DemigodAbility)(object)val, god, "Surtling", SurtlingColor); if (row == null) { return false; } int num4 = ((num3 > 0f) ? Mathf.CeilToInt(num2 / num3 * 100f) : 0); if (num != row.A || num4 != row.B) { row.A = num; row.B = num4; row.Bar.Set((float)num4 / 100f, Loc.F("$dgp_pet_surtlings", num, num4)); } return true; } private void AnimateRows(float dt) { Row[] rows = _rows; foreach (Row row in rows) { if (row != null && row.Bar.Animating && ((Component)row.Rt).gameObject.activeSelf) { row.Bar.Animate(dt); } } } private void EnsureRoot() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_009d: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_root != (Object)null)) { Hud instance = Hud.instance; if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_rootObject == (Object)null)) { GameObject val = new GameObject("DemigodCompanions", new Type[2] { typeof(RectTransform), typeof(Canvas) }); _root = (RectTransform)val.transform; ((Transform)_root).SetParent(instance.m_rootObject.transform, false); RectTransform root = _root; RectTransform root2 = _root; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(0.5f, 0f); root2.anchorMax = val2; root.anchorMin = val2; _root.pivot = Vector2.zero; _root.sizeDelta = new Vector2(36f + (float)Plugin.CompanionBarWidth.Value, 30f); ApplyLayout(); } } } private Row RowFor(Kind kind, DemigodAbility ability, Demigod god, string art, Color color) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0160: 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_0185: Unknown result type (might be due to invalid IL or missing references) Row row = _rows[(int)kind]; if (row != null) { return row; } RectTransform val = UiKit.Box((Transform)(object)_root, kind.ToString(), 0f, 0f, _root.sizeDelta.x, 30f); Vector2 val2 = (val.anchorMin = (val.anchorMax = Vector2.zero)); val.pivot = Vector2.zero; Image val4 = UiKit.Image((Transform)(object)val, "Icon", AbilityView.CompanionIcon(art, ((Object)(object)god != (Object)null) ? god.DemigodName : null) ?? AbilityView.Icon(ability), Color.white); val4.preserveAspect = true; RectTransform rectTransform = ((Graphic)val4).rectTransform; ((Vector2)(ref val2))..ctor(0f, 0.5f); rectTransform.anchorMax = val2; rectTransform.anchorMin = val2; rectTransform.pivot = new Vector2(0f, 0.5f); rectTransform.anchoredPosition = Vector2.zero; rectTransform.sizeDelta = new Vector2(30f, 30f); HudBar hudBar = HudBar.Create((Transform)(object)val, "Bar", HudBar.FillWidthFor(Plugin.CompanionBarWidth.Value), 20f, 13f); RectTransform root = hudBar.Root; RectTransform root2 = hudBar.Root; ((Vector2)(ref val2))..ctor(0f, 0.5f); root2.anchorMax = val2; root.anchorMin = val2; hudBar.Root.pivot = new Vector2(0f, 0.5f); hudBar.Root.anchoredPosition = new Vector2(36f, 0f); hudBar.SetColor(color); row = new Row { Rt = val, Icon = val4, Bar = hudBar }; ((Component)val).gameObject.SetActive(false); _rows[(int)kind] = row; return row; } private void Stack(int mask) { //IL_0092: 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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) float num = 0f; for (int i = 0; i < _rows.Length; i++) { Row row = _rows[i]; bool flag = (mask & (1 << i)) != 0; if (row != null) { if (((Component)row.Rt).gameObject.activeSelf != flag) { ((Component)row.Rt).gameObject.SetActive(flag); } if (flag) { row.Rt.anchoredPosition = new Vector2(0f, num); num += 34f; } } } float num2 = Mathf.Max(30f, num - 4f); if (_root.sizeDelta.y != num2) { _root.sizeDelta = new Vector2(_root.sizeDelta.x, num2); ApplyLayout(); } } private void SetVisible(bool visible) { if ((Object)(object)_root != (Object)null && ((Component)_root).gameObject.activeSelf != visible) { ((Component)_root).gameObject.SetActive(visible); } } } internal abstract class PanelTab { public GameObject Root; public abstract void Build(DemigodPanelView view, RectTransform root); public abstract void Rebuild(Demigod god); public abstract void Refresh(); public virtual void Tick() { } public virtual void Hidden() { } } internal sealed class DemigodPanelView { public const float Width = 1400f; public const float Height = 820f; public const float ContentY = 190f; public const float ContentH = 520f; public const float LeftX = 30f; public const float LeftW = 430f; public const float MidX = 475f; public const float MidW = 520f; public const float RightX = 1010f; public const float RightW = 360f; private const float RefreshSeconds = 0.5f; private GameObject _panel; private Text _godName; private Text _godSub; private Image _godIcon; private Button _change; private readonly Button[] _tabButtons = (Button[])(object)new Button[3]; private readonly Text[] _tabLabels = (Text[])(object)new Text[3]; private readonly PanelTab[] _tabs = new PanelTab[3]; private readonly TabStamps _built = new TabStamps(3); private int _tab; private Text _levelText; private Image _xpFill; private HudBar _xpBar; private Text _xpText; private Text _capText; private ConfirmDialog _confirm; private float _refresh; private int _builtVersion = -1; private Demigod _god; public const int TabAbilities = 0; public const int TabPerks = 1; public const int TabPantheon = 2; private bool _warming; private CanvasGroup _group; private int _toggledFrame = -1; private PanelInput _input; private bool _releaseBlock; private int _releaseFrame; private int _hfLevel = -1; private int _hfRaw = -1; private int _hfAcc = -1; private int _hfTrophies = -1; private int _hfTab = -1; private int _hfVersion = -1; private int _hfConfig = -1; private object _hfGod; private int _pendingTab = -1; public bool IsOpen { get { if ((Object)(object)_panel != (Object)null && _panel.activeSelf) { return !_warming; } return false; } } public bool ToggledThisFrame => _toggledFrame == Time.frameCount; public PantheonTab Pantheon => (PantheonTab)_tabs[2]; public void Build() { //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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: 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_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Expected O, but got Unknown _panel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, 1400f, 820f, false); ((Object)_panel).name = "DemigodPanel"; _panel.SetActive(false); _group = _panel.AddComponent<CanvasGroup>(); Transform transform = _panel.transform; UiKit.Text(transform, Loc.T("$dgp_title").ToUpperInvariant(), 38, UiKit.Orange, (TextAnchor)1, 0f, 14f, 1400f, 48f, bold: true, norse: true); _godName = UiKit.Text(transform, string.Empty, 28, Color.white, (TextAnchor)1, 300f, 62f, 800f, 36f, bold: true); _godSub = UiKit.Text(transform, string.Empty, 16, UiKit.Muted, (TextAnchor)1, 300f, 98f, 800f, 24f); _godIcon = UiKit.Image(transform, "GodIcon", null, Color.white); _godIcon.preserveAspect = true; Place(((Graphic)_godIcon).rectTransform, 0f, 64f, 52f, 52f); ((Behaviour)_godIcon).enabled = false; _change = UiKit.Button(transform, Loc.T("$dgp_change"), 1150f, 70f, 200f, 40f, delegate { ShowTab(2); }); UiKit.Button(transform, "X", 1338f, 18f, 40f, 40f, Close); string[] array = new string[3] { "$dgp_tab_abilities", "$dgp_tab_perks", "$dgp_tab_pantheon" }; for (int num = 0; num < 3; num++) { int index = num; _tabButtons[num] = UiKit.Button(transform, Loc.T(array[num]), 30f + (float)num * 220f, 132f, 210f, 40f, delegate { ShowTab(index); }); _tabLabels[num] = ((Component)_tabButtons[num]).GetComponentInChildren<Text>(); } Place(((Graphic)UiKit.Image(transform, "Divider", UiKit.White, new Color(1f, 0.85f, 0.6f, 0.15f))).rectTransform, 30f, 180f, 1340f, 2f); _tabs[0] = new AbilitiesTab(); _tabs[1] = new PerksTab(); _tabs[2] = new PantheonTab(); PanelTab[] tabs = _tabs; foreach (PanelTab panelTab in tabs) { RectTransform val = UiKit.Box(transform, panelTab.GetType().Name, 0f, 0f, 1400f, 820f); panelTab.Root = ((Component)val).gameObject; panelTab.Build(this, val); panelTab.Root.SetActive(false); } BuildFooter(transform); _confirm = new ConfirmDialog(GUIManager.CustomGUIFront.transform); GameObject val2 = new GameObject("DemigodPanelInput"); val2.transform.SetParent(GUIManager.CustomGUIFront.transform, false); _input = val2.AddComponent<PanelInput>(); _input.View = this; } private void BuildFooter(Transform t) { //IL_000f: 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_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_025a: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) float num = 724f; _levelText = UiKit.Text(t, string.Empty, 22, UiKit.Orange, (TextAnchor)3, 30f, num, 200f, 30f, bold: true); _xpBar = HudBar.Create(t, "XpBar", HudBar.FillWidthFor(904f), 26f, 16f); if (_xpBar != null) { RectTransform root = _xpBar.Root; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0f, 1f); root.anchorMax = val; root.anchorMin = val; root.pivot = new Vector2(0f, 0.5f); root.anchoredPosition = new Vector2(228f, 0f - (num + 15f)); _xpBar.SetColor(ElementColors.Xp); _xpText = UiKit.Text(t, string.Empty, 18, Color.white, (TextAnchor)5, 1140f, num, 230f, 30f, bold: true); _capText = UiKit.Text(t, string.Empty, 16, UiKit.Muted, (TextAnchor)4, 30f, num + 36f, 1340f, 26f); } else { Image obj = UiKit.Image(t, "XpFrame", UiKit.White, new Color(0.55f, 0.42f, 0.26f, 0.9f)); Place(((Graphic)obj).rectTransform, 228f, num + 3f, 904f, 24f); Image val2 = UiKit.Image(((Component)obj).transform, "XpBg", UiKit.White, new Color(0.06f, 0.05f, 0.04f, 0.95f)); UiKit.Fill(((Graphic)val2).rectTransform, 2f); _xpFill = UiKit.Image(((Component)val2).transform, "XpFill", UiKit.White, new Color(0.95f, 0.7f, 0.25f, 0.95f)); _xpFill.type = (Type)3; _xpFill.fillMethod = (FillMethod)0; _xpFill.fillAmount = 0f; UiKit.Fill(((Graphic)_xpFill).rectTransform, 1f); _xpText = UiKit.Text(t, string.Empty, 18, Color.white, (TextAnchor)5, 1140f, num, 230f, 30f, bold: true); _capText = UiKit.Text(t, string.Empty, 16, UiKit.Muted, (TextAnchor)4, 30f, num + 36f, 1340f, 26f); } } public static void Place(RectTransform rt, float x, float y, float w, float h) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0f, 1f); rt.anchorMax = val; rt.anchorMin = val; rt.pivot = new Vector2(0f, 1f); rt.anchoredPosition = new Vector2(x, 0f - y); rt.sizeDelta = new Vector2(w, h); } public IEnumerator WarmUp() { if ((Object)(object)_panel == (Object)null || _panel.activeSelf || (Object)(object)Player.m_localPlayer == (Object)null) { yield break; } _warming = true; _group.alpha = 0f; _group.blocksRaycasts = false; _panel.SetActive(true); int[] array = new int[3] { 0, 1, 2 }; int[] array2 = array; foreach (int tab in array2) { if (!_warming) { yield break; } if (!WarmStep(tab)) { break; } yield return null; } EndWarmUp(); } private bool WarmStep(int tab) { long start = Perf.Begin(); long mem = Perf.BeginMem(); try { SyncGod(); ShowTab(tab); return true; } catch (Exception ex) { Plugin.Log.LogDebug((object)("Panel warm-up stopped: " + ex.Message)); return false; } finally { Perf.End(Perf.Scope.PanelWarm, start, mem); } } private void EndWarmUp() { if (_warming) { _warming = false; _panel.SetActive(false); _group.alpha = 1f; _group.blocksRaycasts = true; } } public void Open(int tab = -1) { if (!((Object)(object)_panel == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null)) { long start = Perf.Begin(); long mem = Perf.BeginMem(); OpenInner(tab); Perf.End(Perf.Scope.PanelOpen, start, mem); } } private void OpenInner(int tab) { EndWarmUp(); if (!IsOpen) { _panel.SetActive(true); _toggledFrame = Time.frameCount; if (_releaseBlock) { _releaseBlock = false; } else { GUIManager.BlockInput(true); } } SyncGod(); ShowTab((tab >= 0) ? tab : (((Object)(object)_god == (Object)null) ? 2 : 0)); } public void Close() { Close(releaseLate: false); } private void Close(bool releaseLate) { _pendingTab = -1; _confirm?.Hide(); ValueTip.Hide(); if (IsOpen) { _tabs[_tab].Hidden(); _panel.SetActive(false); _toggledFrame = Time.frameCount; if (releaseLate) { _releaseBlock = true; _releaseFrame = Time.frameCount; return; } GUIManager.BlockInput(false); } ReleaseBlock(); } public void HandleCloseKeys() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (IsOpen && !ToggledThisFrame && !Console.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && (ZInput.GetKeyDown((KeyCode)27, false) || Utils.Pressed(Plugin.PanelKey.Value))) { Back(); } } public void LateRelease() { ReleaseBlock(); } private void ReleaseBlock() { if (_releaseBlock) { _releaseBlock = false; GUIManager.BlockInput(false); } } public void ShowTab(int index) { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_god == (Object)null && index != 2) { index = 2; } _tab = index; EnsureBuilt(index); for (int i = 0; i < _tabs.Length; i++) { if (i != index && _tabs[i].Root.activeSelf) { _tabs[i].Hidden(); } _tabs[i].Root.SetActive(i == index); Text val = _tabLabels[i]; if ((Object)(object)val != (Object)null) { ((Graphic)val).color = ((i == index) ? UiKit.Orange : (((Object)(object)_god == (Object)null && i != 2) ? (UiKit.Muted * 0.7f) : Color.white)); } ((Selectable)_tabButtons[i]).interactable = (Object)(object)_god != (Object)null || i == 2; } RefreshNow(); } public void ShowBasics() { ShowTab(2); Pantheon.ShowBasics(); } public void Back() { if (_confirm != null && _confirm.IsOpen) { _confirm.Hide(); } else { Close(releaseLate: true); } } public void Update(Player player, float dt) { if (_releaseBlock && Time.frameCount != _releaseFrame) { ReleaseBlock(); } if (!IsOpen) { return; } if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { Close(); return; } long start = Perf.Begin(); long mem = Perf.BeginMem(); bool num = SyncGod(); Perf.End(Perf.Scope.PanelUpdate, start, mem); if (num) { int num2 = ((_pendingTab >= 0 && (Object)(object)_god != (Object)null) ? _pendingTab : _tab); if (num2 == _pendingTab) { _pendingTab = -1; } ShowTab(num2); } else { _tabs[_tab].Tick(); _refresh -= dt; if (_refresh <= 0f) { RefreshNow(); } } } private bool SyncGod() { if (NdEvents.Pending) { return false; } Demigod val = NdBridge.GodOf(Player.m_localPlayer); if (val == _god && _builtVersion == NdEvents.Version) { return false; } _god = val; _builtVersion = NdEvents.Versio