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 LateGamePerformance v1.5.0
LateGamePerformance.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.FalseSon; using EntityStates.ScavBackpack; using HarmonyLib; using LateGamePerformance.Patches; using LateGamePerformance.Ui; using Microsoft.CodeAnalysis; using Rewired; using RoR2; using RoR2.Navigation; using RoR2.Skills; using RoR2.UI; using RoR2.UI.SkinControllers; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("RoR2")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LateGamePerformance")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.5.0.0")] [assembly: AssemblyInformationalVersion("1.5.0")] [assembly: AssemblyProduct("LateGamePerformance")] [assembly: AssemblyTitle("LateGamePerformance")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LateGamePerformance { internal sealed class DpsHud : MonoBehaviour { private sealed class RowView { internal RectTransform root; internal Image bar; internal HGTextMeshProUGUI name; internal HGTextMeshProUGUI damage; internal HGTextMeshProUGUI share; internal HGTextMeshProUGUI dps; internal HGTextMeshProUGUI now; } private const float Width = 470f; private const float Pad = 14f; private const float TitleHeight = 30f; private const float ColumnHeight = 20f; private const float RowHeight = 30f; private const float FooterHeight = 22f; private const float NameWidth = 150f; private const float DamageWidth = 78f; private const float ShareWidth = 56f; private const float DpsWidth = 66f; private const float NowWidth = 72f; private static readonly Color[] Ranks = (Color[])(object)new Color[3] { new Color(1f, 0.82f, 0.36f, 1f), new Color(0.8f, 0.84f, 0.9f, 1f), new Color(0.79f, 0.55f, 0.36f, 1f) }; private Canvas canvas; private RectTransform panel; private RectTransform rowRoot; private HGTextMeshProUGUI clock; private HGTextMeshProUGUI footer; private readonly List<RowView> views = new List<RowView>(); private bool hidden; internal static DpsHud Instance { get; private set; } internal static void Install(GameObject host) { Instance = host.AddComponent<DpsHud>(); } private void Update() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (DpsMeterPatch.Active && DpsMeterPatch.ToggleKey != null) { KeyboardShortcut value = DpsMeterPatch.ToggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { hidden = !hidden; } } if (!DpsMeterPatch.Active || hidden || !DpsMeterPatch.ShowDuringRun.Value || !Object.op_Implicit((Object)(object)Run.instance) || !Object.op_Implicit((Object)(object)Stage.instance) || ModMenu.IsOpen) { UiFactory.SetVisible(canvas, visible: false); return; } GameSkin.Refresh(); if (GameSkin.Ready) { if ((Object)(object)canvas == (Object)null) { Build(); } UiFactory.SetVisible(canvas, visible: true); Refresh(); } } private void OnDestroy() { if ((Object)(object)canvas != (Object)null) { Object.Destroy((Object)(object)((Component)canvas).gameObject); } } private void Build() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_021d: Unknown result type (might be due to invalid IL or missing references) canvas = UiFactory.CreateCanvas("LGP_DamageMeter", 100, interactive: false); panel = UiFactory.Panel(((Component)canvas).transform, "Panel"); float value = DpsMeterPatch.PanelX.Value; float num = 1f - DpsMeterPatch.PanelY.Value; panel.anchorMin = new Vector2(value, num); panel.anchorMax = new Vector2(value, num); panel.pivot = new Vector2(value, num); panel.anchoredPosition = Vector2.zero; panel.sizeDelta = new Vector2(470f, 200f); UiFactory.Row(((TMP_Text)UiFactory.Label((Transform)(object)panel, "Title", "DAMAGE THIS STAGE", GameSkin.TextKind.Header, 22f, (TextAlignmentOptions)513)).rectTransform, 14f, 442f, 14f, 30f); clock = UiFactory.Label((Transform)(object)panel, "Clock", "0:00", GameSkin.TextKind.Header, 22f, (TextAlignmentOptions)516); UiFactory.Row(((TMP_Text)clock).rectTransform, 14f, 442f, 14f, 30f); float num2 = 44f; Column("Player", (TextAlignmentOptions)513, 0, num2); Column("Damage", (TextAlignmentOptions)516, 1, num2); Column("Share", (TextAlignmentOptions)516, 2, num2); Column("DPS", (TextAlignmentOptions)516, 3, num2); Column("Now 6s", (TextAlignmentOptions)516, 4, num2); GameObject val = new GameObject("Rows", new Type[1] { typeof(RectTransform) }); rowRoot = val.GetComponent<RectTransform>(); ((Transform)rowRoot).SetParent((Transform)(object)panel, false); UiFactory.Row(rowRoot, 0f, 470f, num2 + 20f, 0f); footer = UiFactory.Label((Transform)(object)panel, "Footer", string.Empty, GameSkin.TextKind.Body, 15f, (TextAlignmentOptions)513); ((Graphic)footer).color = GameSkin.QuietColor; } private void Column(string text, TextAlignmentOptions alignment, int index, float top) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) HGTextMeshProUGUI obj = UiFactory.Label((Transform)(object)panel, "Column" + text, text, GameSkin.TextKind.Body, 16f, alignment); ((Graphic)obj).color = GameSkin.QuietColor; UiFactory.Row(((TMP_Text)obj).rectTransform, 14f + OffsetOf(index), WidthOf(index), top, 20f); } private static float WidthOf(int index) { return index switch { 0 => 150f, 1 => 78f, 2 => 56f, 3 => 66f, _ => 72f, }; } private static float OffsetOf(int index) { float num = 0f; for (int i = 0; i < index; i++) { num += WidthOf(i); } return num; } private RowView CreateRow(int index) { //IL_0024: 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) RectTransform component = new GameObject("Row" + index, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)rowRoot, false); UiFactory.Row(component, 0f, 470f, (float)index * 30f, 30f); RowView obj = new RowView { root = component, bar = UiFactory.Fill((Transform)(object)component, "Bar", new Color(1f, 1f, 1f, 0.16f)) }; UiFactory.Row(((Graphic)obj.bar).rectTransform, 7f, 456f, 2f, 26f); obj.name = Cell(component, "Name", 0, (TextAlignmentOptions)513, 20f, GameSkin.TextKind.Body); obj.damage = Cell(component, "Damage", 1, (TextAlignmentOptions)516, 20f, GameSkin.TextKind.Header); obj.share = Cell(component, "Share", 2, (TextAlignmentOptions)516, 19f, GameSkin.TextKind.Body); obj.dps = Cell(component, "Dps", 3, (TextAlignmentOptions)516, 19f, GameSkin.TextKind.Body); obj.now = Cell(component, "Now", 4, (TextAlignmentOptions)516, 20f, GameSkin.TextKind.Header); return obj; } private static HGTextMeshProUGUI Cell(RectTransform parent, string name, int index, TextAlignmentOptions alignment, float size, GameSkin.TextKind kind) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) HGTextMeshProUGUI obj = UiFactory.Label((Transform)(object)parent, name, string.Empty, kind, size, alignment); UiFactory.Row(((TMP_Text)obj).rectTransform, 14f + OffsetOf(index), WidthOf(index), 0f, 30f); return obj; } private void Refresh() { //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) List<DpsMeterPatch.Row> list = DpsMeterPatch.Snapshot(); while (views.Count < list.Count) { views.Add(CreateRow(views.Count)); } for (int i = list.Count; i < views.Count; i++) { ((Component)views[i].root).gameObject.SetActive(false); } float stageSeconds = DpsMeterPatch.StageSeconds; double num = 0.0; for (int j = 0; j < list.Count; j++) { num += list[j].total; } double num2 = ((list.Count > 0) ? list[0].total : 0.0); for (int k = 0; k < list.Count; k++) { DpsMeterPatch.Row row = list[k]; RowView rowView = views[k]; ((Component)rowView.root).gameObject.SetActive(true); Color val = ((k < Ranks.Length && row.total > 0.0) ? Ranks[k] : GameSkin.BodyColor); ((Graphic)rowView.name).color = val; ((TMP_Text)rowView.name).text = row.name; ((TMP_Text)rowView.damage).text = Short(row.total); ((TMP_Text)rowView.share).text = ((num > 0.0) ? (((float)(row.total / num) * 100f).ToString("0", CultureInfo.InvariantCulture) + "%") : "-"); ((TMP_Text)rowView.dps).text = Short((stageSeconds > 0.5f) ? (row.total / (double)stageSeconds) : 0.0); ((TMP_Text)rowView.now).text = Short(row.Recent); float num3 = ((num2 > 0.0) ? Mathf.Clamp01((float)(row.total / num2)) : 0f); ((Graphic)rowView.bar).color = new Color(val.r, val.g, val.b, 0.2f); ((Graphic)rowView.bar).rectTransform.sizeDelta = new Vector2(456f * num3, 26f); } ((TMP_Text)clock).text = Clock(stageSeconds); HGTextMeshProUGUI obj = footer; string arg = Short(num); KeyboardShortcut value = DpsMeterPatch.ToggleKey.Value; ((TMP_Text)obj).text = $"Total {arg} - {((KeyboardShortcut)(ref value)).MainKey} hides this"; float num4 = 64f; float num5 = num4 + (float)list.Count * 30f + 22f + 14f; panel.sizeDelta = new Vector2(470f, num5); UiFactory.Row(((TMP_Text)footer).rectTransform, 14f, 442f, num4 + (float)list.Count * 30f + 2f, 22f); } private static string Clock(float seconds) { int num = Mathf.Max(0, Mathf.FloorToInt(seconds)); return (num / 60).ToString(CultureInfo.InvariantCulture) + ":" + (num % 60).ToString("00", CultureInfo.InvariantCulture); } private static string Short(double value) { if (value >= 1000000.0) { return (value / 1000000.0).ToString("0.0", CultureInfo.InvariantCulture) + "M"; } if (value >= 1000.0) { return (value / 1000.0).ToString("0.0", CultureInfo.InvariantCulture) + "k"; } return value.ToString("0", CultureInfo.InvariantCulture); } } internal static class MenuCatalog { private sealed class Entry { internal string Category; internal string Title; internal string Blurb; } internal const string Gameplay = "Gameplay"; internal const string Maintenance = "Fixes and performance"; private static readonly Dictionary<string, Entry> features = new Dictionary<string, Entry> { ["SkipIntro"] = new Entry { Category = "Gameplay", Title = "Skip the intro video", Blurb = "Cuts the engine logo and the ship cutscene, so the game goes almost straight to the title screen." }, ["CritOverstack"] = new Entry { Category = "Gameplay", Title = "Crit overstacking", Blurb = "Crit chance above 100 percent turns into extra crit damage instead of counting for nothing." }, ["AutoSprint"] = new Entry { Category = "Gameplay", Title = "Automatic sprint", Blurb = "Your character sprints while it moves. Hold the sprint key to walk instead." }, ["EmptyChests"] = new Entry { Category = "Gameplay", Title = "Clear empty chests", Blurb = "Opened chests, used barrels, and spent shops disappear." }, ["Sharing"] = new Entry { Category = "Gameplay", Title = "Share items and money", Blurb = "An item one player picks up goes to everybody, and every player gets the full gold. Only the host needs this mod. Off by default, because it makes a group much stronger than the base game intends." }, ["DpsMeter"] = new Entry { Category = "Gameplay", Title = "Damage meter", Blurb = "A table on screen shows the damage each player did on the stage you are on. It also gives the share of the total and damage per second." }, ["StatPoints"] = new Entry { Category = "Gameplay", Title = "Character stat points", Blurb = "Earn a point every few character levels and spend it on health, damage, attack speed, crit, armor, regeneration, or speed. Press F3 during a run, or click the badge, to open the point window. Only the host can spend. A player who joins sees the window, but the buttons stay off there. The stats would never reach the machine that runs the game." }, ["BugFixes"] = new Entry { Category = "Fixes and performance", Title = "Fix game bugs", Blurb = "Stops errors that the base game throws during play." }, ["BuffStatsFilter"] = new Entry { Category = "Fixes and performance", Title = "Faster damage-over-time ticks", Blurb = "Bleed and poison stacks no longer recalculate every stat on every tick." }, ["NavPathBudget"] = new Entry { Category = "Fixes and performance", Title = "Spread out enemy pathfinding", Blurb = "Spreads the path work of an enemy wave over several frames." }, ["TargetSearchGc"] = new Entry { Category = "Fixes and performance", Title = "Cheaper target search", Blurb = "Missiles, drones, and turrets no longer create garbage when they look for a target." }, ["DamageNumberBatch"] = new Entry { Category = "Fixes and performance", Title = "Faster damage numbers", Blurb = "Big hits no longer slow the game down with damage numbers." }, ["RaycastThrottle"] = new Entry { Category = "Fixes and performance", Title = "Cheaper enemy steering", Blurb = "Enemies check for obstacles less often." }, ["HealthBarThrottle"] = new Entry { Category = "Fixes and performance", Title = "Cheaper health bars", Blurb = "Health bars refresh on a timer instead of every frame." }, ["TeamItemCountCache"] = new Entry { Category = "Fixes and performance", Title = "Faster teleporter events", Blurb = "Stops repeated scans of every character during a teleporter fight." }, ["ModelCameraPass"] = new Entry { Category = "Fixes and performance", Title = "Cheaper character drawing", Blurb = "The camera examines every character once instead of twice, and skips the work for characters that draw nothing." }, ["PerfReadout"] = new Entry { Category = "Fixes and performance", Title = "Performance readout", Blurb = "Frame times and entity counts in the log. The panel starts closed. Press F6 to show it or hide it." }, ["FixedTimeCatchup"] = new Entry { Category = "Fixes and performance", Title = "Stop freeze spirals", Blurb = "Under heavy load the game slows down for a moment instead of freezing." } }; private static readonly HashSet<string> playerFacing = new HashSet<string> { "Menu/ToggleKey", "SkipIntro/AlsoSkipLogoScreen", "Sharing/ShareItems", "Sharing/ShareMoney", "Sharing/ShareWhiteItems", "Sharing/ShareGreenItems", "Sharing/ShareRedItems", "Sharing/ShareBossItems", "Sharing/ShareLunarItems", "Sharing/ShareVoidItems", "Sharing/ShareToDeadPlayers", "Sharing/ShareEquipment", "Sharing/DropReplacedEquipment", "Sharing/SharePrinterOutput", "Sharing/ScaleSharedLoot", "Sharing/MoneyShareScalar", "EmptyChests/Chests", "EmptyChests/Barrels", "EmptyChests/Multishops", "EmptyChests/ScavengerBags", "EmptyChests/DelaySeconds", "AutoSprint/HoldSprintKeyToWalk", "AutoSprint/HoldOffSeconds", "DpsMeter/ShowDuringRun", "DpsMeter/ToggleKey", "DpsMeter/IncludeMinions", "DpsMeter/CountAllDamage", "DpsMeter/PanelX", "DpsMeter/PanelY", "StatPoints/ShowBadge", "StatPoints/OpenKey", "StatPoints/BadgeX", "StatPoints/BadgeY", "StatPoints/CharacterLevelsPerPoint", "StatPoints/MaxPointsPerStat", "StatPoints/HealthPerPoint", "StatPoints/RegenerationPerPoint", "StatPoints/DamagePerPoint", "StatPoints/AttackSpeedPerPoint", "StatPoints/CritChancePerPoint", "StatPoints/ArmorPerPoint", "StatPoints/MoveSpeedPerPoint", "FixedTimeCatchup/MaxCatchUpTicks", "ModelCameraPass/OverlayFrameStride", "PerfReadout/ShowPanel", "PerfReadout/ToggleKey", "PerfReadout/LogSeconds" }; internal static bool IsPlayerFacing(string section, string key) { return playerFacing.Contains(section + "/" + key); } internal static string CategoryOf(string featureKey) { if (!features.TryGetValue(featureKey, out var value)) { return "Gameplay"; } return value.Category; } internal static string TitleOf(string featureKey) { if (!features.TryGetValue(featureKey, out var value)) { return featureKey; } return value.Title; } internal static string BlurbOf(string featureKey, string fallback) { if (!features.TryGetValue(featureKey, out var value)) { return fallback; } return value.Blurb; } } internal sealed class ModMenu : MonoBehaviour { private const float WindowWidth = 1000f; private const float WindowHeight = 620f; private const float ListWidth = 340f; private static ConfigEntry<bool> showEverySetting; private Canvas canvas; private RectTransform listContent; private RectTransform detailContent; private HGTextMeshProUGUI detailTitle; private HGTextMeshProUGUI detailBlurb; private HGTextMeshProUGUI detailState; private Button showEveryButton; private readonly List<SettingRow> rows = new List<SettingRow>(); private readonly List<HGTextMeshProUGUI> listLabels = new List<HGTextMeshProUGUI>(); private readonly List<HGTextMeshProUGUI> listPicks = new List<HGTextMeshProUGUI>(); private readonly List<PatchRegistry.Group> listGroups = new List<PatchRegistry.Group>(); private string selectedKey; private bool listDirty = true; private bool detailDirty = true; private readonly CursorHold cursor = new CursorHold(); private ConfigEntryBase awaitingBind; private SettingRow awaitingRow; internal static ModMenu Instance { get; private set; } internal static bool IsOpen { get; private set; } internal static ConfigEntry<KeyboardShortcut> Hotkey { get; private set; } internal static void Install(Harmony harmony, GameObject host) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown Hotkey = Plugin.Cfg.Bind<KeyboardShortcut>("Menu", "ToggleKey", new KeyboardShortcut((KeyCode)285, Array.Empty<KeyCode>()), "Key that opens and closes the settings page."); showEverySetting = Plugin.Cfg.Bind<bool>("Menu", "ShowEverySetting", false, "Also show the fine-tuning values that most players never need."); harmony.Patch((MethodBase)AccessTools.Method(typeof(PlayerCharacterMasterController), "CanSendBodyInput", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(ModMenu), "BlockInputPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Instance = host.AddComponent<ModMenu>(); } private static void BlockInputPostfix(ref bool __result, ref bool onlyAllowMovement) { if (IsOpen || StatPointsWindow.IsOpen) { __result = false; onlyAllowMovement = false; } } internal static void Close() { Instance?.SetOpen(open: false); } internal static void OpenAt(string featureKey) { if (!((Object)(object)Instance == (Object)null)) { Instance.selectedKey = featureKey; Instance.detailDirty = true; Instance.SetOpen(open: true); } } private void Update() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (awaitingBind != null) { CaptureKey(); } else if (Hotkey != null) { KeyboardShortcut value = Hotkey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { SetOpen(!IsOpen); } } if (!IsOpen) { return; } if (Input.GetKeyDown((KeyCode)27)) { SetOpen(open: false); return; } cursor.Set(wanted: true); GameSkin.Refresh(); if (GameSkin.Ready) { if ((Object)(object)canvas == (Object)null) { Build(); } if (listDirty) { BuildList(); } if (detailDirty) { BuildDetail(); } RefreshListState(); } } private void OnDisable() { SetOpen(open: false); } private void OnDestroy() { if ((Object)(object)canvas != (Object)null) { Object.Destroy((Object)(object)((Component)canvas).gameObject); } } private void SetOpen(bool open) { if (open != IsOpen) { IsOpen = open; awaitingBind = null; awaitingRow = null; UiFactory.SetVisible(canvas, open); if (open) { detailDirty = true; } else { cursor.Release(); } } } private void CaptureKey() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (!Input.anyKeyDown) { return; } foreach (KeyCode value in Enum.GetValues(typeof(KeyCode))) { if (Input.GetKeyDown(value)) { if ((int)value != 27) { awaitingBind.BoxedValue = (object)new KeyboardShortcut(value, Array.Empty<KeyCode>()); } awaitingRow?.Refresh(); awaitingRow?.SetBindPrompt(waiting: false); awaitingBind = null; awaitingRow = null; break; } } } private void Build() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) canvas = UiFactory.CreateCanvas("LGP_Settings", 200, interactive: true); Image obj = UiFactory.Fill(((Component)canvas).transform, "Dim", new Color(0f, 0f, 0f, 0.66f)); UiFactory.Stretch(((Graphic)obj).rectTransform); ((Graphic)obj).raycastTarget = true; RectTransform obj2 = UiFactory.Panel(((Component)canvas).transform, "Window", GameSkin.PanelKind.Main, opaque: true); obj2.anchorMin = new Vector2(0.5f, 0.5f); obj2.anchorMax = new Vector2(0.5f, 0.5f); obj2.pivot = new Vector2(0.5f, 0.5f); obj2.anchoredPosition = Vector2.zero; obj2.sizeDelta = new Vector2(1000f, 620f); RectTransform obj3 = UiFactory.Vertical((Transform)(object)obj2, "Body", 10f, 18); UiFactory.Stretch(obj3); RectTransform parent = UiFactory.Horizontal((Transform)(object)obj3, "TitleBar", 10f, 34f); UiFactory.Size((Component)(object)UiFactory.Label((Transform)(object)parent, "Title", "LateGamePerformance 1.5.0", GameSkin.TextKind.Header, 26f, (TextAlignmentOptions)513), 800f, 32f); UiFactory.Size((Component)(object)UiFactory.Button((Transform)(object)parent, "Close", "Close", delegate { SetOpen(open: false); }), 120f, 32f); RectTransform obj4 = UiFactory.Horizontal((Transform)(object)obj3, "Columns", 16f, 0f); UiFactory.Size((Component)(object)obj4, 0f, 530f); RectTransform val = UiFactory.Vertical((Transform)(object)obj4, "Left", 8f); UiFactory.Size((Component)(object)val, 340f, 530f); listContent = UiFactory.Scroll((Transform)(object)val, "FeatureList", out var scroll); UiFactory.Size((Component)(object)scroll, 340f, 480f); showEveryButton = UiFactory.Button((Transform)(object)val, "ShowEvery", string.Empty, delegate { showEverySetting.Value = !showEverySetting.Value; listDirty = true; detailDirty = true; }); UiFactory.Size((Component)(object)showEveryButton, 340f, 34f); RectTransform val2 = UiFactory.Vertical((Transform)(object)obj4, "Right", 6f); UiFactory.Size((Component)(object)val2, 608f, 530f); detailTitle = UiFactory.Label((Transform)(object)val2, "DetailTitle", string.Empty, GameSkin.TextKind.Header, 24f, (TextAlignmentOptions)513); UiFactory.Size((Component)(object)detailTitle, 0f, 30f); detailBlurb = UiFactory.Label((Transform)(object)val2, "DetailBlurb", string.Empty, GameSkin.TextKind.Body, 17f, (TextAlignmentOptions)257); ((TMP_Text)detailBlurb).enableWordWrapping = true; UiFactory.Size((Component)(object)detailBlurb, 0f, 64f); detailState = UiFactory.Label((Transform)(object)val2, "DetailState", string.Empty, GameSkin.TextKind.Body, 16f, (TextAlignmentOptions)513); ((Graphic)detailState).color = GameSkin.QuietColor; UiFactory.Size((Component)(object)detailState, 0f, 22f); detailContent = UiFactory.Scroll((Transform)(object)val2, "Detail", out var scroll2); UiFactory.Size((Component)(object)scroll2, 608f, 400f); listDirty = true; detailDirty = true; } private void BuildList() { listDirty = false; Clear(listContent); listLabels.Clear(); listPicks.Clear(); listGroups.Clear(); AddCategory("Gameplay"); if (showEverySetting.Value) { AddCategory("Fixes and performance"); } HGTextMeshProUGUI componentInChildren = ((Component)showEveryButton).GetComponentInChildren<HGTextMeshProUGUI>(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).text = (showEverySetting.Value ? "Hide fixes and tuning" : "Show fixes and tuning"); } } private void AddCategory(string category) { UiFactory.Size((Component)(object)UiFactory.Label((Transform)(object)listContent, "Header" + category, category.ToUpperInvariant(), GameSkin.TextKind.Header, 17f, (TextAlignmentOptions)513), 0f, 26f); IReadOnlyList<PatchRegistry.Group> groups = PatchRegistry.Groups; for (int i = 0; i < groups.Count; i++) { PatchRegistry.Group obj = groups[i]; if (!(MenuCatalog.CategoryOf(obj.Key) != category)) { if (string.IsNullOrEmpty(selectedKey)) { selectedKey = obj.Key; } RectTransform parent = UiFactory.Horizontal((Transform)(object)listContent, "Row" + obj.Key, 8f, 34f); PatchRegistry.Group captured = obj; Button val = UiFactory.Button((Transform)(object)parent, "Toggle", string.Empty, delegate { PatchRegistry.SetEnabled(captured, !captured.Active); }); UiFactory.Size((Component)(object)val, 62f, 30f); Button obj2 = UiFactory.Button((Transform)(object)parent, "Pick", MenuCatalog.TitleOf(obj.Key), delegate { selectedKey = captured.Key; detailDirty = true; }); UiFactory.Size((Component)(object)obj2, 254f, 30f); HGTextMeshProUGUI componentInChildren = ((Component)obj2).GetComponentInChildren<HGTextMeshProUGUI>(); if ((Object)(object)componentInChildren != (Object)null) { ((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)513; ((TMP_Text)componentInChildren).fontSize = 17f; } listLabels.Add(((Component)val).GetComponentInChildren<HGTextMeshProUGUI>()); listPicks.Add(componentInChildren); listGroups.Add(obj); } } } private void RefreshListState() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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) for (int i = 0; i < listGroups.Count && i < listLabels.Count; i++) { HGTextMeshProUGUI val = listLabels[i]; if ((Object)(object)val != (Object)null) { bool active = listGroups[i].Active; ((TMP_Text)val).text = (active ? "ON" : "OFF"); ((Graphic)val).color = (active ? GameSkin.HeaderColor : GameSkin.QuietColor); } if (i < listPicks.Count && (Object)(object)listPicks[i] != (Object)null) { ((Graphic)listPicks[i]).color = ((listGroups[i].Key == selectedKey) ? GameSkin.HeaderColor : GameSkin.BodyColor); } } } private void BuildDetail() { //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) detailDirty = false; Clear(detailContent); rows.Clear(); PatchRegistry.Group obj = FindSelected(); if (obj == null) { return; } ((TMP_Text)detailTitle).text = MenuCatalog.TitleOf(obj.Key); ((TMP_Text)detailBlurb).text = MenuCatalog.BlurbOf(obj.Key, obj.Description); ((TMP_Text)detailState).text = (obj.Active ? "Turned on" : "Turned off"); if (!string.IsNullOrEmpty(obj.Error)) { HGTextMeshProUGUI obj2 = detailState; ((TMP_Text)obj2).text = ((TMP_Text)obj2).text + " - last error: " + obj.Error; } int num = 0; ConfigEntryBase[] configEntries = Plugin.Cfg.GetConfigEntries(); foreach (ConfigEntryBase val in configEntries) { if (!(val.Definition.Section != obj.Key) && (showEverySetting.Value || MenuCatalog.IsPlayerFacing(obj.Key, val.Definition.Key))) { rows.Add(SettingRow.Create((Transform)(object)detailContent, val, RequestBind)); num++; } } if (num == 0) { HGTextMeshProUGUI obj3 = UiFactory.Label((Transform)(object)detailContent, "None", "Nothing to set for this one.", GameSkin.TextKind.Body, 17f, (TextAlignmentOptions)513); ((Graphic)obj3).color = GameSkin.QuietColor; UiFactory.Size((Component)(object)obj3, 0f, 26f); } HGTextMeshProUGUI obj4 = UiFactory.Label((Transform)(object)detailContent, "Note", "Changes save by themselves.", GameSkin.TextKind.Body, 15f, (TextAlignmentOptions)513); ((Graphic)obj4).color = GameSkin.QuietColor; UiFactory.Size((Component)(object)obj4, 0f, 24f); } private void RequestBind(ConfigEntryBase entry) { awaitingBind = entry; awaitingRow = null; for (int i = 0; i < rows.Count; i++) { bool flag = rows[i].Entry == entry; rows[i].SetBindPrompt(flag); if (flag) { awaitingRow = rows[i]; } } } private PatchRegistry.Group FindSelected() { IReadOnlyList<PatchRegistry.Group> groups = PatchRegistry.Groups; for (int i = 0; i < groups.Count; i++) { if (groups[i].Key == selectedKey) { return groups[i]; } } if (groups.Count <= 0) { return null; } return groups[0]; } private static void Clear(RectTransform parent) { if (!((Object)(object)parent == (Object)null)) { for (int num = ((Transform)parent).childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)((Transform)parent).GetChild(num)).gameObject); } } } } internal static class PatchGroups { internal static void RegisterAll() { PatchRegistry.Register("BuffStatsFilter", "Skip full stat recalculation when a pure damage-over-time buff changes count. Bleed and poison stacks no longer force a stat pass per tick.", defaultOn: true, BuffStatsFilterPatch.Apply); PatchRegistry.Register("NavPathBudget", "Limit synchronous AI path computations per physics tick and stagger repath timers. The game ships this throttle in a broken state.", defaultOn: true, NavPathBudgetPatch.Apply); PatchRegistry.Register("TargetSearchGc", "Remove per-call allocations from target searches used by missiles, drones, turrets, and AI.", defaultOn: true, TargetSearchGcPatch.Apply); PatchRegistry.Register("DamageNumberBatch", "Batch damage-number particle writes to one copy per frame instead of one per number.", defaultOn: true, DamageNumberBatchPatch.Apply, DamageNumberBatchPatch.Unapply); PatchRegistry.Register("RaycastThrottle", "Throttle AI obstruction raycasts to the interval the game defines but never uses.", defaultOn: true, RaycastThrottlePatch.Apply); PatchRegistry.Register("HealthBarThrottle", "Restore the health-bar update throttle that the game defeats on load.", defaultOn: true, HealthBarThrottlePatch.Apply); PatchRegistry.Register("TeamItemCountCache", "Cache team item counts briefly. Removes repeated full scans of all characters during teleporter events.", defaultOn: true, TeamItemCountCachePatch.Apply, TeamItemCountCachePatch.Unapply); PatchRegistry.Register("ModelCameraPass", "One camera pass over character models instead of two, and a frame stride on the overlay scan. The base game measures hurtbox distances for models that draw nothing.", defaultOn: true, ModelCameraPassPatch.Apply); PatchRegistry.Register("PerfReadout", "Frame times and entity counts on screen and in the log.", defaultOn: true, PerfReadoutPatch.Apply, PerfReadoutPatch.Unapply); PatchRegistry.Register("FixedTimeCatchup", "Clamp physics catch-up so a slow frame cannot snowball into a freeze. The game slows down under extreme load instead.", defaultOn: true, FixedTimeCatchupPatch.Apply, FixedTimeCatchupPatch.Unapply); PatchRegistry.Register("SkipIntro", "Boot straight to the title screen without the startup video.", defaultOn: true, SkipIntroPatch.Apply, SkipIntroPatch.Unapply); PatchRegistry.Register("CritOverstack", "Crit chance above 100 percent converts into extra crit damage.", defaultOn: true, CritOverstackPatch.Apply); PatchRegistry.Register("BugFixes", "Guards for vanilla code that throws exceptions during normal play.", defaultOn: true, BugFixesPatch.Apply); PatchRegistry.Register("Sharing", "Item and money sharing between players. Off by default, because it changes the balance of the run for every player. Host-side, clients need no mod.", defaultOn: false, SharingPatch.Apply); PatchRegistry.Register("EmptyChests", "Remove opened chests, used barrels, and spent multishops after a delay.", defaultOn: true, EmptyChestsPatch.Apply, EmptyChestsPatch.Unapply); PatchRegistry.Register("AutoSprint", "Sprint turns on by itself while moving.", defaultOn: true, AutoSprintPatch.Apply, AutoSprintPatch.Unapply); PatchRegistry.Register("DpsMeter", "Damage per player for the stage you are on. Shows every connected player.", defaultOn: true, DpsMeterPatch.Apply, DpsMeterPatch.Unapply); PatchRegistry.Register("StatPoints", "Earn points as your character levels and spend them on stats. Works with every survivor.", defaultOn: true, StatPointsPatch.Apply, StatPointsPatch.Unapply); } } internal static class PatchRegistry { internal delegate void GroupApplier(Harmony harmony); internal delegate void GroupReverter(); internal sealed class Group { internal string Key; internal string Description; internal bool DefaultOn; internal GroupApplier Apply; internal GroupReverter Revert; internal ConfigEntry<bool> Toggle; internal Harmony Harmony; internal bool Active; internal string Error; } private static readonly List<Group> groups = new List<Group>(); internal static IReadOnlyList<Group> Groups => groups; internal static void Register(string key, string description, bool defaultOn, GroupApplier apply, GroupReverter revert = null) { groups.Add(new Group { Key = key, Description = description, DefaultOn = defaultOn, Apply = apply, Revert = revert }); } internal static int ApplyAll() { PatchGroups.RegisterAll(); int num = 0; foreach (Group group in groups) { group.Toggle = Plugin.Cfg.Bind<bool>("Features", group.Key, group.DefaultOn, group.Description); Group captured = group; captured.Toggle.SettingChanged += delegate { if (captured.Toggle.Value) { Enable(captured); } else { Disable(captured); } }; if (group.Toggle.Value && Enable(group)) { num++; } } return num; } internal static bool Enable(Group group) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown if (group.Active) { return true; } group.Harmony = new Harmony("com.tim.LateGamePerformance." + group.Key); try { group.Apply(group.Harmony); group.Active = true; group.Error = null; return true; } catch (Exception ex) { group.Error = ex.Message; Plugin.Log.LogError((object)$"Feature '{group.Key}' failed and is off: {ex}"); try { group.Harmony.UnpatchSelf(); } catch (Exception) { } group.Harmony = null; return false; } } internal static void Disable(Group group) { if (group.Active) { try { group.Revert?.Invoke(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Feature '" + group.Key + "' did not clean up: " + ex.Message)); } Harmony harmony = group.Harmony; if (harmony != null) { harmony.UnpatchSelf(); } group.Harmony = null; group.Active = false; } } internal static void SetEnabled(Group group, bool enabled) { if (group.Toggle != null) { group.Toggle.Value = enabled; } if (enabled) { Enable(group); } else { Disable(group); } } internal static void DisableAll() { foreach (Group group in groups) { Disable(group); } } } internal sealed class PerfHud : MonoBehaviour { private const int SampleCount = 512; private const float PeakWindowSeconds = 10f; private const float Width = 290f; private const float Pad = 14f; private const float TitleHeight = 28f; private const float LineHeight = 22f; private static readonly string[] Titles = new string[8] { "Frame", "FPS", "Peak 10s", "Peak run", "Monsters", "Hurtboxes", "GC0 / s", "Heap" }; private readonly float[] samples = new float[512]; private int sampleIndex; private int sampleFill; private readonly float[] secondPeaks = new float[10]; private int lastSecond = -1; private float runPeakFrame; private int lastGcCount; private float gcStamp; private float gcPerSecond; private float nextLog; private bool wasRunning; private Canvas canvas; private HGTextMeshProUGUI[] values; internal static PerfHud Instance { get; private set; } internal static void Install(GameObject host) { Instance = host.AddComponent<PerfHud>(); } private void Update() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!PerfReadoutPatch.Active) { Show(visible: false); return; } if (PerfReadoutPatch.ToggleKey != null) { KeyboardShortcut value = PerfReadoutPatch.ToggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { PerfReadoutPatch.ShowPanel.Value = !PerfReadoutPatch.ShowPanel.Value; } } Sample(); if (!PerfReadoutPatch.ShowPanel.Value || !Object.op_Implicit((Object)(object)Run.instance) || ModMenu.IsOpen || StatPointsWindow.IsOpen) { Show(visible: false); return; } GameSkin.Refresh(); if (GameSkin.Ready) { if ((Object)(object)canvas == (Object)null) { Build(); } Show(visible: true); WriteValues(); } } private void OnDestroy() { if ((Object)(object)canvas != (Object)null) { Object.Destroy((Object)(object)((Component)canvas).gameObject); } } private void Show(bool visible) { UiFactory.SetVisible(canvas, visible); } private void Sample() { float unscaledDeltaTime = Time.unscaledDeltaTime; samples[sampleIndex] = unscaledDeltaTime; sampleIndex = (sampleIndex + 1) % 512; if (sampleFill < 512) { sampleFill++; } float unscaledTime = Time.unscaledTime; RollPeaks(Mathf.FloorToInt(unscaledTime), unscaledDeltaTime); if (!Object.op_Implicit((Object)(object)Run.instance)) { runPeakFrame = 0f; } else if (unscaledDeltaTime > runPeakFrame) { runPeakFrame = unscaledDeltaTime; } if (unscaledTime - gcStamp >= 1f) { int num = GC.CollectionCount(0); gcPerSecond = (float)(num - lastGcCount) / (unscaledTime - gcStamp); lastGcCount = num; gcStamp = unscaledTime; } float value = PerfReadoutPatch.LogInterval.Value; bool flag = Object.op_Implicit((Object)(object)Run.instance); if (flag != wasRunning) { wasRunning = flag; nextLog = unscaledTime + 2f; } if (value > 0f && flag && unscaledTime >= nextLog) { nextLog = unscaledTime + value; Plugin.Log.LogInfo((object)LogLine()); } } private void Build() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) canvas = UiFactory.CreateCanvas("LGP_PerfReadout", 99, interactive: false); RectTransform val = UiFactory.Panel(((Component)canvas).transform, "Panel"); float value = PerfReadoutPatch.PanelX.Value; float num = 1f - PerfReadoutPatch.PanelY.Value; val.anchorMin = new Vector2(value, num); val.anchorMax = new Vector2(value, num); val.pivot = new Vector2(value, num); val.anchoredPosition = Vector2.zero; val.sizeDelta = new Vector2(290f, 56f + (float)Titles.Length * 22f); UiFactory.Row(((TMP_Text)UiFactory.Label((Transform)(object)val, "Title", "PERFORMANCE", GameSkin.TextKind.Header, 20f, (TextAlignmentOptions)513)).rectTransform, 14f, 262f, 14f, 28f); values = (HGTextMeshProUGUI[])(object)new HGTextMeshProUGUI[Titles.Length]; for (int i = 0; i < Titles.Length; i++) { float y = 42f + (float)i * 22f; HGTextMeshProUGUI obj = UiFactory.Label((Transform)(object)val, "Label" + i, Titles[i], GameSkin.TextKind.Body, 16f, (TextAlignmentOptions)513); ((Graphic)obj).color = GameSkin.QuietColor; UiFactory.Row(((TMP_Text)obj).rectTransform, 14f, 130f, y, 22f); values[i] = UiFactory.Label((Transform)(object)val, "Value" + i, string.Empty, GameSkin.TextKind.Header, 17f, (TextAlignmentOptions)516); UiFactory.Row(((TMP_Text)values[i]).rectTransform, 144f, 132f, y, 22f); } } private void WriteValues() { float num = Average(); ((TMP_Text)values[0]).text = $"{num * 1000f:0.0} ms"; ((TMP_Text)values[1]).text = ((num > 0f) ? (1f / num) : 0f).ToString("0", CultureInfo.InvariantCulture); ((TMP_Text)values[2]).text = $"{PeakFrame() * 1000f:0.0} ms"; ((TMP_Text)values[3]).text = $"{runPeakFrame * 1000f:0.0} ms"; ((TMP_Text)values[4]).text = Monsters().ToString(CultureInfo.InvariantCulture); ((TMP_Text)values[5]).text = HurtBox.readOnlyBullseyesList.Count.ToString(CultureInfo.InvariantCulture); ((TMP_Text)values[6]).text = gcPerSecond.ToString("0.0", CultureInfo.InvariantCulture); ((TMP_Text)values[7]).text = $"{GC.GetTotalMemory(forceFullCollection: false) / 1048576} MB"; } private void RollPeaks(int second, float frame) { int num = secondPeaks.Length; if (lastSecond < 0) { lastSecond = second; } else if (second > lastSecond) { int num2 = second - lastSecond; if (num2 >= num) { Array.Clear(secondPeaks, 0, num); } else { for (int i = 1; i <= num2; i++) { secondPeaks[((lastSecond + i) % num + num) % num] = 0f; } } lastSecond = second; } int num3 = (second % num + num) % num; if (frame > secondPeaks[num3]) { secondPeaks[num3] = frame; } } private float PeakFrame() { float num = 0f; for (int i = 0; i < secondPeaks.Length; i++) { if (secondPeaks[i] > num) { num = secondPeaks[i]; } } return num; } private float Average() { if (sampleFill == 0) { return 0f; } float num = 0f; for (int i = 0; i < sampleFill; i++) { num += samples[i]; } return num / (float)sampleFill; } private static int Monsters() { return TeamComponent.GetTeamMembers((TeamIndex)2).Count; } private string LogLine() { float num = Average(); return string.Format(CultureInfo.InvariantCulture, "PERF stage {0} | frame avg {1:0.0} ms ({2:0} fps), peak {3:0.0} ms in {4:0} s, run peak {5:0.0} ms | bodies {6}, monsters {7}, models {8}, hurtboxes {9} | gc0 {10:0.0}/s, heap {11:0} MB", Clock(DpsMeterPatch.StageSeconds), num * 1000f, (num > 0f) ? (1f / num) : 0f, PeakFrame() * 1000f, 10f, runPeakFrame * 1000f, CharacterBody.readOnlyInstancesList.Count, Monsters(), InstanceTracker.GetInstancesList<CharacterModel>().Count, HurtBox.readOnlyBullseyesList.Count, gcPerSecond, GC.GetTotalMemory(forceFullCollection: false) / 1048576); } private static string Clock(float seconds) { int num = Mathf.Max(0, Mathf.FloorToInt(seconds)); return (num / 60).ToString(CultureInfo.InvariantCulture) + ":" + (num % 60).ToString("00", CultureInfo.InvariantCulture); } } [BepInPlugin("com.tim.LateGamePerformance", "LateGamePerformance", "1.5.0")] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "com.tim.LateGamePerformance"; public const string Name = "LateGamePerformance"; public const string Version = "1.5.0"; internal static ManualLogSource Log; internal static ConfigFile Cfg; private Harmony coreHarmony; private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Cfg = ((BaseUnityPlugin)this).Config; coreHarmony = new Harmony("com.tim.LateGamePerformance.core"); ModMenu.Install(coreHarmony, ((Component)this).gameObject); int num = PatchRegistry.ApplyAll(); StatPointsHud.Install(((Component)this).gameObject); DpsHud.Install(((Component)this).gameObject); StatPointsWindow.Install(((Component)this).gameObject); PerfHud.Install(((Component)this).gameObject); Log.LogInfo((object)string.Format("{0} {1}: {2} of {3} features active. Press {4} for the menu.", "LateGamePerformance", "1.5.0", num, PatchRegistry.Groups.Count, ModMenu.Hotkey.Value)); } private void OnDestroy() { ModMenu.Close(); PatchRegistry.DisableAll(); Harmony obj = coreHarmony; if (obj != null) { obj.UnpatchSelf(); } } } internal sealed class StatPointsHud : MonoBehaviour { [CompilerGenerated] private static class <>O { public static UnityAction <0>__Open; } private const float BadgeSize = 74f; private static ConfigEntry<bool> showBadge; private static ConfigEntry<KeyboardShortcut> openKey; private static ConfigEntry<float> badgeX; private static ConfigEntry<float> badgeY; private Canvas canvas; private RectTransform badge; private HGTextMeshProUGUI count; private HGTextMeshProUGUI word; private Image backing; internal static StatPointsHud Instance { get; private set; } internal static void Install(GameObject host) { //IL_0038: 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) //IL_0083: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown showBadge = Plugin.Cfg.Bind<bool>("StatPoints", "ShowBadge", true, "Show a badge on screen while you have points to spend."); openKey = Plugin.Cfg.Bind<KeyboardShortcut>("StatPoints", "OpenKey", new KeyboardShortcut((KeyCode)284, Array.Empty<KeyCode>()), "Key that opens the stat points window."); badgeX = Plugin.Cfg.Bind<float>("StatPoints", "BadgeX", 0.028f, new ConfigDescription("Badge position across the screen, 0 is left and 1 is right.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); badgeY = Plugin.Cfg.Bind<float>("StatPoints", "BadgeY", 0.4f, new ConfigDescription("Badge position down the screen, 0 is top and 1 is bottom.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); Instance = host.AddComponent<StatPointsHud>(); } private void Update() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) if (openKey != null) { KeyboardShortcut value = openKey.Value; if (((KeyboardShortcut)(ref value)).IsDown() && !ModMenu.IsOpen) { StatPointsWindow.Toggle(); return; } } int num = Available(); if (showBadge == null || !showBadge.Value || !StatPointsPatch.CanSpend || num <= 0 || !Object.op_Implicit((Object)(object)Run.instance) || ModMenu.IsOpen || StatPointsWindow.IsOpen) { UiFactory.SetVisible(canvas, visible: false); return; } GameSkin.Refresh(); if (GameSkin.Ready) { if ((Object)(object)canvas == (Object)null) { Build(); } UiFactory.SetVisible(canvas, visible: true); ((TMP_Text)count).text = num.ToString(); ((TMP_Text)word).text = ((num == 1) ? "point" : "points"); float num2 = 0.75f + 0.25f * Mathf.Sin(Time.unscaledTime * 3f); Color headerColor = GameSkin.HeaderColor; ((Graphic)backing).color = new Color(headerColor.r, headerColor.g, headerColor.b, 0.2f * num2); } } private void OnDestroy() { if ((Object)(object)canvas != (Object)null) { Object.Destroy((Object)(object)((Component)canvas).gameObject); } } private static int Available() { if (!StatPointsPatch.TryGetLocal(out var tracker, out var _)) { return 0; } return tracker.AvailablePoints(); } private void Build() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown canvas = UiFactory.CreateCanvas("LGP_StatBadge", 98, interactive: true); badge = UiFactory.Panel(((Component)canvas).transform, "Badge"); float value = badgeX.Value; float num = 1f - badgeY.Value; badge.anchorMin = new Vector2(value, num); badge.anchorMax = new Vector2(value, num); badge.pivot = new Vector2(value, num); badge.anchoredPosition = Vector2.zero; badge.sizeDelta = new Vector2(74f, 92f); backing = UiFactory.Fill((Transform)(object)badge, "Pulse", Color.clear); UiFactory.Stretch(((Graphic)backing).rectTransform, 3f, 3f); GameObject val = new GameObject("Open", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent((Transform)(object)badge, false); UiFactory.Stretch(component); Image component2 = val.GetComponent<Image>(); ((Graphic)component2).color = new Color(0f, 0f, 0f, 0.01f); Button obj = val.AddComponent<Button>(); ((Selectable)obj).targetGraphic = (Graphic)(object)component2; ButtonClickedEvent onClick = obj.onClick; object obj2 = <>O.<0>__Open; if (obj2 == null) { UnityAction val2 = StatPointsWindow.Open; <>O.<0>__Open = val2; obj2 = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj2); count = UiFactory.Label((Transform)(object)badge, "Count", "0", GameSkin.TextKind.Header, 30f, (TextAlignmentOptions)514); UiFactory.Row(((TMP_Text)count).rectTransform, 0f, 74f, 6f, 34f); word = UiFactory.Label((Transform)(object)badge, "Word", "points", GameSkin.TextKind.Body, 14f, (TextAlignmentOptions)514); ((Graphic)word).color = GameSkin.QuietColor; UiFactory.Row(((TMP_Text)word).rectTransform, 0f, 74f, 40f, 18f); RectTransform parent = badge; KeyboardShortcut value2 = openKey.Value; HGTextMeshProUGUI obj3 = UiFactory.Label((Transform)(object)parent, "Hint", ((object)((KeyboardShortcut)(ref value2)).MainKey/*cast due to .constrained prefix*/).ToString(), GameSkin.TextKind.Body, 13f, (TextAlignmentOptions)514); ((Graphic)obj3).color = GameSkin.QuietColor; UiFactory.Row(((TMP_Text)obj3).rectTransform, 0f, 74f, 60f, 18f); } } internal sealed class StatPointsWindow : MonoBehaviour { private const float WindowWidth = 520f; private const float Pad = 18f; private Canvas canvas; private StatPointsPanel panel; private readonly CursorHold cursor = new CursorHold(); internal static StatPointsWindow Instance { get; private set; } internal static bool IsOpen { get; private set; } internal static void Install(GameObject host) { Instance = host.AddComponent<StatPointsWindow>(); } internal static void Toggle() { Instance?.SetOpen(!IsOpen); } internal static void Open() { Instance?.SetOpen(open: true); } internal static void Close() { Instance?.SetOpen(open: false); } private void Update() { if (!IsOpen) { return; } if (Input.GetKeyDown((KeyCode)27) || !Object.op_Implicit((Object)(object)Run.instance) || ModMenu.IsOpen) { SetOpen(open: false); return; } cursor.Set(wanted: true); GameSkin.Refresh(); if (GameSkin.Ready) { if ((Object)(object)canvas == (Object)null) { Build(); } UiFactory.SetVisible(canvas, visible: true); panel.Refresh(); } } private void OnDisable() { SetOpen(open: false); } private void OnDestroy() { if ((Object)(object)canvas != (Object)null) { Object.Destroy((Object)(object)((Component)canvas).gameObject); } } private void SetOpen(bool open) { if (open != IsOpen) { IsOpen = open; UiFactory.SetVisible(canvas, open); if (!open) { cursor.Release(); } } } private void Build() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) canvas = UiFactory.CreateCanvas("LGP_StatPoints", 190, interactive: true); Image obj = UiFactory.Fill(((Component)canvas).transform, "Dim", new Color(0f, 0f, 0f, 0.55f)); UiFactory.Stretch(((Graphic)obj).rectTransform); ((Graphic)obj).raycastTarget = true; RectTransform obj2 = UiFactory.Panel(((Component)canvas).transform, "Window", GameSkin.PanelKind.Main, opaque: true); obj2.anchorMin = new Vector2(0.5f, 0.5f); obj2.anchorMax = new Vector2(0.5f, 0.5f); obj2.pivot = new Vector2(0.5f, 0.5f); obj2.anchoredPosition = Vector2.zero; obj2.sizeDelta = new Vector2(520f, 480f); RectTransform val = UiFactory.Vertical((Transform)(object)obj2, "Body", 10f, 18); UiFactory.Stretch(val); RectTransform parent = UiFactory.Horizontal((Transform)(object)val, "TitleBar", 10f, 34f); UiFactory.Size((Component)(object)UiFactory.Label((Transform)(object)parent, "Title", "LEVEL UP", GameSkin.TextKind.Header, 26f, (TextAlignmentOptions)513), 340f, 32f); UiFactory.Size((Component)(object)UiFactory.Button((Transform)(object)parent, "Close", "Close", delegate { SetOpen(open: false); }), 110f, 32f); panel = new StatPointsPanel((Transform)(object)val); } } } namespace LateGamePerformance.Ui { internal sealed class CursorHold { private readonly List<MPEventSystem> linked = new List<MPEventSystem>(); internal void Set(bool wanted) { if (!wanted) { Release(); return; } for (int num = linked.Count - 1; num >= 0; num--) { if ((Object)(object)linked[num] == (Object)null) { linked.RemoveAt(num); } } ReadOnlyCollection<MPEventSystem> readOnlyInstancesList = MPEventSystem.readOnlyInstancesList; for (int i = 0; i < readOnlyInstancesList.Count; i++) { MPEventSystem val = readOnlyInstancesList[i]; if (!((Object)(object)val == (Object)null) && !linked.Contains(val)) { int cursorOpenerCount = val.cursorOpenerCount; val.cursorOpenerCount = cursorOpenerCount + 1; cursorOpenerCount = val.cursorOpenerForGamepadCount; val.cursorOpenerForGamepadCount = cursorOpenerCount + 1; linked.Add(val); } } } internal void Release() { for (int i = 0; i < linked.Count; i++) { MPEventSystem val = linked[i]; if (!((Object)(object)val == (Object)null)) { int cursorOpenerCount = val.cursorOpenerCount; val.cursorOpenerCount = cursorOpenerCount - 1; cursorOpenerCount = val.cursorOpenerForGamepadCount; val.cursorOpenerForGamepadCount = cursorOpenerCount - 1; } } linked.Clear(); } } internal static class GameSkin { internal enum PanelKind { Main, Header, Detail } internal enum TextKind { Body, Header, Detail } private static UISkinData data; private static bool searched; internal static UISkinData Data { get { if ((Object)(object)data == (Object)null && !searched) { searched = true; data = Find(); if ((Object)(object)data == (Object)null) { Plugin.Log.LogWarning((object)"No UISkinData found yet. Menus fall back to plain colors until one loads."); } } return data; } } internal static bool Ready => (Object)(object)Data != (Object)null; internal static float ButtonHeight { get { if (!((Object)(object)Data != (Object)null)) { return 32f; } return Mathf.Max(28f, Data.buttonStyle.recommendedHeight); } } internal static Color HeaderColor { get { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Data != (Object)null)) { return new Color(1f, 0.78f, 0.33f); } return Data.headerTextStyle.color; } } internal static Color BodyColor { get { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Data != (Object)null)) { return Color.white; } return Data.bodyTextStyle.color; } } internal static Color DetailColor { get { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Data != (Object)null)) { return new Color(0.6f, 0.64f, 0.71f); } return Data.detailTextStyle.color; } } internal static Color QuietColor { get { //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) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) Color bodyColor = BodyColor; return new Color(bodyColor.r, bodyColor.g, bodyColor.b, bodyColor.a * 0.55f); } } internal static void Refresh() { if ((Object)(object)data == (Object)null) { searched = false; } } private static UISkinData Find() { UISkinData val = null; int num = 0; List<UISkinData> list = new List<UISkinData>(Resources.FindObjectsOfTypeAll<UISkinData>()); BaseSkinController[] array = Resources.FindObjectsOfTypeAll<BaseSkinController>(); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && (Object)(object)array[i].skinData != (Object)null && !list.Contains(array[i].skinData)) { list.Add(array[i].skinData); } } for (int j = 0; j < list.Count; j++) { int num2 = Score(list[j]); if (num2 > num) { num = num2; val = list[j]; } } if ((Object)(object)val != (Object)null) { Plugin.Log.LogInfo((object)$"UI skin: '{((Object)val).name}' out of {list.Count} candidates, score {num}."); } return val; } private static int Score(UISkinData skin) { if ((Object)(object)skin == (Object)null) { return 0; } int num = 1; if ((Object)(object)skin.bodyTextStyle.font != (Object)null) { num += 4; } if ((Object)(object)skin.headerTextStyle.font != (Object)null) { num += 2; } if (skin.bodyTextStyle.color.a > 0.5f) { num += 4; } if (skin.headerTextStyle.color.a > 0.5f) { num += 2; } if ((Object)(object)skin.mainPanelStyle.sprite != (Object)null) { num += 4; } if (skin.mainPanelStyle.color.a > 0.2f) { num += 2; } if ((Object)(object)skin.buttonStyle.sprite != (Object)null) { num += 2; } return num; } internal static void ApplyPanel(Image image, PanelKind kind) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) UISkinData val = Data; if (!((Object)(object)val == (Object)null) && !((Object)(object)image == (Object)null)) { switch (kind) { case PanelKind.Header: ((PanelStyle)(ref val.headerPanelStyle)).Apply(image); break; case PanelKind.Detail: ((PanelStyle)(ref val.detailPanelStyle)).Apply(image); break; default: ((PanelStyle)(ref val.mainPanelStyle)).Apply(image); break; } if ((Object)(object)image.sprite != (Object)null) { image.type = (Type)(!(image.sprite.border == Vector4.zero)); } } } internal static void ApplyText(TextMeshProUGUI label, TextKind kind, bool useSkinAlignment = false) { UISkinData val = Data; if (!((Object)(object)val == (Object)null) && !((Object)(object)label == (Object)null)) { switch (kind) { case TextKind.Header: ((TextStyle)(ref val.headerTextStyle)).Apply(label, useSkinAlignment); break; case TextKind.Detail: ((TextStyle)(ref val.detailTextStyle)).Apply(label, useSkinAlignment); break; default: ((TextStyle)(ref val.bodyTextStyle)).Apply(label, useSkinAlignment); break; } } } internal static void ApplyButton(Button button, Image image, TextMeshProUGUI label) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) UISkinData val = Data; if (!((Object)(object)val == (Object)null)) { ButtonStyle buttonStyle = val.buttonStyle; ColorBlock defaultColorBlock = ColorBlock.defaultColorBlock; ((ColorBlock)(ref defaultColorBlock)).normalColor = new Color(1f, 1f, 1f, 0.1f); ((ColorBlock)(ref defaultColorBlock)).highlightedColor = new Color(1f, 1f, 1f, 0.26f); ((ColorBlock)(ref defaultColorBlock)).pressedColor = new Color(1f, 1f, 1f, 0.4f); ((ColorBlock)(ref defaultColorBlock)).selectedColor = new Color(1f, 1f, 1f, 0.16f); ((ColorBlock)(ref defaultColorBlock)).disabledColor = new Color(1f, 1f, 1f, 0.04f); ((ColorBlock)(ref defaultColorBlock)).fadeDuration = 0.08f; if ((Object)(object)button != (Object)null) { ((Selectable)button).colors = defaultColorBlock; } if ((Object)(object)image != (Object)null) { image.sprite = null; ((Graphic)image).material = null; ((Graphic)image).color = Color.white; } if ((Object)(object)label != (Object)null) { ((TextStyle)(ref buttonStyle.interactableTextStyle)).Apply(label, false); } } } internal static Color PanelColor(PanelKind kind) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) UISkinData val = Data; if ((Object)(object)val == (Object)null) { return new Color(0.06f, 0.07f, 0.09f, 1f); } return (Color)(kind switch { PanelKind.Header => val.headerPanelStyle.color, PanelKind.Detail => val.detailPanelStyle.color, _ => val.mainPanelStyle.color, }); } } internal sealed class SettingRow { private readonly ConfigEntryBase entry; private readonly Button toggleButton; private readonly HGTextMeshProUGUI toggleLabel; private readonly Slider slider; private readonly HGTextMeshProUGUI readout; private bool writing; internal ConfigEntryBase Entry => entry; internal static SettingRow Create(Transform parent, ConfigEntryBase entry, Action<ConfigEntryBase> onKeyBindRequest) { return new SettingRow(parent, entry, onKeyBindRequest); } private SettingRow(Transform parent, ConfigEntryBase entry, Action<ConfigEntryBase> onKeyBindRequest) { //IL_02b2: Unknown result type (might be due to invalid IL or missing references) this.entry = entry; RectTransform parent2 = UiFactory.Vertical(parent, "Setting_" + entry.Definition.Key, 2f); RectTransform parent3 = UiFactory.Horizontal((Transform)(object)parent2, "Line", 10f, 30f); UiFactory.Size((Component)(object)UiFactory.Label((Transform)(object)parent3, "Name", Spaced(entry.Definition.Key), GameSkin.TextKind.Body, 18f, (TextAlignmentOptions)513), 230f, 28f); Type settingType = entry.SettingType; if (settingType == typeof(bool)) { toggleButton = UiFactory.Button((Transform)(object)parent3, "Toggle", string.Empty, Flip); toggleLabel = ((Component)toggleButton).GetComponentInChildren<HGTextMeshProUGUI>(); UiFactory.Size((Component)(object)toggleButton, 78f, 28f); } else if (settingType == typeof(float) || settingType == typeof(int)) { slider = MakeSlider((Transform)(object)parent3, settingType == typeof(int)); readout = UiFactory.Label((Transform)(object)parent3, "Value", string.Empty, GameSkin.TextKind.Header, 18f, (TextAlignmentOptions)516); UiFactory.Size((Component)(object)readout, 74f, 28f); } else if (settingType == typeof(KeyboardShortcut)) { toggleButton = UiFactory.Button((Transform)(object)parent3, "Bind", string.Empty, delegate { onKeyBindRequest?.Invoke(entry); }); toggleLabel = ((Component)toggleButton).GetComponentInChildren<HGTextMeshProUGUI>(); UiFactory.Size((Component)(object)toggleButton, 150f, 28f); } else if (settingType.IsEnum) { toggleButton = UiFactory.Button((Transform)(object)parent3, "Cycle", string.Empty, CycleEnum); toggleLabel = ((Component)toggleButton).GetComponentInChildren<HGTextMeshProUGUI>(); UiFactory.Size((Component)(object)toggleButton, 170f, 28f); } else { readout = UiFactory.Label((Transform)(object)parent3, "Value", entry.GetSerializedValue(), GameSkin.TextKind.Body, 17f, (TextAlignmentOptions)513); UiFactory.Size((Component)(object)readout, 200f, 28f); } ConfigDescription description = entry.Description; string text = ((description != null) ? description.Description : null); if (!string.IsNullOrEmpty(text)) { HGTextMeshProUGUI obj = UiFactory.Label((Transform)(object)parent2, "Help", text, GameSkin.TextKind.Body, 15f, (TextAlignmentOptions)257); ((Graphic)obj).color = GameSkin.QuietColor; ((TMP_Text)obj).enableWordWrapping = true; ((TMP_Text)obj).overflowMode = (TextOverflowModes)0; UiFactory.Size((Component)(object)obj, 0f, 34f); } Refresh(); } private Slider MakeSlider(Transform parent, bool whole) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Slider", new Type[1] { typeof(RectTransform) }); ((Transform)val.GetComponent<RectTransform>()).SetParent(parent, false); Slider val2 = val.AddComponent<Slider>(); UiFactory.Size((Component)(object)val2, 250f, 24f); UiFactory.Stretch(((Graphic)UiFactory.Fill(val.transform, "Track", new Color(1f, 1f, 1f, 0.14f))).rectTransform, 0f, 9f); RectTransform component = new GameObject("FillArea", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component).SetParent(val.transform, false); UiFactory.Stretch(component, 0f, 9f); Image val3 = UiFactory.Fill((Transform)(object)component, "Fill", GameSkin.HeaderColor); UiFactory.Stretch(((Graphic)val3).rectTransform); RectTransform component2 = new GameObject("HandleArea", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>(); ((Transform)component2).SetParent(val.transform, false); UiFactory.Stretch(component2); Image val4 = UiFactory.Fill((Transform)(object)component2, "Handle", GameSkin.HeaderColor); ((Graphic)val4).raycastTarget = true; ((Graphic)val4).rectTransform.sizeDelta = new Vector2(12f, 0f); val2.fillRect = ((Graphic)val3).rectTransform; val2.handleRect = ((Graphic)val4).rectTransform; ((Selectable)val2).targetGraphic = (Graphic)(object)val4; val2.wholeNumbers = whole; GetRange(out var min, out var max); val2.minValue = min; val2.maxValue = max; ((UnityEvent<float>)(object)val2.onValueChanged).AddListener((UnityAction<float>)OnSlider); return val2; } private void OnSlider(float value) { if (!writing) { if (entry.SettingType == typeof(int)) { entry.BoxedValue = Mathf.RoundToInt(value); } else { entry.BoxedValue = value; } WriteReadout(); } } private void Flip() { entry.BoxedValue = !(bool)entry.BoxedValue; Refresh(); } private void CycleEnum() { Type settingType = entry.SettingType; string[] names = Enum.GetNames(settingType); string value = entry.BoxedValue.ToString(); int num = Array.IndexOf(names, value); entry.BoxedValue = Enum.Parse(settingType, names[(num + 1) % names.Length]); Refresh(); } private void GetRange(out float min, out float max) { ConfigDescription description = entry.Description; AcceptableValueBase val = ((description != null) ? description.AcceptableValues : null); if (!(val is AcceptableValueRange<float> val2)) { if (val is AcceptableValueRange<int> val3) { min = val3.MinValue; max = val3.MaxValue; } else { min = 0f; max = ((entry.SettingType == typeof(int)) ? 100f : 10f); } } else { min = val2.MinValue; max = val2.MaxValue; } } internal void Refresh() { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) writing = true; try { if (entry.SettingType == typeof(bool) && (Object)(object)toggleLabel != (Object)null) { bool flag = (bool)entry.BoxedValue; ((TMP_Text)toggleLabel).text = (flag ? "ON" : "OFF"); ((Graphic)toggleLabel).color = (flag ? GameSkin.HeaderColor : GameSkin.QuietColor); } else if (entry.SettingType == typeof(KeyboardShortcut) && (Object)(object)toggleLabel != (Object)null) { ((TMP_Text)toggleLabel).text = entry.BoxedValue.ToString(); } else if (entry.SettingType.IsEnum && (Object)(object)toggleLabel != (Object)null) { ((TMP_Text)toggleLabel).text = entry.BoxedValue.ToString(); } else if ((Object)(object)slider != (Object)null) { slider.value = Convert.ToSingle(entry.BoxedValue, CultureInfo.InvariantCulture); WriteReadout(); } } finally { writing = false; } } internal void SetBindPrompt(bool waiting) { if ((Object)(object)toggleLabel != (Object)null && entry.SettingType == typeof(KeyboardShortcut)) { ((TMP_Text)toggleLabel).text = (waiting ? "press a key" : entry.BoxedValue.ToString()); } } private void WriteReadout() { if (!((Object)(object)readout == (Object)null)) { ((TMP_Text)readout).text = ((entry.SettingType == typeof(int)) ? ((int)entry.BoxedValue).ToString(CultureInfo.InvariantCulture) : ((float)entry.BoxedValue).ToString("0.###", CultureInfo.InvariantCulture)); } } private static string Spaced(string key) { StringBuilder stringBuilder = new StringBuilder(key.Length + 6); for (int i = 0; i < key.Length; i++) { char c = key[i]; if (i > 0 && char.IsUpper(c) && !char.IsUpper(key[i - 1])) { stringBuilder.Append(' '); stringBuilder.Append(char.ToLowerInvariant(c)); } else { stringBuilder.Append((i == 0) ? c : char.ToLowerInvariant(c)); } } return stringBuilder.ToString(); } } internal sealed class StatPointsPanel { private sealed class StatLine { internal StatPointsPatch.Stat stat; internal HGTextMeshProUGUI value; internal HGTextMeshProUGUI spent; internal Button minus; internal Button plus; } private readonly HGTextMeshProUGUI heading; private readonly HGTextMeshProUGUI note; private readonly List<StatLine> lines = new List<StatLine>(); private readonly Button reset; internal StatPointsPanel(Transform parent) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) RectTransform parent2 = UiFactory.Vertical(parent, "StatPoints", 4f); heading = UiFactory.Label((Transform)(object)parent2, "Heading", string.Empty, GameSkin.TextKind.Header, 21f, (TextAlignmentOptions)513); UiFactory.Size((Component)(object)heading, 0f, 28f); note = UiFactory.Label((Transform)(object)parent2, "Note", string.Empty, GameSkin.TextKind.Body, 16f, (TextAlignmentOptions)513); ((Graphic)note).color = GameSkin.QuietColor; UiFactory.Size((Component)(object)note, 0f, 24f); StatPointsPatch.Stat[] allStats = StatPointsPatch.AllStats; for (int i = 0; i < allStats.Length; i++) { StatPointsPatch.Stat stat = allStats[i]; RectTransform parent3 = UiFactory.Horizontal((Transform)(object)parent2, "Stat" + stat, 8f, 32f); StatPointsPatch.Stat captured = stat; UiFactory.Size((Component)(object)UiFactory.Label((Transform)(object)parent3, "Name", StatPointsPatch.Describe(stat), GameSkin.TextKind.Body, 18f, (TextAlignmentOptions)513), 190f, 30f); HGTextMeshProUGUI val = UiFactory.Label((Transform)(object)parent3, "Value", string.Empty, GameSkin.TextKind.Header, 18f, (TextAlignmentOptions)516); UiFactory.Size((Component)(object)val, 90f, 30f); HGTextMeshProUGUI val2 = UiFactory.Label((Transform)(object)parent3, "Spent", string.Empty, GameSkin.TextKind.Body, 16f, (TextAlignmentOptions)516); ((Graphic)val2).color = GameSkin.QuietColor; UiFactory.Size((Component)(object)val2, 56f, 30f); Button val3 = UiFactory.Button((Transform)(object)parent3, "Minus", "-", delegate { StatPointsPatch.RefundLocal(captured); }); UiFactory.Size((Component)(object)val3, 40f, 30f); Button val4 = UiFactory.Button((Transform)(object)parent3, "Plus", "+", delegate { StatPointsPatch.SpendLocal(captured); }); UiFactory.Size((Component)(object)val4, 40f, 30f); lines.Add(new StatLine { stat = stat, value = val, spent = val2, minus = val3, plus = val4 }); } reset = UiFactory.Button((Transform)(object)parent2, "Reset", "Take every point back", StatPointsPatch.RefundAllLocal); UiFactory.Size((Component)(object)reset, 260f, 32f); Refresh(); } internal void Refresh() { if (!StatPointsPatch.TryGetLocal(out var tracker, out var body)) { ((TMP_Text)heading).text = "Start a run to spend points."; ((TMP_Text)note).text = string.Empty; for (int i = 0; i < lines.Count; i++) { ((TMP_Text)lines[i].value).text = "-"; ((TMP_Text)lines[i].spent).text = string.Empty; ((Selectable)lines[i].minus).interactable = false; ((Selectable)lines[i].plus).interactable = false; } ((Selectable)reset).interactable = false; return; } bool canSpend = StatPointsPatch.CanSpend; int num = tracker.AvailablePoints(); if (canSpend) { ((TMP_Text)heading).text = ((num == 1) ? "1 point to spend" : $"{num} points to spend"); ((TMP_Text)note).text = $"Character level {Mathf.FloorToInt(body.level)}, {tracker.EarnedPoints()} points earned in total."; } else { ((TMP_Text)heading).text = "Points count on the host only"; ((TMP_Text)note).text = "Another machine runs this game, so a point spent here would not reach your character."; } for (int j = 0; j < lines.Count; j++) { StatLine statLine = lines[j]; int spent = tracker.GetSpent(statLine.stat); ((TMP_Text)statLine.value).text = StatPointsPatch.CurrentValue(body, statLine.stat); ((TMP_Text)statLine.spent).text = ((spent > 0) ? ("+" + spent.ToString(CultureInfo.InvariantCulture)) : string.Empty); ((Selectable)statLine.minus).interactable = canSpend && spent > 0; ((Selectable)statLine.plus).interactable = canSpend && num > 0; } ((Selectable)reset).interactable = canSpend && tracker.TotalSpent() > 0; } } internal static class UiFactory { private const float ReferenceWidth = 1920f; private const float ReferenceHeight = 1080f; internal static Canvas CreateCanvas(string name, int sortOrder, bool interactive) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler) }); Object.DontDestroyOnLoad((Object)(object)val); Canvas component = val.GetComponent<Canvas>(); component.renderMode = (RenderMode)0; component.sortingOrder = sortOrder; CanvasScaler component2 = val.GetComponent<CanvasScaler>(); component2.uiScaleMode = (ScaleMode)1; component2.referenceResolution = new Vector2(1920f, 1080f); component2.screenMatchMode = (ScreenMatchMode)0; component2.matchWidthOrHeight = 1f; if (interactive) { val.AddComponent<GraphicRaycaster>(); } return component; } internal static void SetVisible(Canvas canvas, bool visible) { if (!((Object)(object)canvas == (Object)null) && ((Behaviour)canvas).enabled != visible) { ((Behaviour)canvas).enabled = visible; GraphicRaycaster component = ((Component)canvas).GetComponent<GraphicRaycaster>(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = visible; } } } internal static RectTransform Panel(Transform parent, string name, GameSkin.PanelKind kind = GameSkin.PanelKind.Main, bool opaque = false) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); if (!opaque) { GameSkin.ApplyPanel(val.GetComponent<Image>(), kind); return component; } Image component2 = val.GetComponent<Image>(); Color val2 = GameSkin.PanelColor(kind); ((Graphic)component2).color = new Color(val2.r * 0.5f, val2.g * 0.5f, val2.b * 0.5f, 0.97f); GameObject val3 = new GameObject("Skin", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); RectTransform component3 = val3.GetComponent<RectTransform>(); ((Transform)component3).SetParent((Transform)(object)component, false); Stretch(component3); Image component4 = val3.GetComponent<Image>(); ((Graphic)component4).raycastTarget = false; GameSkin.ApplyPanel(component4, kind); return component; } internal static Image Fill(Transform parent, string name, Color color) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); ((Transform)val.GetComponent<RectTransform>()).SetParent(parent, false); Image component = val.GetComponent<Image>(); ((Graphic)component).color = color; ((Graphic)component).raycastTarget = false; return component; } internal static HGTextMeshProUGUI Label(Transform parent, string name, string text, GameSkin.TextKind kind, float fontSize, TextAlignmentOptions alignment) { //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_0043: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); ((Transform)val.GetComponent<RectTransform>()).SetParent(parent, false); HGTextMeshProUGUI obj = val.AddComponent<HGTextMeshProUGUI>(); GameSkin.ApplyText((TextMeshProUGUI)(object)obj, kind); ((TMP_Text)obj).text = text; ((TMP_Text)obj).fontSize = fontSize; ((TMP_Text)obj).alignment = alignment; ((TMP_Text)obj).enableWordWrapping = false; ((TMP_Text)obj).overflowMode = (TextOverflowModes)0; ((Graphic)obj).raycastTarget = false; return obj; } internal static Button Button(Transform parent, string name, string text, Action onClick) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); ((Transform)val.GetComponent<RectTransform>()).SetParent(parent, false); Image component = val.GetComponent<Image>(); Button val2 = val.AddComponent<Button>(); ((Selectable)val2).targetGraphic = (Graphic)(object)component; HGTextMeshProUGUI val3 = Label(val.transform, "Text", text, GameSkin.TextKind.Body, 20f, (TextAlignmentOptions)514); Stretch(((TMP_Text)val3).rectTransform, 10f, 2f); GameSkin.ApplyButton(val2, component, (TextMeshProUGUI)(object)val3); if (onClick != null) { ((UnityEvent)val2.onClick).AddListener((UnityAction)delegate { onClick(); }); } return val2; } internal static RectTransform Vertical(Transform parent, string name, float spacing, int pad = 0) { //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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); VerticalLayoutGroup obj = val.AddComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = spacing; ((LayoutGroup)obj).padding = new RectOffset(pad, pad, pad, pad); ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = false; return component; } internal static RectTransform Horizontal(Transform parent, string name, float spacing, float height) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); HorizontalLayoutGroup obj = val.AddComponent<HorizontalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)obj).spacing = spacing; ((HorizontalOrVerticalLayoutGroup)obj).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)obj).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)obj).childForceExpandHeight = true; ((LayoutGroup)obj).childAlignment = (TextAnchor)3; if (height > 0f) { val.AddComponent<LayoutElement>().minHeight = height; } return component; } internal static LayoutElement Size(Component target, float width, float height = -1f) { LayoutElement val = target.gameObject.GetComponent<LayoutElement>() ?? target.gameObject.AddComponent<LayoutElement>(); if (width > 0f) { val.minWidth = width; val.preferredWidth = width; } if (height > 0f) { val.minHeight = height; val.preferredHeight = height; } return val; } internal static RectTransform Scroll(Transform parent, string name, out ScrollRect scroll) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(parent, false); scroll = val.AddComponent<ScrollRect>(); scroll.horizontal = false; scroll.movementType = (MovementType)2; scroll.scrollSensitivity = 28f; GameObject val2 = new GameObject("Viewport", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(RectMask2D) }); RectTransform component2 = val2.GetComponent<RectTransform>(); ((Transform)component2).SetParent((Transform)(object)component, false); Stretch(component2); ((Graphic)val2.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.01f); RectTransform val3 = Vertical((Transform)(object)component2, "Content", 4f); val3.anchorMin = new Vector2(0f, 1f); val3.anchorMax = new Vector2(1f, 1f); val3.pivot = new Vector2(0.5f, 1f); val3.anchoredPosition = Vector2.zero; val3.sizeDelta = Vector2.zero; ((Component)val3).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2; scroll.viewport = component2; scroll.content = val3; return val3; } internal static void Stretch(RectTransform rect, float padX = 0f, float padY = 0f) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0028: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.offsetMin = new Vector2(padX, padY); rect.offsetMax = new Vector2(0f - padX, 0f - padY); } internal static void Place(RectTransform rect, Vector2 anchor, Vector2 pivot, Vector2 position, Vector2 size) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = anchor; rect.anchorMax = anchor; rect.pivot = pivot; rect.anchoredPosition = position; rect.sizeDelta = size; } internal static void Row(RectTransform rect, float x, float width, float y, float height) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = new Vector2(0f, 1f); rect.anchorMax = new Vector2(0f, 1f); rect.pivot = new Vector2(0f, 1f); rect.anchoredPosition = new Vector2(x, 0f - y); rect.sizeDelta = new Vector2(width, height); } } } namespace LateGamePerformance.Patches { internal static class AutoSprintPatch { private static ConfigEntry<float> holdOffSeconds; private static ConfigEntry<bool> holdToWalk; private const int SprintActionId = 18; private static ConfigEntry<float> moveThreshold; private static readonly Dictionary<CharacterBody, float> suppressedUntil = new Dictionary<CharacterBody, float>(); internal static void Apply(Harmony harmony) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown holdToWalk = Plugin.Cfg.Bind<bool>("AutoSprint", "HoldSprintKeyToWalk", true, "Reverses the sprint key. You sprint by default. Hold the sprint key to walk."); holdOffSeconds = Plugin.Cfg.Bind<float>("AutoSprint", "HoldOffSeconds", 0.4f, new ConfigDescription("Pause before sprint resumes after a skill that cancels sprint.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); moveThreshold = Plugin.Cfg.Bind<float>("AutoSprint", "MoveThreshold", 0.5f, new ConfigDescription("Minimum move input before sprint engages.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>())); harmony.Patch((MethodBase)AccessTools.Method(typeof(PlayerCharacterMasterController), "PollButtonInput", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(AutoSprintPatch), "PollButtonInputPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(GenericSkill), "OnExecute", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(AutoSprintPatch), "SkillExecutePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Run.onRunDestroyGlobal -= OnRunDestroy; Run.onRunDestroyGlobal += OnRunDestroy; } internal static void Unapply() { Run.onRunDestroyGlobal -= OnRunDestroy; suppressedUntil.Clear(); } private static void OnRunDestroy(Run run) { suppressedUntil.Clear(); } private static void PollButtonInputPostfix(PlayerCharacterMasterController __instance) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_00bb: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) InputBankTest bodyInputs = __instance.bodyInputs; CharacterBody body = __instance.body; if (!Object.op_Implicit((Object)(object)bodyInputs) || !Object.op_Implicit((Object)(object)body)) { return; } NetworkUser networkUser = __instance.networkUser; if ((Object)(object)networkUser == (Object)null || networkUser.localUser == null || networkUser.localUser.isUIFocused) { return; } if (holdToWalk.Value) { Player inputPlayer = networkUser.inputPlayer; if (inputPlayer != null && inputPlayer.GetButton(18)) { bodyInputs.sprint.down = false; return; } } float value = moveThreshold.Value; if (((Vector3)(ref bodyInputs.moveVector)).sqrMagnitude < value * value || (suppressedUntil.TryGetValue(body, out var value2) && Time.time < value2)) { return; } if ((body.bodyFlags & 0x20) == 0) { Vector3 aimDirection = bodyInputs.aimDirection; aimDirection.y = 0f; ((Vector3)(ref aimDirection)).Normalize(); Vector3 moveVector = bodyInputs.moveVector; moveVector.y = 0f; ((Vector3)(ref moveVector)).Normalize(); if (Vector3.Dot(aimDirection, moveVector) < PlayerCharacterMasterController.sprintMinAimMoveDot) { return; } } bodyInputs.sprint.down = true; } private static void SkillExecutePostfix(GenericSkill __instance) { SkillDef skillDef = __instance.skillDef; if (Object.op_Implicit((Object)(object)skillDef) && skillDef.cancelSprintingOnActivation) { CharacterBody characterBody = __instance.characterBody; if (Object.op_Implicit((Object)(object)characterBody) && characte