using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using ProMLGStats.Stats; using ProMLGStats.UI; using ProMLGStats.Utils; using TMPro; using UnboundLib; using UnboundLib.GameModes; using UnboundLib.Utils.UI; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ProMLGStats")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.5+55b73cdce38371846b742abe42a0fd48a4a387b1")] [assembly: AssemblyProduct("ProMLGStats")] [assembly: AssemblyTitle("ProMLGStats")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ProMLGStats { internal class Configs { public ConfigEntry EnableStatsHud { get; } public ConfigEntry StatsHudVisible { get; } public ConfigEntry StatsHudCollapsed { get; } public ConfigEntry StatsHudSimpleMode { get; } public ConfigEntry StatsHudUltraCompact { get; } public ConfigEntry StatsHudPeekMode { get; } public ConfigEntry StatsHudPeekKey { get; } public ConfigEntry HideStatsHudDuringPick { get; } public ConfigEntry HideStatsHudDuringBattle { get; } public ConfigEntry StatsHudToggleKey { get; } public ConfigEntry StatsHudOpacity { get; } public ConfigEntry StatsHudFontScale { get; } public ConfigEntry StatsHudColorR { get; } public ConfigEntry StatsHudColorG { get; } public ConfigEntry StatsHudColorB { get; } public ConfigEntry ShowPickDeltasOnHud { get; } public ConfigEntry EnableStatsTab { get; } public ConfigEntry StatsTabKey { get; } public ConfigEntry TabCompareKey { get; } public ConfigEntry EnableTabCompare { get; } public ConfigEntry TabPanelWidth { get; } public ConfigEntry TabPanelHeightFraction { get; } public ConfigEntry TabPanelOpacity { get; } public ConfigEntry TabPosX { get; } public ConfigEntry TabPosY { get; } public ConfigEntry ShowPing { get; } public ConfigEntry AutoCloseTabDuringPick { get; } public ConfigEntry ShowTabInfoStats { get; } public ConfigEntry StatsPanelScale { get; } public ConfigEntry StatsHudOffsetX { get; } public ConfigEntry StatsHudOffsetY { get; } public ConfigEntry StatsAccentR { get; } public ConfigEntry StatsAccentG { get; } public ConfigEntry StatsAccentB { get; } public Configs(ConfigFile config) { EnableStatsHud = config.Bind("Stats HUD", "Enabled", true, "Always-on stats panel in the bottom-left corner."); StatsHudVisible = config.Bind("Stats HUD", "Visible", true, "Whether the HUD is currently shown (toggle in-game with ToggleKey)."); StatsHudCollapsed = config.Bind("Stats HUD", "Collapsed", false, "Show the HUD as a minimal strip instead of the full panel."); StatsHudSimpleMode = config.Bind("Stats HUD", "SimpleMode", true, "Show a compact stat list instead of every stat."); StatsHudUltraCompact = config.Bind("Stats HUD", "UltraCompact", false, "Narrow HUD with fewer lines."); StatsHudPeekMode = config.Bind("Stats HUD", "PeekMode", false, "Only show the HUD while holding the peek key."); StatsHudPeekKey = config.Bind("Stats HUD", "PeekKey", (KeyCode)308, "Hold to show HUD when PeekMode is enabled."); HideStatsHudDuringPick = config.Bind("Stats HUD", "HideDuringPick", false, "Hide the always-on HUD during card pick."); HideStatsHudDuringBattle = config.Bind("Stats HUD", "HideDuringBattle", false, "Hide the always-on HUD during battle rounds."); StatsHudToggleKey = config.Bind("Stats HUD", "ToggleKey", (KeyCode)111, "Toggle the always-on HUD visibility. Set to None to disable the shortcut."); StatsHudOpacity = config.Bind("Stats HUD", "Opacity", 0f, "Background opacity for the HUD panel (0 = text only)."); StatsHudFontScale = config.Bind("Stats HUD", "FontScale", 1f, "Text scale multiplier (auto-scales with resolution too)."); StatsHudColorR = config.Bind("Stats HUD", "ColorR", 1f, "HUD text red channel."); StatsHudColorG = config.Bind("Stats HUD", "ColorG", 1f, "HUD text green channel."); StatsHudColorB = config.Bind("Stats HUD", "ColorB", 1f, "HUD text blue channel."); ShowPickDeltasOnHud = config.Bind("Stats HUD", "ShowPickDeltas", true, "During picks, show card deltas on the HUD for whoever is picking (hover a card to preview)."); EnableStatsTab = config.Bind("Stats Tab", "Enabled", true, "Full-player Tab overlay. Press the Tab key in-game."); StatsTabKey = config.Bind("Stats Tab", "OpenKey", (KeyCode)9, "Opens the Tab overlay. Rebind if another mod already uses Tab. None disables it."); TabCompareKey = config.Bind("Stats Tab", "CompareKey", (KeyCode)99, "Toggles compare mode while the Tab overlay is open."); EnableTabCompare = config.Bind("Stats Tab", "EnableCompare", true, "Compare mode inside the Tab overlay ([ and ] switch opponent)."); TabPanelWidth = config.Bind("Stats Tab", "PanelWidth", 480f, "Tab overlay width in pixels (before scale)."); TabPanelHeightFraction = config.Bind("Stats Tab", "PanelHeightFraction", 0.82f, "Tab overlay height as a fraction of screen height."); TabPanelOpacity = config.Bind("Stats Tab", "PanelOpacity", 0.94f, "Tab overlay background opacity."); TabPosX = config.Bind("Stats Tab", "PosX", -1f, "Tab overlay X in canvas pixels. Negative = default centered."); TabPosY = config.Bind("Stats Tab", "PosY", -1f, "Tab overlay Y in canvas pixels. Negative = default centered."); ShowPing = config.Bind("Stats Tab", "ShowPing", true, "Show Photon ping next to player names (online games)."); AutoCloseTabDuringPick = config.Bind("Stats Tab", "AutoCloseDuringPick", true, "Close the Tab overlay automatically when a card pick starts."); ShowTabInfoStats = config.Bind("Stats Tab", "ShowTabInfoStats", true, "If willuwontu's TabInfo is installed, also show stats other mods registered with it."); StatsPanelScale = config.Bind("Stats Layout", "PanelScale", 1f, "Global UI scale multiplier."); StatsHudOffsetX = config.Bind("Stats Layout", "HudOffsetX", 14f, "HUD distance from left edge."); StatsHudOffsetY = config.Bind("Stats Layout", "HudOffsetY", 14f, "HUD distance from bottom edge."); StatsAccentR = config.Bind("Stats Layout", "AccentR", 0.35f, "Accent color red."); StatsAccentG = config.Bind("Stats Layout", "AccentG", 0.82f, "Accent color green."); StatsAccentB = config.Bind("Stats Layout", "AccentB", 0.72f, "Accent color blue."); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.ljindustries.rounds.promlgstats", "Pro MLG Stats", "1.0.5")] [BepInProcess("Rounds.exe")] public class Plugin : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__9_0; internal void b__9_0() { } } public const string ModId = "com.ljindustries.rounds.promlgstats"; public const string ModName = "Pro MLG Stats"; public const string Version = "1.0.5"; internal static Configs Configs; public static Plugin Instance { get; private set; } private void Awake() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown Instance = this; Configs = new Configs(((BaseUnityPlugin)this).Config); try { Harmony val = new Harmony("com.ljindustries.rounds.promlgstats"); Type[] types; try { types = typeof(Plugin).Assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { types = ex.Types; ManualLogSource logger = ((BaseUnityPlugin)this).Logger; Exception?[] loaderExceptions = ex.LoaderExceptions; logger.LogWarning((object)$"GetTypes partial load: {((loaderExceptions != null) ? loaderExceptions.Length : 0)} loader error(s)"); } Type[] array = types; foreach (Type type in array) { if (!(type == null)) { try { val.CreateClassProcessor(type).Patch(); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Harmony skip " + type.FullName + ": " + ex2.GetType().Name + ": " + ex2.Message)); } } } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Harmony patching failed: {arg}"); } } private void Start() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown Unbound.RegisterClientSideMod("com.ljindustries.rounds.promlgstats"); object obj = <>c.<>9__9_0; if (obj == null) { UnityAction val = delegate { }; <>c.<>9__9_0 = val; obj = (object)val; } Unbound.RegisterMenu("Pro MLG Stats", (UnityAction)obj, (Action)MenuBuilder.Build, (GameObject)null, true); ExtensionMethods.GetOrAddComponent(((Component)this).gameObject, false); StatsController.RegisterHooks(); } internal void Log(string message) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[Pro MLG Stats] " + message)); } internal void LogWarn(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[Pro MLG Stats] " + message)); } } [HarmonyPatch(typeof(CardChoice), "StartPick")] internal static class StartPickTrackerPatch { private static void Postfix(int pickerIDToSet) { PickPhase.NoteActingPicker(pickerIDToSet); } } } namespace ProMLGStats.Utils { internal static class PickPhase { private static readonly FieldInfo PickerTypeField = AccessTools.Field(typeof(CardChoice), "pickerType"); private static readonly FieldInfo SpawnedCardsField = AccessTools.Field(typeof(CardChoice), "spawnedCards"); private static int _actingPickerId = -1; internal static void NoteActingPicker(int pickerId) { _actingPickerId = pickerId; } internal static void ClearActingPicker() { _actingPickerId = -1; } internal static Player GetCurrentPicker() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) CardChoice instance = CardChoice.instance; if ((Object)(object)instance == (Object)null) { return null; } if (instance.IsPicking && _actingPickerId >= 0) { Player val = FindPlayer(_actingPickerId); if ((Object)(object)val != (Object)null) { return val; } } if (PickerTypeField != null && (int)(PickerType)PickerTypeField.GetValue(instance) == 0) { Player[] array = (((Object)(object)PlayerManager.instance != (Object)null) ? PlayerManager.instance.GetPlayersInTeam(instance.pickrID) : null); if (array != null && array.Length != 0) { return DesignateFromTeam(array); } } return FindPlayer(instance.pickrID); } internal static Player FindPlayer(int playerId) { List list = PlayerManager.instance?.players; if (list == null) { return null; } foreach (Player item in list) { if ((Object)(object)item != (Object)null && item.playerID == playerId) { return item; } } return null; } internal static List GetSpawnedCards() { CardChoice instance = CardChoice.instance; if ((Object)(object)instance == (Object)null) { return null; } return SpawnedCardsField?.GetValue(instance) as List; } internal static bool PickerHoldsCardNamed(string cardName) { if (string.IsNullOrEmpty(cardName)) { return false; } Player currentPicker = GetCurrentPicker(); if ((Object)(object)currentPicker == (Object)null || !PlayerStatsSnapshot.IsLocallyControlled(currentPicker)) { return false; } List list = currentPicker.data?.currentCards; if (list == null) { return false; } foreach (CardInfo item in list) { if (!((Object)(object)item == (Object)null) && string.Equals(item.cardName, cardName, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static Player DesignateFromTeam(Player[] team) { if (team == null || team.Length == 0) { return null; } Player val = null; Player val2 = null; foreach (Player val3 in team) { if (!((Object)(object)val3 == (Object)null)) { if ((Object)(object)val2 == (Object)null || val3.playerID < val2.playerID) { val2 = val3; } if ((Object)(object)val == (Object)null && PlayerStatsSnapshot.IsLocallyControlled(val3)) { val = val3; } } } return val ?? val2; } } internal static class RoundsWithBotsBridge { private const string ExtensionTypeName = "RoundsWithBots.Extensions.CharacterDataExtension"; private const string AdditionalDataTypeName = "RoundsWithBots.Extensions.CharacterDataAdditionalData"; private static bool _probed; private static bool _logged; private static MethodInfo _getAdditionalData; private static PropertyInfo _isBot; private static Type _playerAiPhilip; internal static bool IsAvailable { get { Probe(); if (_getAdditionalData != null) { return _isBot != null; } return false; } } internal static bool IsBot(Player player) { if ((Object)(object)player?.data == (Object)null) { return false; } Probe(); if (_getAdditionalData != null && _isBot != null) { try { object obj = _getAdditionalData.Invoke(null, new object[1] { player.data }); if (obj != null) { object value = _isBot.GetValue(obj); if (value is bool && (bool)value) { return true; } } } catch { } } return HasEnabledAi(player); } internal static string DisplayName(Player player, string fallback) { if ((Object)(object)player == (Object)null || !IsBot(player)) { if (!string.IsNullOrEmpty(fallback)) { return fallback; } return "?"; } return $"[BOT] P{player.playerID + 1}"; } private static bool HasEnabledAi(Player player) { if (_playerAiPhilip == null || (Object)(object)player == (Object)null) { return false; } try { Component component = ((Component)player).GetComponent(_playerAiPhilip); Behaviour val = (Behaviour)(((object)((component is Behaviour) ? component : null)) ?? ((object)/*isinst with value type is only supported in some contexts*/)); return (Object)(object)val != (Object)null && val.enabled; } catch { return false; } } private static void Probe() { if (_probed) { return; } _probed = true; try { Type type = AccessTools.TypeByName("RoundsWithBots.Extensions.CharacterDataExtension"); if (type != null) { _getAdditionalData = AccessTools.Method(type, "GetAdditionalData", new Type[1] { typeof(CharacterData) }, (Type[])null); Type type2 = AccessTools.TypeByName("RoundsWithBots.Extensions.CharacterDataAdditionalData") ?? _getAdditionalData?.ReturnType; _isBot = ((type2 == null) ? null : AccessTools.Property(type2, "IsBot")); } } catch { _getAdditionalData = null; _isBot = null; } _playerAiPhilip = AccessTools.TypeByName("PlayerAIPhilip"); if (!_logged && _getAdditionalData != null && _isBot != null) { _logged = true; Plugin.Instance?.Log("RoundsWithBots detected - bots are listed separately and are not treated as the local player."); } } } internal static class TabInfoBridge { private const string ManagerTypeName = "TabInfo.Utils.TabInfoManager"; private static bool _probed; private static MethodInfo _getVisibleStats; private static object _basicStats; private static FieldInfo _rowCategory; private static FieldInfo _rowStat; private static FieldInfo _rowValue; private static FieldInfo _categoryName; private static FieldInfo _statName; internal static bool IsAvailable { get { Probe(); return _getVisibleStats != null; } } internal static IEnumerable<(string category, string label, string value)> GetExtensionStats(Player player) { if ((Object)(object)player == (Object)null || (Plugin.Configs != null && !Plugin.Configs.ShowTabInfoStats.Value)) { yield break; } Probe(); if (_getVisibleStats == null) { yield break; } IEnumerable enumerable; try { enumerable = _getVisibleStats.Invoke(null, new object[1] { player }) as IEnumerable; } catch (Exception ex) { Plugin.Instance?.LogWarn("TabInfo GetVisibleStats failed: " + ex.Message); yield break; } if (enumerable == null) { yield break; } foreach (object item in enumerable) { if (item == null) { continue; } string text; string text2; string text3; try { object obj = _rowCategory?.GetValue(item); if (obj == null || (_basicStats != null && obj == _basicStats)) { continue; } object obj2 = _rowStat?.GetValue(item); text = _categoryName?.GetValue(obj) as string; text2 = ((obj2 != null) ? (_statName?.GetValue(obj2) as string) : null); text3 = _rowValue?.GetValue(item) as string; goto IL_0191; } catch { } continue; IL_0191: if (!string.IsNullOrEmpty(text2)) { yield return (category: text ?? string.Empty, label: text2, value: text3 ?? string.Empty); } } } private static void Probe() { if (_probed) { return; } _probed = true; Type type = AccessTools.TypeByName("TabInfo.Utils.TabInfoManager"); if (type == null) { return; } _getVisibleStats = AccessTools.Method(type, "GetVisibleStats", new Type[1] { typeof(Player) }, (Type[])null); if (_getVisibleStats == null) { return; } try { _basicStats = AccessTools.Field(type, "basicStats")?.GetValue(null) ?? AccessTools.Property(type, "basicStats")?.GetValue(null); } catch { _basicStats = null; } Type type2 = (_getVisibleStats.ReturnType.IsGenericType ? _getVisibleStats.ReturnType.GetGenericArguments()[0] : null); if (type2 == null) { _getVisibleStats = null; return; } _rowCategory = AccessTools.Field(type2, "category"); _rowStat = AccessTools.Field(type2, "stat"); _rowValue = AccessTools.Field(type2, "value"); if (_rowCategory == null || _rowStat == null || _rowValue == null) { _getVisibleStats = null; return; } _categoryName = AccessTools.Field(_rowCategory.FieldType, "name"); _statName = AccessTools.Field(_rowStat.FieldType, "name"); Plugin.Instance?.Log("TabInfo detected — extension stats will be shown in the Tab panel."); } } } namespace ProMLGStats.UI { internal static class MenuBuilder { public static void Build(GameObject menu) { //IL_048f: Unknown result type (might be due to invalid IL or missing references) //IL_04a4: Unknown result type (might be due to invalid IL or missing references) Configs cfg = Plugin.Configs; TextMeshProUGUI val = default(TextMeshProUGUI); MenuHandler.CreateText("Pro MLG Stats", menu, ref val, 60, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateText("Client-side only. Other players do not need this mod.", menu, ref val, 26, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateText("Stats HUD", menu, ref val, 40, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateToggle(cfg.EnableStatsHud.Value, "Enable HUD", menu, (UnityAction)delegate(bool v) { cfg.EnableStatsHud.Value = v; StatsController.Instance?.RebuildHud(); }, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateToggle(cfg.StatsHudSimpleMode.Value, "Compact stat list", menu, (UnityAction)delegate(bool v) { cfg.StatsHudSimpleMode.Value = v; StatsController.Instance?.RebuildHud(); }, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateToggle(cfg.HideStatsHudDuringPick.Value, "Hide HUD during pick", menu, (UnityAction)delegate(bool v) { cfg.HideStatsHudDuringPick.Value = v; }, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateToggle(cfg.HideStatsHudDuringBattle.Value, "Hide HUD during battle", menu, (UnityAction)delegate(bool v) { cfg.HideStatsHudDuringBattle.Value = v; }, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateToggle(cfg.ShowPickDeltasOnHud.Value, "Show card deltas while picking", menu, (UnityAction)delegate(bool v) { cfg.ShowPickDeltasOnHud.Value = v; }, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); Slider val2 = default(Slider); MenuHandler.CreateSlider("HUD opacity", menu, 30, 0f, 1f, cfg.StatsHudOpacity.Value, (UnityAction)delegate(float v) { cfg.StatsHudOpacity.Value = v; StatsController.Instance?.RebuildHud(); }, ref val2, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateSlider("HUD text scale", menu, 30, 0.6f, 2f, cfg.StatsHudFontScale.Value, (UnityAction)delegate(float v) { cfg.StatsHudFontScale.Value = v; StatsController.Instance?.RebuildHud(); }, ref val2, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateText("Tab overlay", menu, ref val, 40, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateToggle(cfg.EnableStatsTab.Value, "Enable Tab overlay", menu, (UnityAction)delegate(bool v) { cfg.EnableStatsTab.Value = v; StatsController.Instance?.RebuildTab(); }, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateToggle(cfg.EnableTabCompare.Value, "Enable compare mode", menu, (UnityAction)delegate(bool v) { cfg.EnableTabCompare.Value = v; }, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateToggle(cfg.AutoCloseTabDuringPick.Value, "Close automatically on pick", menu, (UnityAction)delegate(bool v) { cfg.AutoCloseTabDuringPick.Value = v; }, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateToggle(cfg.ShowPing.Value, "Show ping", menu, (UnityAction)delegate(bool v) { cfg.ShowPing.Value = v; }, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); if (TabInfoBridge.IsAvailable) { MenuHandler.CreateToggle(cfg.ShowTabInfoStats.Value, "Include TabInfo stats", menu, (UnityAction)delegate(bool v) { cfg.ShowTabInfoStats.Value = v; StatsController.Instance?.RebuildTab(); }, 32, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); } MenuHandler.CreateSlider("Tab panel width", menu, 30, 280f, 640f, cfg.TabPanelWidth.Value, (UnityAction)delegate(float v) { cfg.TabPanelWidth.Value = v; StatsController.Instance?.RebuildTab(); }, ref val2, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateSlider("Global UI scale", menu, 30, 0.6f, 1.8f, cfg.StatsPanelScale.Value, (UnityAction)delegate(float v) { cfg.StatsPanelScale.Value = v; StatsController.Instance?.RebuildHud(); StatsController.Instance?.RebuildTab(); }, ref val2, false, (Color?)null, (Direction)0, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); MenuHandler.CreateText("Keys are rebindable in BepInEx/config/com.ljindustries.rounds.promlgstats.cfg " + $"(currently {cfg.StatsTabKey.Value} for the panel, {cfg.StatsHudToggleKey.Value} for the HUD).", menu, ref val, 24, true, (Color?)null, (TMP_FontAsset)null, (Material)null, (TextAlignmentOptions?)null); } } internal sealed class OverlayDrag : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler { internal RectTransform Target; internal bool ResizeWidth; private Vector2 _startPointer; private Vector2 _startPos; private Vector2 _startSize; public void OnBeginDrag(PointerEventData eventData) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Target == (Object)null)) { _startPos = Target.anchoredPosition; _startSize = Target.sizeDelta; ScreenToParent(eventData, out _startPointer); } } public void OnDrag(PointerEventData eventData) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Target == (Object)null)) { ScreenToParent(eventData, out var local); Vector2 val = local - _startPointer; Vector2 overlaySize = StatsUiHelper.OverlaySize; if (ResizeWidth) { float num = Mathf.Min(640f, overlaySize.x * 0.55f); float num2 = Mathf.Clamp(_startSize.x - val.x, 280f, num); float num3 = _startSize.x - num2; Target.sizeDelta = new Vector2(num2, _startSize.y); Target.anchoredPosition = Clamp(_startPos + new Vector2(num3, 0f), Target.sizeDelta, overlaySize); } else { Target.anchoredPosition = Clamp(_startPos + val, _startSize, overlaySize); } } } public void OnEndDrag(PointerEventData eventData) { //IL_0026: 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_0064: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Target == (Object)null) && Plugin.Configs != null) { Plugin.Configs.TabPosX.Value = Target.anchoredPosition.x; Plugin.Configs.TabPosY.Value = Target.anchoredPosition.y; Plugin.Configs.TabPanelWidth.Value = Target.sizeDelta.x; } } private void ScreenToParent(PointerEventData eventData, out Vector2 local) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) Transform parent = ((Transform)Target).parent; RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)(object)((parent is RectTransform) ? parent : null), eventData.position, eventData.pressEventCamera, ref local); } private static Vector2 Clamp(Vector2 pos, Vector2 size, Vector2 canvas) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) float num = 8f; pos.x = Mathf.Clamp(pos.x, num, Mathf.Max(num, canvas.x - size.x - num)); pos.y = Mathf.Clamp(pos.y, num, Mathf.Max(num, canvas.y - size.y - num)); return pos; } } internal sealed class StatsController : MonoBehaviour { private const string BlindDraftCardName = "Blind Draft"; private StatsHudPanel _hud; private StatsTabOverlay _tab; private CardInfo _hoveredCard; private CardInfo _hoveredVisual; private PlayerStatsSnapshot _previewDelta; private readonly Dictionary _pickBaselines = new Dictionary(); private float _refreshTimer; private static float _readyCacheUntil; private static bool _readyCache; private static readonly FieldInfo SpawnedCardsField = AccessTools.Field(typeof(CardChoice), "spawnedCards"); private static readonly FieldInfo IsHoveredField = AccessTools.Field(typeof(CardVisuals), "isHovered"); private static readonly FieldInfo IsSelectedField = AccessTools.Field(typeof(CardVisuals), "isSelected"); private static readonly FieldInfo CurrentlySelectedCardField = AccessTools.Field(typeof(CardChoice), "currentlySelectedCard"); private static readonly PropertyInfo CurrentlySelectedCardProp = AccessTools.Property(typeof(CardChoice), "currentlySelectedCard"); internal static StatsController Instance { get; private set; } internal static bool InPickPhase { get; private set; } internal static bool InBattlePhase { get; private set; } internal static bool MatchSessionActive { get; private set; } internal static int CurrentRound { get; private set; } internal static int CurrentPoint { get; private set; } internal static string HoveredCardName => Instance?._hoveredCard?.cardName; internal static bool IsCardPickActive { get { if (InPickPhase && (Object)(object)CardChoice.instance != (Object)null) { return CardChoice.instance.IsPicking; } return false; } } private void Awake() { Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); _hud = ((Component)this).gameObject.AddComponent(); _tab = ((Component)this).gameObject.AddComponent(); } internal static void RegisterHooks() { GameModeManager.AddHook("GameStart", (Func)OnGameStart); GameModeManager.AddHook("GameEnd", (Func)OnGameEnd); GameModeManager.AddHook("PickStart", (Func)OnPickStart); GameModeManager.AddHook("PickEnd", (Func)OnPickEnd); GameModeManager.AddHook("PlayerPickStart", (Func)OnPlayerPickStart); GameModeManager.AddHook("RoundStart", (Func)OnRoundStart); GameModeManager.AddHook("PointStart", (Func)OnPointStart); GameModeManager.AddHook("BattleStart", (Func)OnBattleStart); } private static IEnumerator OnGameStart(IGameModeHandler gm) { MatchSessionActive = true; CurrentRound = 0; CurrentPoint = 0; InPickPhase = false; InBattlePhase = false; Instance?._tab?.SetOpen(open: false); Instance?.ClearPickBaselines(); yield break; } private static IEnumerator OnGameEnd(IGameModeHandler gm) { MatchSessionActive = false; InPickPhase = false; InBattlePhase = false; Instance?._tab?.SetOpen(open: false); Instance?.ClearPickBaselines(); yield break; } private static IEnumerator OnPickStart(IGameModeHandler gm) { InPickPhase = true; InBattlePhase = false; Instance?.CaptureAllPickBaselines(); yield break; } private static IEnumerator OnPickEnd(IGameModeHandler gm) { InPickPhase = false; Instance?.ClearPreview(); yield break; } private static IEnumerator OnPlayerPickStart(IGameModeHandler gm) { Instance?.CapturePickBaseline(); Instance?.ClearPreview(); yield return null; Instance?.CapturePickBaseline(); } private static IEnumerator OnRoundStart(IGameModeHandler gm) { CurrentRound++; CurrentPoint = 0; InPickPhase = false; yield break; } private static IEnumerator OnPointStart(IGameModeHandler gm) { CurrentPoint++; yield break; } private static IEnumerator OnBattleStart(IGameModeHandler gm) { InBattlePhase = true; InPickPhase = false; yield break; } private void CapturePickBaseline() { Player val = PickPhase.GetCurrentPicker() ?? PlayerStatsSnapshot.LocalPlayer(); if (!((Object)(object)val == (Object)null) && PlayerStatsSnapshot.TryFrom(val, out var snapshot)) { _pickBaselines[val.playerID] = snapshot; } } private void CaptureAllPickBaselines() { foreach (Player item in PlayerStatsSnapshot.ActivePlayers()) { if (PlayerStatsSnapshot.TryFrom(item, out var snapshot)) { _pickBaselines[item.playerID] = snapshot; } } } private void CaptureMissingPickBaselines() { foreach (Player item in PlayerStatsSnapshot.ActivePlayers()) { if (!_pickBaselines.ContainsKey(item.playerID) && PlayerStatsSnapshot.TryFrom(item, out var snapshot)) { _pickBaselines[item.playerID] = snapshot; } } } private void ClearPickBaselines() { _pickBaselines.Clear(); } private PlayerStatsSnapshot GetPickBaselineFor(Player player) { if ((Object)(object)player == (Object)null) { return null; } if (!_pickBaselines.TryGetValue(player.playerID, out var value)) { return null; } return value; } internal static Player GetHudPlayer() { if (InPickPhase && (Object)(object)CardChoice.instance != (Object)null && CardChoice.instance.IsPicking) { return PickPhase.GetCurrentPicker() ?? PlayerStatsSnapshot.LocalPlayer(); } return PlayerStatsSnapshot.LocalPlayer(); } internal static bool IsWatchingOtherPicker() { if (!InPickPhase || (Object)(object)CardChoice.instance == (Object)null || !CardChoice.instance.IsPicking) { return false; } Player currentPicker = PickPhase.GetCurrentPicker(); Player val = PlayerStatsSnapshot.LocalPlayer(); if ((Object)(object)currentPicker == (Object)null || (Object)(object)val == (Object)null) { return false; } return currentPicker.playerID != val.playerID; } internal void NotifyHoveredCard(Player picker, CardInfo cardInfo, CardInfo pickVisual = null) { if ((Object)(object)picker == (Object)null || (Object)(object)cardInfo == (Object)null) { ClearPreview(); } else if (!((Object)(object)_hoveredCard == (Object)(object)cardInfo) || !((Object)(object)_hoveredVisual == (Object)(object)pickVisual) || _previewDelta == null) { _hoveredCard = cardInfo; _hoveredVisual = pickVisual; if (CardStatPreview.TryPreview(picker, cardInfo, out var delta, pickVisual)) { _previewDelta = delta; } else { _previewDelta = null; } _hud?.SetPreviewDelta(_previewDelta); _refreshTimer = 0f; } } internal void ClearPreview() { bool num = (Object)(object)_hoveredCard != (Object)null || _previewDelta != null; _hoveredCard = null; _hoveredVisual = null; _previewDelta = null; _hud?.SetPreviewDelta(null); if (num) { _refreshTimer = 0f; } } internal static bool InActiveMatch() { if (!HasReadyPlayers()) { return false; } if (MatchSessionActive) { return true; } return IsSandboxMode(); } private static bool HasReadyPlayers() { if (Time.unscaledTime < _readyCacheUntil) { return _readyCache; } List list = PlayerManager.instance?.players; bool flag = false; if (list != null && list.Count > 0) { foreach (Player item in list) { if ((Object)(object)item?.data?.weaponHandler?.gun != (Object)null && (Object)(object)item.data.block != (Object)null) { flag = true; break; } } } _readyCache = flag; _readyCacheUntil = Time.unscaledTime + 0.25f; return flag; } private static bool IsSandboxMode() { try { if (GameModeManager.CurrentHandler is SandboxHandler) { return true; } string currentHandlerID = GameModeManager.CurrentHandlerID; if (!string.IsNullOrEmpty(currentHandlerID) && currentHandlerID.IndexOf("Sandbox", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } catch { } return false; } internal void RebuildHud() { _hud?.Rebuild(); } internal void RebuildTab() { _tab?.RebuildLayout(); } private void Update() { HandleTabToggle(); HandleHudToggle(); _tab?.HandleShortcuts(); PollHoveredCard(); PingTracker.Tick(); _refreshTimer -= Time.unscaledDeltaTime; if (!(_refreshTimer > 0f)) { _refreshTimer = (((Object)(object)_tab != (Object)null && _tab.IsOpen) ? 0.25f : 0.2f); if (InPickPhase) { CaptureMissingPickBaselines(); } Player hudPlayer = GetHudPlayer(); _hud?.Refresh(GetPickBaselineFor(hudPlayer), hudPlayer, IsWatchingOtherPicker()); if ((Object)(object)_tab != (Object)null && _tab.IsOpen) { _tab.Refresh(); } } } private static void HandleTabToggle() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_0056: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Instance?._tab == (Object)null) { return; } if (!InActiveMatch()) { if (Instance._tab.IsOpen) { Instance._tab.SetOpen(open: false); } return; } KeyCode value = Plugin.Configs.StatsTabKey.Value; if ((int)value != 0 && Input.GetKeyDown(value)) { Instance._tab.Toggle(); } if (Input.GetKeyDown((KeyCode)27) && Instance._tab.IsOpen) { Instance._tab.SetOpen(open: false); } } internal static void HandleHudToggle() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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 (!((Object)(object)Instance == (Object)null)) { KeyCode value = Plugin.Configs.StatsHudToggleKey.Value; if ((int)value != 0 && Input.GetKeyDown(value)) { Plugin.Configs.StatsHudVisible.Value = !Plugin.Configs.StatsHudVisible.Value; } } } private void PollHoveredCard() { if (!InPickPhase) { if (_previewDelta != null) { ClearPreview(); } return; } if ((Object)(object)CardChoice.instance == (Object)null || !CardChoice.instance.IsPicking) { if (_previewDelta != null) { ClearPreview(); } return; } Player currentPicker = PickPhase.GetCurrentPicker(); CardInfo source; CardInfo visual; if ((Object)(object)currentPicker == (Object)null) { if (_previewDelta != null) { ClearPreview(); } } else if (PickPhase.PickerHoldsCardNamed("Blind Draft")) { if (_previewDelta != null || (Object)(object)_hoveredCard != (Object)null) { ClearPreview(); } } else if (!TryGetHighlightedCard(out source, out visual)) { if (_previewDelta != null || (Object)(object)_hoveredCard != (Object)null) { ClearPreview(); } } else { NotifyHoveredCard(currentPicker, source, visual); } } private static bool TryGetHighlightedCard(out CardInfo source, out CardInfo visual) { //IL_011d: Unknown result type (might be due to invalid IL or missing references) source = null; visual = null; CardChoice instance = CardChoice.instance; if ((Object)(object)instance == (Object)null) { return false; } object raw = CurrentlySelectedCardField?.GetValue(instance) ?? CurrentlySelectedCardProp?.GetValue(instance); if (TryResolveCard(instance, raw, out source, out visual)) { return true; } if (!(SpawnedCardsField?.GetValue(instance) is IList list)) { return false; } CardInfo val = null; CardInfo val2 = null; float num = 1.04f; foreach (object item in list) { GameObject val3 = (GameObject)((item is GameObject) ? item : null); if (val3 == null || (Object)(object)val3 == (Object)null) { continue; } CardInfo component = val3.GetComponent(); if (!((Object)(object)component == (Object)null)) { CardVisuals componentInChildren = val3.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && (ReadFlag(componentInChildren, IsHoveredField) || ReadFlag(componentInChildren, IsSelectedField))) { visual = component; source = instance.GetSourceCard(component) ?? component.sourceCard ?? component; return (Object)(object)source != (Object)null; } float x = val3.transform.localScale.x; if (!(x < num)) { num = x; val2 = component; val = instance.GetSourceCard(component) ?? component.sourceCard ?? component; } } } if ((Object)(object)val == (Object)null) { return false; } source = val; visual = val2; return true; } private static bool TryResolveCard(CardChoice choice, object raw, out CardInfo source, out CardInfo visual) { source = null; visual = null; if (raw == null) { return false; } GameObject val = (GameObject)((raw is GameObject) ? raw : null); CardInfo val2 = (CardInfo)((raw is CardInfo) ? raw : null); if (val2 != null) { visual = val2; if (val == null) { val = ((Component)val2).gameObject; } } if ((Object)(object)visual == (Object)null && (Object)(object)val != (Object)null) { visual = val.GetComponent() ?? val.GetComponentInChildren(); } if ((Object)(object)visual == (Object)null) { return false; } source = choice.GetSourceCard(visual) ?? visual.sourceCard ?? visual; return (Object)(object)source != (Object)null; } private static bool ReadFlag(CardVisuals visuals, FieldInfo field) { if (field == null || (Object)(object)visuals == (Object)null) { return false; } try { object value = field.GetValue(visuals); return value is bool && (bool)value; } catch { return false; } } } internal sealed class StatsHudPanel : MonoBehaviour { private const float HorizontalPadding = 12f; private const float VerticalPadding = 12f; private GameObject _root; private TextMeshProUGUI _body; private PlayerStatsSnapshot _previewDelta; internal void Rebuild() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); _root = null; _body = null; } } internal void EnsureBuilt() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_root != (Object)null) && StatsUiHelper.OverlayReady) { float uiScale = StatsUiHelper.UiScale; float num = GetPanelWidth() * uiScale; Vector2 anchoredPos = default(Vector2); ((Vector2)(ref anchoredPos))..ctor(Plugin.Configs.StatsHudOffsetX.Value * uiScale, Plugin.Configs.StatsHudOffsetY.Value * uiScale); _root = StatsUiHelper.CreateModernPanel(StatsUiHelper.OverlayRoot, "MM_StatsHud", new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(0f, 0f), anchoredPos, new Vector2(num, 160f * uiScale), 0f); Image component = _root.GetComponent(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = new Color(0f, 0f, 0f, 0f); ((Graphic)component).raycastTarget = false; } _body = StatsUiHelper.CreateText(_root.transform, "Body", "", StatsUiHelper.BaseFont, (TextAlignmentOptions)257); RectTransform rectTransform = ((TMP_Text)_body).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.offsetMin = new Vector2(12f, 12f); rectTransform.offsetMax = new Vector2(-12f, -12f); ((TMP_Text)_body).enableWordWrapping = true; ((TMP_Text)_body).overflowMode = (TextOverflowModes)0; ((Graphic)_body).raycastTarget = false; } } internal void SetPreviewDelta(PlayerStatsSnapshot delta) { _previewDelta = delta; } internal void Refresh(PlayerStatsSnapshot pickBaseline, Player hudPlayer, bool watchingPicker) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) bool value = Plugin.Configs.StatsHudVisible.Value; bool flag = StatsController.InActiveMatch(); if ((Object)(object)hudPlayer == (Object)null || !PlayerStatsSnapshot.TryFrom(hudPlayer, out var snapshot)) { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } return; } if (!value || !flag) { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } return; } EnsureBuilt(); if (!((Object)(object)_root == (Object)null) && !((Object)(object)_body == (Object)null)) { _root.SetActive(true); ((TMP_Text)_body).lineSpacing = 2f; ((TMP_Text)_body).fontSize = StatsUiHelper.BaseFont; ((Graphic)_body).color = Color.white; ((TMP_Text)_body).outlineWidth = 0.35f; ((TMP_Text)_body).outlineColor = Color32.op_Implicit(new Color(0f, 0f, 0f, 0.95f)); ((TMP_Text)_body).fontMaterial.EnableKeyword("OUTLINE_ON"); bool isCardPickActive = StatsController.IsCardPickActive; string text = (watchingPicker ? " · picking" : ""); if (isCardPickActive && !string.IsNullOrEmpty(StatsController.HoveredCardName)) { text = text + " · " + StatsController.HoveredCardName; } string text2 = StatsViewBuilder.BuildHud(snapshot, simple: true, isCardPickActive ? null : pickBaseline, isCardPickActive ? _previewDelta : null, null, string.IsNullOrEmpty(text) ? null : text, StatsController.InBattlePhase, isCardPickActive); if (((TMP_Text)_body).text != text2) { ((TMP_Text)_body).text = text2; LayoutToContent(); } } } private void LayoutToContent() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_00d7: 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_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0120: 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_0164: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) float uiScale = StatsUiHelper.UiScale; Vector2 overlaySize = StatsUiHelper.OverlaySize; float num = GetPanelWidth() * uiScale; float num2 = 0.72f; bool visible = false; ((TMP_Text)_body).ForceMeshUpdate(); float num3 = Mathf.Max(((TMP_Text)_body).preferredHeight, 36f) + 24f + 6f; num3 = Mathf.Min(num3, Mathf.Max(64f, overlaySize.y - 24f)); num = Mathf.Min(num, Mathf.Max(120f, overlaySize.x - 24f)); float num4 = Mathf.Clamp(Plugin.Configs.StatsHudOffsetX.Value * uiScale, 8f, Mathf.Max(8f, overlaySize.x - num - 8f)); float num5 = Mathf.Clamp(Plugin.Configs.StatsHudOffsetY.Value * uiScale, 8f, Mathf.Max(8f, overlaySize.y - num3 - 8f)); StatsUiHelper.ApplyRect(_root, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(num4, num5), new Vector2(num, num3)); Image component = _root.GetComponent(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = new Color(0.02f, 0.03f, 0.05f, num2); ((Graphic)component).raycastTarget = false; } StatsUiHelper.SetAccentVisible(_root, visible); Transform val = _root.transform.Find("AccentTop") ?? _root.transform.Find("Accent"); Transform val2 = _root.transform.Find("AccentBottom"); if ((Object)(object)val != (Object)null) { ((Graphic)((Component)val).GetComponent()).color = StatsUiHelper.AccentColor; } if ((Object)(object)val2 != (Object)null) { ((Graphic)((Component)val2).GetComponent()).color = StatsUiHelper.AccentColor; } } private static float GetPanelWidth() { return 260f; } } internal sealed class StatsTabOverlay : MonoBehaviour { private GameObject _root; private TextMeshProUGUI _title; private TextMeshProUGUI _hint; private RectTransform _content; private readonly List _playerBlocks = new List(); private bool _compareMode; private int _compareTargetPlayerId = -1; private PlayerStatsSnapshot _pinnedLocal; private int _pinnedLocalPlayerId = -1; internal bool IsOpen { get; private set; } internal void EnsureBuilt() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_0114: 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_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Expected O, but got Unknown //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Expected O, but got Unknown //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Expected O, but got Unknown //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_043a: Unknown result type (might be due to invalid IL or missing references) //IL_0440: Expected O, but got Unknown //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_0488: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04cc: Unknown result type (might be due to invalid IL or missing references) //IL_04ee: Unknown result type (might be due to invalid IL or missing references) //IL_04f8: Expected O, but got Unknown if (!((Object)(object)_root != (Object)null) && StatsUiHelper.OverlayReady) { ApplyPanelLayout(); _title = StatsUiHelper.CreateText(_root.transform, "Title", "Player Stats", StatsUiHelper.TitleFont, (TextAlignmentOptions)257, StatsUiHelper.TitleColor); RectTransform rectTransform = ((TMP_Text)_title).rectTransform; rectTransform.anchorMin = new Vector2(0f, 1f); rectTransform.anchorMax = new Vector2(1f, 1f); rectTransform.pivot = new Vector2(0f, 1f); rectTransform.anchoredPosition = new Vector2(18f, -12f); rectTransform.sizeDelta = new Vector2(-18f, 26f); _hint = StatsUiHelper.CreateText(_root.transform, "Hint", "", StatsUiHelper.BaseFont * 0.78f, (TextAlignmentOptions)257, StatsUiHelper.HintColor); RectTransform rectTransform2 = ((TMP_Text)_hint).rectTransform; rectTransform2.anchorMin = new Vector2(0f, 1f); rectTransform2.anchorMax = new Vector2(1f, 1f); rectTransform2.pivot = new Vector2(0f, 1f); rectTransform2.anchoredPosition = new Vector2(18f, -36f); rectTransform2.sizeDelta = new Vector2(-18f, 16f); RectTransform component = ((Component)StatsUiHelper.CreateGhostButton(_root.transform, "Close", (UnityAction)delegate { SetOpen(open: false); }, new Vector2(72f, 24f))).GetComponent(); component.anchorMin = new Vector2(1f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(1f, 1f); component.anchoredPosition = new Vector2(-14f, -12f); RectTransform component2 = ((Component)StatsUiHelper.CreateGhostButton(_root.transform, "Compare", new UnityAction(ToggleCompareMode), new Vector2(78f, 24f))).GetComponent(); component2.anchorMin = new Vector2(1f, 1f); component2.anchorMax = new Vector2(1f, 1f); component2.pivot = new Vector2(1f, 1f); component2.anchoredPosition = new Vector2(-92f, -12f); GameObject val = new GameObject("Scroll", new Type[3] { typeof(RectTransform), typeof(ScrollRect), typeof(Image) }); val.transform.SetParent(_root.transform, false); RectTransform component3 = val.GetComponent(); component3.anchorMin = new Vector2(0f, 0f); component3.anchorMax = new Vector2(1f, 1f); component3.offsetMin = new Vector2(8f, 10f); component3.offsetMax = new Vector2(-8f, -56f); Image component4 = val.GetComponent(); ((Graphic)component4).color = new Color(1f, 1f, 1f, 0f); ((Graphic)component4).raycastTarget = false; GameObject val2 = new GameObject("Viewport", new Type[3] { typeof(RectTransform), typeof(Image), typeof(Mask) }); val2.transform.SetParent(val.transform, false); RectTransform component5 = val2.GetComponent(); component5.anchorMin = Vector2.zero; component5.anchorMax = Vector2.one; component5.offsetMin = Vector2.zero; component5.offsetMax = Vector2.zero; Image component6 = val2.GetComponent(); ((Graphic)component6).color = new Color(1f, 1f, 1f, 0.01f); ((Graphic)component6).raycastTarget = true; val2.GetComponent().showMaskGraphic = false; GameObject val3 = new GameObject("Content", new Type[3] { typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter) }); val3.transform.SetParent(val2.transform, false); _content = val3.GetComponent(); _content.anchorMin = new Vector2(0f, 1f); _content.anchorMax = new Vector2(1f, 1f); _content.pivot = new Vector2(0.5f, 1f); _content.anchoredPosition = Vector2.zero; _content.sizeDelta = new Vector2(0f, 0f); VerticalLayoutGroup component7 = val3.GetComponent(); ((HorizontalOrVerticalLayoutGroup)component7).spacing = 8f; ((LayoutGroup)component7).padding = new RectOffset(10, 10, 4, 8); ((HorizontalOrVerticalLayoutGroup)component7).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)component7).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)component7).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)component7).childForceExpandWidth = true; ((LayoutGroup)component7).childAlignment = (TextAnchor)0; val3.GetComponent().verticalFit = (FitMode)2; ScrollRect component8 = val.GetComponent(); component8.viewport = component5; component8.content = _content; component8.horizontal = false; component8.vertical = true; component8.scrollSensitivity = 28f; component8.movementType = (MovementType)2; component8.verticalScrollbar = null; component8.horizontalScrollbar = null; component8.inertia = true; Image component9 = _root.GetComponent(); if ((Object)(object)component9 != (Object)null) { ((Graphic)component9).raycastTarget = false; } AddDragHandles(); _root.SetActive(false); } } internal void RebuildLayout() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_root == (Object)null)) { ApplyPanelLayout(); Image component = _root.GetComponent(); if ((Object)(object)component != (Object)null) { StatsUiHelper.ApplyRounded(component, StatsUiHelper.PanelColor); ((Graphic)component).raycastTarget = false; } StatsUiHelper.SetAccentVisible(_root, visible: false); } } private void ApplyPanelLayout() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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) //IL_0050: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) if (StatsUiHelper.OverlayReady) { Vector2 overlaySize = StatsUiHelper.OverlaySize; float num = 16f; float num2 = Mathf.Clamp(Plugin.Configs.TabPanelWidth.Value, 280f, Mathf.Min(640f, overlaySize.x * 0.55f)); float num3 = Mathf.Min(overlaySize.y * 0.74f, overlaySize.y - num * 2f); Vector2 savedOrDefaultPosition = GetSavedOrDefaultPosition(overlaySize, num2, num3); if ((Object)(object)_root == (Object)null) { _root = StatsUiHelper.CreateGlassPanel(StatsUiHelper.OverlayRoot, "MM_StatsTab", savedOrDefaultPosition, new Vector2(num2, num3), StatsUiHelper.PanelColor.a); } else { StatsUiHelper.ApplyRect(_root, Vector2.zero, Vector2.zero, Vector2.zero, savedOrDefaultPosition, new Vector2(num2, num3)); } } } private static Vector2 GetSavedOrDefaultPosition(Vector2 canvas, float width, float height) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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) if (Plugin.Configs.TabPosX.Value < 0f || Plugin.Configs.TabPosY.Value < 0f) { return new Vector2((canvas.x - width) * 0.5f, (canvas.y - height) * 0.5f); } return new Vector2(Mathf.Clamp(Plugin.Configs.TabPosX.Value, 8f, Mathf.Max(8f, canvas.x - width - 8f)), Mathf.Clamp(Plugin.Configs.TabPosY.Value, 8f, Mathf.Max(8f, canvas.y - height - 8f))); } private void AddDragHandles() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_root == (Object)null) && !((Object)(object)_root.transform.Find("HeaderDrag") != (Object)null)) { RectTransform component = _root.GetComponent(); GameObject val = new GameObject("HeaderDrag", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(OverlayDrag) }); val.transform.SetParent(_root.transform, false); val.transform.SetSiblingIndex(0); RectTransform component2 = val.GetComponent(); component2.anchorMin = new Vector2(0f, 1f); component2.anchorMax = new Vector2(1f, 1f); component2.pivot = new Vector2(0.5f, 1f); component2.anchoredPosition = Vector2.zero; component2.sizeDelta = new Vector2(0f, 58f); Image component3 = val.GetComponent(); ((Graphic)component3).color = new Color(1f, 1f, 1f, 0.01f); ((Graphic)component3).raycastTarget = true; val.GetComponent().Target = component; GameObject val2 = new GameObject("Resize", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(OverlayDrag) }); val2.transform.SetParent(_root.transform, false); RectTransform component4 = val2.GetComponent(); component4.anchorMin = new Vector2(0f, 0f); component4.anchorMax = new Vector2(0f, 1f); component4.pivot = new Vector2(0f, 0.5f); component4.offsetMin = new Vector2(0f, 0f); component4.offsetMax = new Vector2(12f, -58f); Image component5 = val2.GetComponent(); ((Graphic)component5).color = new Color(1f, 1f, 1f, 0.01f); ((Graphic)component5).raycastTarget = true; OverlayDrag component6 = val2.GetComponent(); component6.Target = component; component6.ResizeWidth = true; Transform obj = _root.transform.Find("Close_Btn"); if (obj != null) { obj.SetAsLastSibling(); } Transform obj2 = _root.transform.Find("Compare_Btn"); if (obj2 != null) { obj2.SetAsLastSibling(); } } } internal void SetOpen(bool open) { bool flag = open && StatsController.InActiveMatch(); if (flag) { EnsureBuilt(); } IsOpen = flag; if ((Object)(object)_root != (Object)null) { _root.SetActive(flag); } if (flag) { RebuildLayout(); EnsureCompareTarget(); Refresh(); } } internal void Toggle() { SetOpen(!IsOpen); } internal void ToggleCompareMode() { _compareMode = !_compareMode; EnsureCompareTarget(); Refresh(); } internal void CycleCompareTarget(int direction) { if (!_compareMode) { return; } List otherPlayers = GetOtherPlayers(); if (otherPlayers.Count != 0) { int num = otherPlayers.FindIndex((Player p) => p.playerID == _compareTargetPlayerId); if (num < 0) { num = 0; } num = (num + direction + otherPlayers.Count) % otherPlayers.Count; _compareTargetPlayerId = otherPlayers[num].playerID; Refresh(); } } internal void PinLocalBaseline() { Player val = PlayerStatsSnapshot.LocalPlayer(); if (!((Object)(object)val == (Object)null) && PlayerStatsSnapshot.TryFrom(val, out var snapshot)) { _pinnedLocal = snapshot; _pinnedLocalPlayerId = val.playerID; } } internal void ResetPinnedBaseline() { _pinnedLocal = null; _pinnedLocalPlayerId = -1; } internal void HandleShortcuts() { //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) //IL_0019: 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 (!IsOpen) { return; } KeyCode value = Plugin.Configs.TabCompareKey.Value; if ((int)value != 0 && Input.GetKeyDown(value)) { ToggleCompareMode(); } if (_compareMode) { if (Input.GetKeyDown((KeyCode)91) || Input.GetKeyDown((KeyCode)44)) { CycleCompareTarget(-1); } if (Input.GetKeyDown((KeyCode)93) || Input.GetKeyDown((KeyCode)46)) { CycleCompareTarget(1); } } if (Input.GetKeyDown((KeyCode)112)) { PinLocalBaseline(); } if (Input.GetKeyDown((KeyCode)8) || Input.GetKeyDown((KeyCode)127)) { ResetPinnedBaseline(); } } internal void Refresh() { if (!((Object)(object)_root == (Object)null) && _root.activeSelf) { if (_compareMode) { RefreshCompareView(); } else { RefreshAllPlayersView(); } } } private void RefreshAllPlayersView() { List list = new List(); foreach (Player item in PlayerStatsSnapshot.ActivePlayers()) { list.Add(item); } EnsureBlockCount(list.Count); bool flag = false; for (int i = 0; i < _playerBlocks.Count; i++) { bool flag2 = i < list.Count; GameObject gameObject = ((Component)((TMP_Text)_playerBlocks[i]).transform.parent).gameObject; if (gameObject.activeSelf != flag2) { gameObject.SetActive(flag2); flag = true; } if (flag2) { if (!PlayerStatsSnapshot.TryFrom(list[i], out var snapshot)) { flag |= AssignBlockText(_playerBlocks[i], "Unavailable"); continue; } PlayerStatsSnapshot pinnedBaselineFor = GetPinnedBaselineFor(list[i]); string text = ((pinnedBaselineFor != null) ? StatsViewBuilder.BuildHud(snapshot, simple: false, pinnedBaselineFor, null, TabInfoBridge.GetExtensionStats(list[i])) : StatsViewBuilder.BuildTabBlock(snapshot, TabInfoBridge.GetExtensionStats(list[i]))); flag |= AssignBlockText(_playerBlocks[i], text); } } if (flag) { RelayoutBlocks(); } ((TMP_Text)_title).text = FormatAllPlayersTitle(); ((TMP_Text)_hint).text = "Drag the header to move"; } private void RefreshCompareView() { Player val = PlayerStatsSnapshot.LocalPlayer(); if ((Object)(object)val == (Object)null) { using IEnumerator enumerator = PlayerStatsSnapshot.ActivePlayers().GetEnumerator(); if (enumerator.MoveNext()) { val = enumerator.Current; } } List otherPlayers = GetOtherPlayers(); Player val2 = otherPlayers.Find((Player p) => p.playerID == _compareTargetPlayerId) ?? ((otherPlayers.Count > 0) ? otherPlayers[0] : null); if ((Object)(object)val2 != (Object)null) { _compareTargetPlayerId = val2.playerID; } EnsureBlockCount((!((Object)(object)val2 != (Object)null)) ? 1 : 2); for (int num = 0; num < _playerBlocks.Count; num++) { ((Component)((TMP_Text)_playerBlocks[num]).transform.parent).gameObject.SetActive(num < ((!((Object)(object)val2 != (Object)null)) ? 1 : 2)); } PlayerStatsSnapshot snapshot2; if ((Object)(object)val == (Object)null || !PlayerStatsSnapshot.TryFrom(val, out var snapshot)) { AssignBlockText(_playerBlocks[0], "Local player unavailable"); RelayoutBlocks(); ((TMP_Text)_title).text = "Compare"; ((TMP_Text)_hint).text = "No local player"; } else if ((Object)(object)val2 == (Object)null || !PlayerStatsSnapshot.TryFrom(val2, out snapshot2)) { AssignBlockText(_playerBlocks[0], StatsViewBuilder.BuildTabBlock(snapshot, TabInfoBridge.GetExtensionStats(val))); RelayoutBlocks(); ((TMP_Text)_title).text = "Compare"; ((TMP_Text)_hint).text = "Need another player to compare"; } else { PlayerStatsSnapshot opponent = snapshot2; PlayerStatsSnapshot pinnedLocal = ((_pinnedLocal != null && _pinnedLocalPlayerId == val.playerID) ? _pinnedLocal : null); AssignBlockText(_playerBlocks[0], StatsViewBuilder.BuildTabCompare(snapshot, opponent, pinnedLocal, TabInfoBridge.GetExtensionStats(val))); AssignBlockText(_playerBlocks[1], StatsViewBuilder.BuildTabBlock(snapshot2, TabInfoBridge.GetExtensionStats(val2))); RelayoutBlocks(); ((TMP_Text)_title).text = "You vs " + snapshot2.PlayerName; ((TMP_Text)_hint).text = "[ ] switch player · C back to all"; } } private static string FormatAllPlayersTitle() { string text = $"All players · R{StatsController.CurrentRound} P{StatsController.CurrentPoint}"; int num = PingTracker.LocalPing(); if (num < 0) { return text; } return $"{text} · you {num}ms"; } private static bool AssignBlockText(TextMeshProUGUI block, string text) { if ((Object)(object)block == (Object)null) { return false; } ((TMP_Text)block).lineSpacing = 4f; if (((TMP_Text)block).text == text) { return false; } ((TMP_Text)block).text = text; return true; } private PlayerStatsSnapshot GetPinnedBaselineFor(Player player) { Player val = PlayerStatsSnapshot.LocalPlayer(); if ((Object)(object)val == (Object)null || player.playerID != val.playerID) { return null; } if (_pinnedLocal == null || _pinnedLocalPlayerId != val.playerID) { return null; } return _pinnedLocal; } private void EnsureCompareTarget() { if (_compareMode) { List otherPlayers = GetOtherPlayers(); if (otherPlayers.Count == 0) { _compareTargetPlayerId = -1; } else if (otherPlayers.All((Player p) => p.playerID != _compareTargetPlayerId)) { _compareTargetPlayerId = otherPlayers[0].playerID; } } } private static List GetOtherPlayers() { Player val = PlayerStatsSnapshot.LocalPlayer(); List list = new List(); foreach (Player item in PlayerStatsSnapshot.ActivePlayers()) { if (!((Object)(object)val != (Object)null) || item.playerID != val.playerID) { list.Add(item); } } if ((Object)(object)val == (Object)null && list.Count > 1) { list.RemoveAt(0); } return list; } private void EnsureBlockCount(int count) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_00bf: 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_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) while (_playerBlocks.Count < count) { GameObject val = new GameObject($"Player_{_playerBlocks.Count}", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(LayoutElement) }); val.transform.SetParent((Transform)(object)_content, false); RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); component.sizeDelta = new Vector2(0f, 120f); Image component2 = val.GetComponent(); StatsUiHelper.ApplyRounded(component2, StatsUiHelper.BlockColor); ((Graphic)component2).raycastTarget = false; LayoutElement component3 = val.GetComponent(); component3.minHeight = 96f; component3.preferredHeight = 120f; component3.flexibleWidth = 1f; component3.flexibleHeight = 0f; TextMeshProUGUI val2 = StatsUiHelper.CreateText(val.transform, "Text", "", StatsUiHelper.BaseFont, (TextAlignmentOptions)257); ((TMP_Text)val2).enableWordWrapping = true; ((TMP_Text)val2).overflowMode = (TextOverflowModes)0; ((TMP_Text)val2).lineSpacing = 4f; ((TMP_Text)val2).rectTransform.anchorMin = new Vector2(0f, 0f); ((TMP_Text)val2).rectTransform.anchorMax = new Vector2(1f, 1f); ((TMP_Text)val2).rectTransform.offsetMin = new Vector2(10f, 8f); ((TMP_Text)val2).rectTransform.offsetMax = new Vector2(-10f, -8f); _playerBlocks.Add(val2); } } private void RelayoutBlocks() { if ((Object)(object)_content == (Object)null) { return; } LayoutRebuilder.ForceRebuildLayoutImmediate(_content); foreach (TextMeshProUGUI playerBlock in _playerBlocks) { if (!((Object)(object)playerBlock == (Object)null) && ((Component)playerBlock).gameObject.activeInHierarchy) { UpdateBlockHeight(((Component)((TMP_Text)playerBlock).transform.parent).gameObject, playerBlock); } } LayoutRebuilder.ForceRebuildLayoutImmediate(_content); } private static void UpdateBlockHeight(GameObject block, TextMeshProUGUI text) { ((TMP_Text)text).ForceMeshUpdate(); LayoutElement component = block.GetComponent(); if ((Object)(object)component != (Object)null) { float preferredHeight = (component.minHeight = Mathf.Max(96f, ((TMP_Text)text).preferredHeight + 20f)); component.preferredHeight = preferredHeight; } } } internal static class StatsUiHelper { private static Canvas _overlay; private static Sprite _roundedSprite; internal static float UiScale => 1f; internal static float BaseFont => 13.5f * UiScale; internal static float HeaderFont => 15f * UiScale; internal static float TitleFont => 18f * UiScale; internal static float HeroFont => 15.5f * UiScale; internal static Color AccentColor => new Color(0.78f, 0.8f, 0.84f); internal static Color TitleColor => new Color(0.93f, 0.94f, 0.96f, 0.98f); internal static Color HintColor => new Color(0.84f, 0.87f, 0.92f, 0.96f); internal static Color PanelColor => new Color(0.07f, 0.08f, 0.1f, 0.9f); internal static Color BlockColor => new Color(1f, 1f, 1f, 0.04f); internal static Color ButtonFill => new Color(1f, 1f, 1f, 0.07f); internal static Transform OverlayRoot { get { EnsureOverlayCanvas(); return ((Component)_overlay).transform; } } internal static Vector2 OverlaySize { get { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) EnsureOverlayCanvas(); Rect rect = ((Component)_overlay).GetComponent().rect; Vector2 size = ((Rect)(ref rect)).size; if (size.x < 8f || size.y < 8f) { return new Vector2(1920f, 1080f); } return size; } } internal static bool OverlayReady { get { EnsureOverlayCanvas(); return (Object)(object)_overlay != (Object)null; } } internal static Sprite RoundedSprite { get { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_0074: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_roundedSprite != (Object)null) { return _roundedSprite; } Texture2D val = new Texture2D(64, 64, (TextureFormat)5, false) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; Color[] array = (Color[])(object)new Color[4096]; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { array[i * 64 + j] = new Color(1f, 1f, 1f, RoundedAlpha((float)j + 0.5f, (float)i + 0.5f, 64, 14)); } } val.SetPixels(array); val.Apply(false, false); _roundedSprite = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(14f, 14f, 14f, 14f)); ((Object)_roundedSprite).name = "MM_RoundedPanel"; return _roundedSprite; } } private static void EnsureOverlayCanvas() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_overlay != (Object)null)) { GameObject val = new GameObject("MM_StatsOverlay", new Type[4] { typeof(RectTransform), typeof(Canvas), typeof(CanvasScaler), typeof(GraphicRaycaster) }); Object.DontDestroyOnLoad((Object)val); _overlay = val.GetComponent(); _overlay.renderMode = (RenderMode)0; _overlay.sortingOrder = 300; _overlay.pixelPerfect = false; CanvasScaler component = val.GetComponent(); component.uiScaleMode = (ScaleMode)1; component.referenceResolution = new Vector2(1920f, 1080f); component.screenMatchMode = (ScreenMatchMode)0; component.matchWidthOrHeight = 1f; } } private static float RoundedAlpha(float x, float y, int size, int radius) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) int num = size - radius; int num2 = size - radius; if (x >= (float)radius && x <= (float)num) { if (!(x >= 0f) || !(x <= (float)size) || !(y >= 0f) || !(y <= (float)size)) { return 0f; } return 1f; } if (y >= (float)radius && y <= (float)num2) { if (!(x >= 0f) || !(x <= (float)size) || !(y >= 0f) || !(y <= (float)size)) { return 0f; } return 1f; } int num3 = ((x < (float)radius) ? radius : num); int num4 = ((y < (float)radius) ? radius : num2); float num5 = Vector2.Distance(new Vector2(x, y), new Vector2((float)num3, (float)num4)); return Mathf.Clamp01((float)radius - num5 + 0.5f); } internal static void ApplyRounded(Image image, Color color) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)image == (Object)null)) { image.sprite = RoundedSprite; image.type = (Type)1; ((Graphic)image).color = color; } } internal static GameObject CreateModernPanel(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 anchoredPos, Vector2 sizeDelta, float alpha = 0.88f) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0019: Unknown result type (might be due to invalid IL or missing references) GameObject obj = CreatePanel(parent, name, anchorMin, anchorMax, pivot, anchoredPos, sizeDelta, new Color(0.05f, 0.07f, 0.1f), alpha); CreateAccentBar(obj.transform, "AccentTop", top: true); CreateAccentBar(obj.transform, "AccentBottom", top: false); return obj; } internal static GameObject CreateGlassPanel(Transform parent, string name, Vector2 anchoredPos, Vector2 sizeDelta, float alpha = 0.9f) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_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) GameObject obj = CreatePanel(parent, name, Vector2.zero, Vector2.zero, Vector2.zero, anchoredPos, sizeDelta, PanelColor, alpha); ApplyRounded(obj.GetComponent(), new Color(PanelColor.r, PanelColor.g, PanelColor.b, alpha)); ((Graphic)obj.GetComponent()).raycastTarget = false; return obj; } internal static void SetAccentVisible(GameObject root, bool visible) { if (!((Object)(object)root == (Object)null)) { Transform val = root.transform.Find("AccentTop") ?? root.transform.Find("Accent"); Transform val2 = root.transform.Find("AccentBottom"); if ((Object)(object)val != (Object)null) { ((Component)val).gameObject.SetActive(visible); } if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(visible); } } } private static void CreateAccentBar(Transform parent, string name, bool top) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent(); if (top) { component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); } else { component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(1f, 0f); component.pivot = new Vector2(0.5f, 0f); } component.anchoredPosition = Vector2.zero; component.sizeDelta = new Vector2(0f, 3f); ((Graphic)val.GetComponent()).color = AccentColor; ((Graphic)val.GetComponent()).raycastTarget = false; } internal static GameObject CreatePanel(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 anchoredPos, Vector2 sizeDelta, Color bg, float alpha = 0.82f) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent(); component.anchorMin = anchorMin; component.anchorMax = anchorMax; component.pivot = pivot; component.anchoredPosition = anchoredPos; component.sizeDelta = sizeDelta; Image component2 = val.GetComponent(); ((Graphic)component2).color = new Color(bg.r, bg.g, bg.b, alpha); ((Graphic)component2).raycastTarget = false; return val; } internal static TextMeshProUGUI CreateText(Transform parent, string name, string text, float fontSize, TextAlignmentOptions align = (TextAlignmentOptions)257, Color? color = null) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; TextMeshProUGUI component2 = val.GetComponent(); ((TMP_Text)component2).text = text; ((TMP_Text)component2).fontSize = fontSize; ((TMP_Text)component2).alignment = align; ((Graphic)component2).color = (Color)(((??)color) ?? Color.white); ((Graphic)component2).raycastTarget = false; ((TMP_Text)component2).richText = true; ((TMP_Text)component2).enableWordWrapping = true; ((TMP_Text)component2).lineSpacing = 0f; ((TMP_Text)component2).overflowMode = (TextOverflowModes)0; return component2; } internal static Button CreateButton(Transform parent, string label, UnityAction onClick, Vector2 size) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) return CreateGhostButton(parent, label, onClick, size); } internal static Button CreateGhostButton(Transform parent, string label, UnityAction onClick, Vector2 size) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(label + "_Btn", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button) }); val.transform.SetParent(parent, false); val.GetComponent().sizeDelta = size; Image component = val.GetComponent(); ApplyRounded(component, ButtonFill); Button component2 = val.GetComponent