using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; 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 HarmonyLib; using Microsoft.CodeAnalysis; using SoloShared; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.Utilities; using UnityEngine.Localization; using UnityEngine.Localization.Settings; 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: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("HappyTheLegend")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright (c) 2026 HappyTheLegend")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+84251d1fd4d525e86e0aca6c86990dfc4637245e")] [assembly: AssemblyProduct("SoloHUD")] [assembly: AssemblyTitle("SoloHUD")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.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 SoloShared { internal static class Loc { private static Dictionary _table = new Dictionary(StringComparer.Ordinal); private static string _folder; private static string _mod = "Solo"; private static string _loaded = ""; private static float _nextCheck; private static Action _log = delegate { }; private static Action _warn = delegate { }; private static readonly SortedSet _seen = new SortedSet(StringComparer.Ordinal); private static bool _collect; internal static string Language { get { if (_loaded.Length != 0) { return _loaded; } return "en"; } } internal static void Init(string modName, string dllPath, Action log, Action warn, bool collectStrings = false) { _mod = modName ?? "Solo"; _log = log ?? ((Action)delegate { }); _warn = warn ?? ((Action)delegate { }); _collect = collectStrings; try { _folder = Path.GetDirectoryName(dllPath); } catch { _folder = null; } Reload(CurrentLanguage()); } internal static string T(string english) { if (string.IsNullOrEmpty(english)) { return english; } if (_collect) { lock (_seen) { _seen.Add(english); } } if (!_table.TryGetValue(english, out var value) || value.Length <= 0) { return english; } return value; } internal static string F(string english, params object[] args) { string format = T(english); try { return string.Format(format, args); } catch { try { return string.Format(english, args); } catch { return english; } } } internal static void Tick(float unscaledTime) { if (!(unscaledTime < _nextCheck)) { _nextCheck = unscaledTime + 2f; string text = CurrentLanguage(); if (text != _loaded) { Reload(text); } } } private static string CurrentLanguage() { //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) try { Locale selectedLocale = LocalizationSettings.SelectedLocale; object obj; if (!((Object)(object)selectedLocale != (Object)null)) { obj = ""; } else { LocaleIdentifier identifier = selectedLocale.Identifier; obj = ((LocaleIdentifier)(ref identifier)).Code; } string text = (string)obj; return string.IsNullOrEmpty(text) ? "en" : text; } catch { return "en"; } } private static void Reload(string code) { _loaded = code ?? "en"; Dictionary dictionary = new Dictionary(StringComparer.Ordinal); if (!string.IsNullOrEmpty(_folder) && !_loaded.StartsWith("en", StringComparison.OrdinalIgnoreCase)) { string text = Path.Combine(_folder, "lang"); foreach (string item in Candidates(_loaded, text)) { string path = Path.Combine(text, item + ".txt"); if (File.Exists(path)) { int num = Read(path, dictionary); _log($"[{_mod}] Language {item}: {num} line(s) from {Path.GetFileName(path)}."); break; } } } _table = dictionary; if (dictionary.Count > 0) { _log("[" + _mod + "] Following the game's language: " + _loaded + "."); } if (dictionary.Count == 0 && !_loaded.StartsWith("en", StringComparison.OrdinalIgnoreCase)) { _log("[" + _mod + "] No translation file for '" + _loaded + "' — showing English. Add lang/" + _loaded + ".txt beside the mod to change that."); } } private static IEnumerable Candidates(string code, string dir) { yield return code; string language = code; int num = code.IndexOf('-'); if (num > 0) { language = code.Substring(0, num); yield return language; } string[] array; try { array = (Directory.Exists(dir) ? Directory.GetFiles(dir, "*.txt") : new string[0]); } catch { yield break; } string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(array2[i]); if (fileNameWithoutExtension.StartsWith(language + "-", StringComparison.OrdinalIgnoreCase)) { yield return fileNameWithoutExtension; } } } private static int Read(string path, Dictionary into) { int num = 0; try { string text = null; string[] array = File.ReadAllLines(path, Encoding.UTF8); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length == 0 || text2[0] == '#') { continue; } if (text2[0] == '=') { text = Unescape(text2.Substring(1).Trim()); } else if (text2[0] == '>' && text != null) { string text3 = Unescape(text2.Substring(1).Trim()); if (text3.Length > 0) { into[text] = text3; num++; } text = null; } } } catch (Exception ex) { _warn("[" + _mod + "] Couldn't read " + Path.GetFileName(path) + ": " + ex.Message); } return num; } private static string Unescape(string s) { return s.Replace("\\n", "\n"); } private static string Escape(string s) { return s.Replace("\n", "\\n"); } internal static void DumpSeen() { if (!_collect || string.IsNullOrEmpty(_folder)) { return; } try { string text = Path.Combine(_folder, "lang"); Directory.CreateDirectory(text); string path = Path.Combine(text, "_english.txt"); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# Every line " + _mod + " has shown this session."); stringBuilder.AppendLine("# Copy this file to .txt and fill in the > lines."); stringBuilder.AppendLine("# Leave a > line empty to keep the English."); stringBuilder.AppendLine(); lock (_seen) { foreach (string item in _seen) { stringBuilder.Append("= ").AppendLine(Escape(item)); stringBuilder.AppendLine("> "); } File.WriteAllText(path, stringBuilder.ToString(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); _log($"[{_mod}] Wrote {_seen.Count} line(s) to lang/_english.txt."); } } catch (Exception ex) { _warn("[" + _mod + "] Couldn't write the English list: " + ex.Message); } } } } namespace SoloHUD { internal static class HudController { private static bool _visible = true; private static bool _keyWasDown; private static bool _fullListHeld; private static bool _firstTickLogged; private static float _buildWarnTimer; private static float _stateLogTimer; private static int _lastFrame = -1; private static bool _dotsDirty; private static readonly HashSet _reportedErrors = new HashSet(); private static readonly HudData Data = new HudData(); private static float _scanTimer; private const float ScanInterval = 0.25f; private static Texture2D _white; private static Texture2D _circle; private static GameObject _root; private static TextMeshProUGUI _infoText; private static RawImage _infoBg; private static RectTransform _radar; private static RawImage _radarBg; private static RawImage _mapImage; private static RawImage _centerDot; private static RawImage _fullBg; private static TextMeshProUGUI _fullText; private static readonly List _dots = new List(); private const int MaxDots = 96; private static Camera _mapCam; private static Texture _mapTex; private static Material _mapMat; private static float _mapCamSearchTimer; private static bool _mapCamLogged; private static bool _mapTexIsFallback; private static Texture2D White { get { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_white == (Object)null) { _white = new Texture2D(1, 1); _white.SetPixel(0, 0, Color.white); _white.Apply(); ((Object)_white).hideFlags = (HideFlags)61; } return _white; } } private static Texture2D Circle { get { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0038: 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_0076: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_circle == (Object)null) { _circle = new Texture2D(32, 32, (TextureFormat)5, false); for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num = Vector2.Distance(new Vector2((float)j + 0.5f, (float)i + 0.5f), new Vector2(16f, 16f)); float num2 = Mathf.Clamp01(16f - num); _circle.SetPixel(j, i, new Color(1f, 1f, 1f, num2)); } } _circle.Apply(); ((Texture)_circle).filterMode = (FilterMode)1; ((Object)_circle).hideFlags = (HideFlags)61; } return _circle; } } public static void Tick() { if (!Plugin.Ready || _lastFrame == Time.frameCount) { return; } _lastFrame = Time.frameCount; try { if (!_firstTickLogged) { _firstTickLogged = true; bool flag = Plugin.Instance == null; bool flag2 = (Object)(object)Plugin.Instance == (Object)null; Plugin.Log.LogInfo((object)($"[SoloHUD] First tick — driver hook is firing. plugin ref-null={flag} " + string.Format("unity-null={0}{1}", flag2, (!flag && flag2) ? " <- MonoBehaviour was destroyed (expected)" : ""))); } HandleToggle(); UpdateFullListHeld(); if ((Object)(object)_root == (Object)null) { TryBuild(); } if ((Object)(object)_root == (Object)null) { _buildWarnTimer -= Time.unscaledDeltaTime; if (_buildWarnTimer <= 0f) { _buildWarnTimer = 3f; Plugin.Log.LogWarning((object)($"[SoloHUD] Overlay not built yet — HUDCanvas={(Object)(object)HUDCanvas.instance != (Object)null} " + $"HaulUI={(Object)(object)HaulUI.instance != (Object)null}")); } return; } _scanTimer -= Time.unscaledDeltaTime; if (_scanTimer <= 0f) { _scanTimer = 0.25f; Data.Refresh(); _dotsDirty = true; _stateLogTimer -= 0.25f; if (_stateLogTimer <= 0f) { _stateLogTimer = 15f; Plugin.Log.LogInfo((object)($"[SoloHUD] state: InLevel={Data.InLevel} value=${Data.TotalMapValue:n0} " + $"valuables={Data.RawValuableCount} monsterTypes={Data.Monsters.Count} " + $"enemies={Data.RawEnemyCount} players={Data.RawPlayerCount} " + "mapCam=" + (((Object)(object)_mapCam != (Object)null) ? ((Object)_mapCam).name : "none") + " err=" + Data.DiagError)); } } if (_visible && Data.InLevel && Plugin.UseGameMap.Value) { EnsureGameMapLive(); } bool flag3 = (Object)(object)MenuManager.instance != (Object)null && (Object)(object)MenuManager.instance.currentMenuPage != (Object)null; bool flag4 = Plugin.HideWhileMapOpen.Value && IsMapToolActive(); bool flag5 = _visible && !flag3 && !flag4; _root.SetActive(flag5); if (flag5) { Render(); } } catch (Exception ex) { if (_reportedErrors.Add(ex.StackTrace ?? ex.Message)) { Plugin.Log.LogError((object)$"[SoloHUD] tick threw {ex.GetType().Name}: {ex.Message}\n{ex}"); } } } private static void HandleToggle() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) Keyboard current = Keyboard.current; if (current == null) { return; } Key value = Plugin.ToggleKey.Value; KeyControl val = (((int)value == 0) ? null : current[value]); int num; if (val != null) { num = (((ButtonControl)val).isPressed ? 1 : 0); if (num != 0 && !_keyWasDown) { _visible = !_visible; Plugin.Log.LogInfo((object)("SoloHUD " + (_visible ? "shown" : "hidden") + ".")); } } else { num = 0; } _keyWasDown = (byte)num != 0; } private static void UpdateFullListHeld() { //IL_0015: 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_001b: 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) Keyboard current = Keyboard.current; if (current == null) { _fullListHeld = false; return; } Key value = Plugin.MonsterListKey.Value; KeyControl val = (((int)value == 0) ? null : current[value]); _fullListHeld = val != null && ((ButtonControl)val).isPressed; } private static bool IsMapToolActive() { MapToolController instance = MapToolController.instance; if ((Object)(object)instance != (Object)null) { return instance.Active; } return false; } private static void EnsureGameMapLive() { Map instance = Map.Instance; if ((Object)(object)instance == (Object)null) { return; } if (!instance.Active) { instance.ActiveSet(true); } if ((Object)(object)_mapTex != (Object)null && (Object)(object)_mapCam != (Object)null && !_mapTexIsFallback) { return; } _mapCamSearchTimer -= Time.unscaledDeltaTime; if (_mapCamSearchTimer > 0f) { return; } _mapCamSearchTimer = 1f; if ((Object)(object)_mapCam == (Object)null) { _mapCam = FindMapCamera(instance); if ((Object)(object)_mapCam != (Object)null) { Plugin.Log.LogInfo((object)($"[SoloHUD] Map camera '{((Object)_mapCam).name}' found (ortho={_mapCam.orthographic}, " + "target=" + (((Object)(object)_mapCam.targetTexture != (Object)null) ? (((Texture)_mapCam.targetTexture).width + "x" + ((Texture)_mapCam.targetTexture).height) : "none") + ").")); } } if ((Object)(object)_mapTex == (Object)null || _mapTexIsFallback) { Texture val = FindMapTexture(); if ((Object)(object)val != (Object)null) { _mapTex = val; } } } private static Texture FindMapTexture() { MapToolController val = MapToolController.instance; if ((Object)(object)val == (Object)null) { MapToolController[] array = Object.FindObjectsOfType(); foreach (MapToolController val2 in array) { if (!((Object)(object)val2 == (Object)null)) { Material val3 = (((Object)(object)val2.DisplayMesh != (Object)null) ? ((Renderer)val2.DisplayMesh).sharedMaterial : null); if ((Object)(object)val3 == (Object)null) { val3 = val2.DisplayMaterial; } if ((Object)(object)val3 != (Object)null && (Object)(object)FirstRenderTexture(val3) != (Object)null) { val = val2; break; } } } if ((Object)(object)val != (Object)null) { Plugin.Log.LogInfo((object)"[SoloHUD] Map device found by search (instance was null)."); } } if ((Object)(object)val != (Object)null) { Material val4 = null; if ((Object)(object)val.DisplayMesh != (Object)null) { val4 = ((Renderer)val.DisplayMesh).sharedMaterial; } if ((Object)(object)val4 == (Object)null) { val4 = val.DisplayMaterial; } if ((Object)(object)val4 != (Object)null) { RenderTexture val5 = FirstRenderTexture(val4); if ((Object)(object)val5 != (Object)null) { _mapMat = Object.Instantiate(val4); ((Object)_mapMat).hideFlags = (HideFlags)61; _mapTexIsFallback = false; Plugin.Log.LogInfo((object)($"[SoloHUD] Using map display texture '{((Object)val5).name}' ({((Texture)val5).width}x{((Texture)val5).height}) " + "from material '" + ((Object)val4).name + "' (shader '" + ((Object)val4.shader).name + "').")); return (Texture)(object)val5; } Plugin.Log.LogWarning((object)("[SoloHUD] Map display material '" + ((Object)val4).name + "' has no RenderTexture. Properties: " + string.Join(", ", val4.GetTexturePropertyNames()))); } } if ((Object)(object)_mapCam != (Object)null && (Object)(object)_mapCam.targetTexture != (Object)null) { if (!_mapTexIsFallback) { Plugin.Log.LogInfo((object)"[SoloHUD] Falling back to the map camera's target texture (no underlay yet) — will keep watching for the map device."); } _mapTexIsFallback = true; return (Texture)(object)_mapCam.targetTexture; } return null; } private static RenderTexture FirstRenderTexture(Material mat) { Texture mainTexture = mat.mainTexture; RenderTexture val = (RenderTexture)(object)((mainTexture is RenderTexture) ? mainTexture : null); if (val != null) { return val; } string[] texturePropertyNames = mat.GetTexturePropertyNames(); foreach (string text in texturePropertyNames) { Texture texture = mat.GetTexture(text); RenderTexture val2 = (RenderTexture)(object)((texture is RenderTexture) ? texture : null); if (val2 != null) { return val2; } } return null; } private static Camera FindMapCamera(Map map) { Camera[] componentsInChildren = ((Component)map).GetComponentsInChildren(true); Camera[] array = componentsInChildren; foreach (Camera val in array) { if ((Object)(object)val.targetTexture != (Object)null) { return val; } } if (componentsInChildren.Length != 0) { return componentsInChildren[0]; } Camera val2 = null; Camera[] array2 = Object.FindObjectsOfType(); array = array2; foreach (Camera val3 in array) { if (!((Object)(object)val3.targetTexture == (Object)null) && ((Object)val3).name.ToLowerInvariant().Contains("map")) { val2 = val3; break; } } if ((Object)(object)val2 == (Object)null && !_mapCamLogged) { _mapCamLogged = true; StringBuilder stringBuilder = new StringBuilder("[SoloHUD] No map camera found. Cameras present: "); array = array2; foreach (Camera val4 in array) { stringBuilder.Append($"'{((Object)val4).name}'(rt={(Object)(object)val4.targetTexture != (Object)null}) "); } stringBuilder.Append("— falling back to the dot radar."); Plugin.Log.LogWarning((object)stringBuilder.ToString()); } return val2; } private static bool WorldToMapViewport(Vector3 worldPos, out Vector2 viewport) { //IL_0001: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_00aa: Unknown result type (might be due to invalid IL or missing references) viewport = Vector2.zero; Map instance = Map.Instance; Transform val = (((Object)(object)instance != (Object)null) ? instance.OverLayerParent : null); if ((Object)(object)instance == (Object)null || (Object)(object)_mapCam == (Object)null || (Object)(object)val == (Object)null) { return false; } Vector3 val2 = worldPos * instance.Scale + val.position; Vector3 val3 = val.InverseTransformPoint(val2); val3.y = 0f; val2 = val.TransformPoint(val3); Vector3 val4 = _mapCam.WorldToViewportPoint(val2); if (val4.z <= 0f) { return false; } viewport = new Vector2(val4.x, val4.y); return true; } private static void TryBuild() { //IL_0060: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011c: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0266: 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_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: 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_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_0426: 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_045f: Unknown result type (might be due to invalid IL or missing references) //IL_0493: Unknown result type (might be due to invalid IL or missing references) //IL_049a: Unknown result type (might be due to invalid IL or missing references) //IL_04b5: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Unknown result type (might be due to invalid IL or missing references) //IL_04e7: Unknown result type (might be due to invalid IL or missing references) //IL_04f6: Unknown result type (might be due to invalid IL or missing references) //IL_04fb: Unknown result type (might be due to invalid IL or missing references) //IL_054a: Unknown result type (might be due to invalid IL or missing references) //IL_0583: Unknown result type (might be due to invalid IL or missing references) //IL_05bc: Unknown result type (might be due to invalid IL or missing references) //IL_05d0: Unknown result type (might be due to invalid IL or missing references) //IL_05ee: Unknown result type (might be due to invalid IL or missing references) //IL_060c: Unknown result type (might be due to invalid IL or missing references) Transform val = null; if ((Object)(object)HUDCanvas.instance != (Object)null && (Object)(object)HUDCanvas.instance.rect != (Object)null) { val = (Transform)(object)HUDCanvas.instance.rect; } else if ((Object)(object)HaulUI.instance != (Object)null) { val = ((Component)HaulUI.instance).transform.parent; } if ((Object)(object)val == (Object)null) { return; } TMP_FontAsset val2 = null; Material val3 = null; float characterSpacing = 0f; FontStyles fontStyle = (FontStyles)0; HaulUI instance = HaulUI.instance; TextMeshProUGUI val4 = (((Object)(object)instance != (Object)null) ? ((Component)instance).GetComponent() : null); if ((Object)(object)val4 == (Object)null) { val4 = ((Component)val).GetComponentInChildren(true); } if ((Object)(object)val4 != (Object)null) { val2 = ((TMP_Text)val4).font; val3 = ((TMP_Text)val4).fontSharedMaterial; characterSpacing = ((TMP_Text)val4).characterSpacing; fontStyle = ((TMP_Text)val4).fontStyle; } if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"[SoloHUD] No TMP font found under the HUD yet; retrying."); return; } _root = new GameObject("SoloHUD_Root"); RectTransform val5 = _root.AddComponent(); _root.transform.SetParent(val, false); val5.anchorMin = Vector2.zero; val5.anchorMax = Vector2.one; val5.offsetMin = Vector2.zero; val5.offsetMax = Vector2.zero; ((Transform)val5).localScale = Vector3.one; Vector2 val6 = default(Vector2); ((Vector2)(ref val6))..ctor(Plugin.PanelOffsetX.Value, Plugin.PanelOffsetY.Value); _infoBg = MakeRaw("InfoBg", (Transform)(object)val5, new Color(0f, 0f, 0f, 0f)); AnchorBottomLeft(((Graphic)_infoBg).rectTransform, val6, new Vector2(380f, 120f)); GameObject val7 = new GameObject("InfoText"); val7.transform.SetParent((Transform)(object)val5, false); _infoText = val7.AddComponent(); ((TMP_Text)_infoText).font = val2; if ((Object)(object)val3 != (Object)null) { ((TMP_Text)_infoText).fontSharedMaterial = val3; } ((TMP_Text)_infoText).characterSpacing = characterSpacing; ((TMP_Text)_infoText).fontStyle = fontStyle; ((TMP_Text)_infoText).fontSize = Mathf.Max(6f, Plugin.PanelFontSize.Value); ((TMP_Text)_infoText).lineSpacing = -8f; ((Graphic)_infoText).color = Color.white; ((TMP_Text)_infoText).alignment = (TextAlignmentOptions)1025; ((TMP_Text)_infoText).enableWordWrapping = false; ((Graphic)_infoText).raycastTarget = false; AnchorBottomLeft(((TMP_Text)_infoText).rectTransform, val6 + new Vector2(8f, 6f), new Vector2(360f, 400f)); float num = Mathf.Max(60f, Plugin.RadarSize.Value); _radarBg = MakeRaw("Radar", (Transform)(object)val5, new Color(0f, 0f, 0f, 0.5f)); _radar = ((Graphic)_radarBg).rectTransform; AnchorBottomRight(_radar, new Vector2(-24f, 24f), new Vector2(num, num)); _mapImage = MakeRaw("MapRender", (Transform)(object)_radar, Color.white); RectTransform rectTransform = ((Graphic)_mapImage).rectTransform; RectTransform rectTransform2 = ((Graphic)_mapImage).rectTransform; Vector2 val8 = default(Vector2); ((Vector2)(ref val8))..ctor(0.5f, 0.5f); rectTransform2.anchorMax = val8; rectTransform.anchorMin = val8; ((Graphic)_mapImage).rectTransform.pivot = new Vector2(0.5f, 0.5f); ((Graphic)_mapImage).rectTransform.anchoredPosition = Vector2.zero; ((Behaviour)_mapImage).enabled = false; _centerDot = MakeRaw("You", (Transform)(object)_radar, new Color(0.3f, 1f, 0.4f)); _centerDot.texture = (Texture)(object)Circle; RectTransform rectTransform3 = ((Graphic)_centerDot).rectTransform; RectTransform rectTransform4 = ((Graphic)_centerDot).rectTransform; ((Vector2)(ref val8))..ctor(0.5f, 0.5f); rectTransform4.anchorMax = val8; rectTransform3.anchorMin = val8; ((Graphic)_centerDot).rectTransform.pivot = new Vector2(0.5f, 0.5f); ((Graphic)_centerDot).rectTransform.sizeDelta = new Vector2(7f, 7f); ((Graphic)_centerDot).rectTransform.anchoredPosition = Vector2.zero; _fullBg = MakeRaw("FullListBg", (Transform)(object)val5, new Color(0f, 0f, 0f, 0.82f)); RectTransform rectTransform5 = ((Graphic)_fullBg).rectTransform; RectTransform rectTransform6 = ((Graphic)_fullBg).rectTransform; ((Vector2)(ref val8))..ctor(0.5f, 0.5f); rectTransform6.anchorMax = val8; rectTransform5.anchorMin = val8; ((Graphic)_fullBg).rectTransform.pivot = new Vector2(0.5f, 0.5f); ((Graphic)_fullBg).rectTransform.anchoredPosition = Vector2.zero; ((Graphic)_fullBg).rectTransform.sizeDelta = new Vector2(420f, 300f); GameObject val9 = new GameObject("FullListText"); val9.transform.SetParent((Transform)(object)((Graphic)_fullBg).rectTransform, false); _fullText = val9.AddComponent(); ((TMP_Text)_fullText).font = val2; if ((Object)(object)val3 != (Object)null) { ((TMP_Text)_fullText).fontSharedMaterial = val3; } ((TMP_Text)_fullText).characterSpacing = characterSpacing; ((TMP_Text)_fullText).fontStyle = fontStyle; ((TMP_Text)_fullText).fontSize = Mathf.Max(6f, Plugin.PanelFontSize.Value); ((TMP_Text)_fullText).lineSpacing = -8f; ((Graphic)_fullText).color = Color.white; ((TMP_Text)_fullText).alignment = (TextAlignmentOptions)257; ((TMP_Text)_fullText).enableWordWrapping = false; ((Graphic)_fullText).raycastTarget = false; ((TMP_Text)_fullText).rectTransform.anchorMin = Vector2.zero; ((TMP_Text)_fullText).rectTransform.anchorMax = Vector2.one; ((TMP_Text)_fullText).rectTransform.offsetMin = new Vector2(16f, 12f); ((TMP_Text)_fullText).rectTransform.offsetMax = new Vector2(-16f, -12f); ((Component)_fullBg).gameObject.SetActive(false); _dots.Clear(); Plugin.Log.LogInfo((object)("[SoloHUD] Overlay attached to '" + ((Object)val).name + "' (font: " + ((Object)val2).name + ").")); } private static RawImage MakeRaw(string name, Transform parent, Color color) { //IL_0001: 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_0024: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); RawImage obj = val.AddComponent(); obj.texture = (Texture)(object)White; ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; return obj; } private static void AnchorBottomLeft(RectTransform rt, Vector2 pos, Vector2 size) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0f, 0f); rt.anchorMax = val; rt.anchorMin = val; rt.pivot = new Vector2(0f, 0f); rt.sizeDelta = size; rt.anchoredPosition = pos; ((Transform)rt).localScale = Vector3.one; } private static void AnchorBottomRight(RectTransform rt, Vector2 pos, Vector2 size) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(1f, 0f); rt.anchorMax = val; rt.anchorMin = val; rt.pivot = new Vector2(1f, 0f); rt.sizeDelta = size; rt.anchoredPosition = pos; ((Transform)rt).localScale = Vector3.one; } private static void Render() { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_0331: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) RenderFullList(); bool flag = Plugin.ShowMapValue.Value || Plugin.ShowLooseValue.Value || Plugin.ShowRoomValue.Value || Plugin.ShowMonsterList.Value; bool flag2 = Plugin.ShowInfoPanel.Value && Data.InLevel && flag; ((Component)_infoText).gameObject.SetActive(flag2); ((Component)_infoBg).gameObject.SetActive(flag2); if (flag2) { float num = Mathf.Max(6f, Plugin.PanelFontSize.Value); if (!Mathf.Approximately(((TMP_Text)_infoText).fontSize, num)) { ((TMP_Text)_infoText).fontSize = num; } Rect rect = _root.GetComponent().rect; float num2 = ((Rect)(ref rect)).height; if (num2 <= 0f) { num2 = Screen.height; } float num3 = num2 * Mathf.Clamp01(Plugin.PanelMaxHeightFraction.Value) - Plugin.PanelOffsetY.Value; int num4 = Mathf.Min(Data.Monsters.Count, Mathf.Max(1, Plugin.MonsterListMaxLines.Value)); float preferredHeight; while (true) { ((TMP_Text)_infoText).text = BuildInfoText(num4); ((TMP_Text)_infoText).ForceMeshUpdate(false, false); preferredHeight = ((TMP_Text)_infoText).preferredHeight; if (preferredHeight <= num3 || num4 <= 0) { break; } num4--; } float num5 = Mathf.Clamp(((TMP_Text)_infoText).preferredWidth + 20f, 200f, 520f); ((Graphic)_infoBg).rectTransform.sizeDelta = new Vector2(num5, Mathf.Max(40f, preferredHeight + 16f)); float num6 = Mathf.Clamp01(Plugin.PanelOpacity.Value); ((Graphic)_infoBg).color = new Color(0f, 0f, 0f, num6); ((Behaviour)_infoBg).enabled = num6 > 0f; } bool flag3 = Plugin.ShowRadar.Value && Data.InLevel && Data.HasLocal; ((Component)_radarBg).gameObject.SetActive(flag3); if (!flag3) { return; } float num7 = Mathf.Max(60f, Plugin.RadarSize.Value); if (!Mathf.Approximately(_radar.sizeDelta.x, num7)) { _radar.sizeDelta = new Vector2(num7, num7); } bool flag4 = Plugin.UseGameMap.Value && (Object)(object)_mapTex != (Object)null; ((Behaviour)_mapImage).enabled = flag4; if (flag4) { _mapImage.texture = _mapTex; Material val = (Plugin.UseMapScreenLook.Value ? _mapMat : null); if ((Object)(object)((Graphic)_mapImage).material != (Object)(object)val) { ((Graphic)_mapImage).material = val; } FitToTexture(((Graphic)_mapImage).rectTransform, _mapTex, num7); } ((Component)_centerDot).gameObject.SetActive(!flag4); if (!flag4) { ((Graphic)_centerDot).color = (Data.FollowingDeathHead ? new Color(1f, 0.35f, 0.35f) : new Color(0.3f, 1f, 0.4f)); } if (_dotsDirty) { _dotsDirty = false; if (flag4) { RenderMapDots(); } else { RenderRadarDots(); } } } private static void RenderFullList() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) bool flag = _fullListHeld && Data.InLevel; if (((Component)_fullBg).gameObject.activeSelf != flag) { ((Component)_fullBg).gameObject.SetActive(flag); } if (flag) { float num = Mathf.Max(6f, Plugin.PanelFontSize.Value); if (!Mathf.Approximately(((TMP_Text)_fullText).fontSize, num)) { ((TMP_Text)_fullText).fontSize = num; } ((TMP_Text)_fullText).text = BuildFullListText(); ((TMP_Text)_fullText).ForceMeshUpdate(false, false); Rect rect = _root.GetComponent().rect; float num2 = ((Rect)(ref rect)).height; if (num2 <= 0f) { num2 = Screen.height; } float num3 = Mathf.Clamp(((TMP_Text)_fullText).preferredWidth + 32f, 300f, 700f); float num4 = Mathf.Clamp(((TMP_Text)_fullText).preferredHeight + 24f, 80f, num2 * 0.9f); ((Graphic)_fullBg).rectTransform.sizeDelta = new Vector2(num3, num4); } } private static string BuildFullListText() { //IL_00b3: 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_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected I4, but got Unknown int num = 0; foreach (MonsterGroup monster in Data.Monsters) { num += monster.Total; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"All Monsters — {Data.Monsters.Count} types, {num} total"); if (Data.Monsters.Count == 0) { stringBuilder.Append("none on this level"); return stringBuilder.ToString(); } foreach (MonsterGroup monster2 in Data.Monsters) { string text = DiffHex(monster2.Difficulty); stringBuilder.AppendLine($"[D{monster2.Difficulty + 1}] {monster2.Name} x{monster2.Total}" + " " + F("({0} active)", monster2.Active) + ""); } return stringBuilder.ToString().TrimEnd(); } private static void FitToTexture(RectTransform rt, Texture tex, float box) { //IL_0043: 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_0051: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)tex == (Object)null) && tex.height > 0) { float num = (float)tex.width / (float)tex.height; float num2 = box; float num3 = box; if (num >= 1f) { num3 = box / num; } else { num2 = box * num; } Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(num2, num3); if (rt.sizeDelta != val) { rt.sizeDelta = val; } } } private static string BuildInfoText(int monsterLines) { //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Expected I4, but got Unknown Loc.Tick(Time.unscaledTime); StringBuilder stringBuilder = new StringBuilder(); if (Plugin.ShowMapValue.Value) { stringBuilder.AppendLine("" + T("Map Value") + " $" + Money(Data.TotalMapValue) + ""); stringBuilder.AppendLine("" + T("Goal") + " $" + Money(Data.ExtractionGoal) + " " + T("In extract") + " $" + Money(Data.CurrentHaul) + ""); } if (Plugin.ShowLooseValue.Value) { stringBuilder.AppendLine("" + T("Still out") + " $" + Money(Data.LooseValue) + " " + T("not in carts or extraction") + ""); } if (Plugin.ShowRoomValue.Value) { stringBuilder.AppendLine("" + T("This room") + " $" + Money(Data.RoomValue) + ""); } if (!Plugin.ShowMonsterList.Value) { return stringBuilder.ToString().TrimEnd(); } int num = 0; foreach (MonsterGroup monster in Data.Monsters) { num += monster.Total; } stringBuilder.AppendLine("" + F("Monsters ({0} types, {1} total)", Data.Monsters.Count, num) + ""); if (Data.Monsters.Count == 0) { stringBuilder.Append(" " + T("none on this level") + ""); return stringBuilder.ToString(); } int num2 = Mathf.Clamp(monsterLines, 0, Data.Monsters.Count); for (int i = 0; i < num2; i++) { MonsterGroup monsterGroup = Data.Monsters[i]; string text = DiffHex(monsterGroup.Difficulty); stringBuilder.AppendLine($" [D{monsterGroup.Difficulty + 1}] {monsterGroup.Name} x{monsterGroup.Total}" + " " + F("({0} active)", monsterGroup.Active) + ""); } if (Data.Monsters.Count > num2) { stringBuilder.Append(" " + F("+ {0} more type(s)…", Data.Monsters.Count - num2) + ""); } return stringBuilder.ToString(); } private static string T(string english) { return Loc.T(english); } private static string F(string english, params object[] args) { return Loc.F(english, args); } private static string Money(int amount) { try { return SemiFunc.DollarGetString(amount); } catch { return amount.ToString("n0"); } } private static void RenderMapDots() { //IL_000a: 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) float x = ((Graphic)_mapImage).rectTransform.sizeDelta.x; float y = ((Graphic)_mapImage).rectTransform.sizeDelta.y; int index = 0; foreach (Blip monsterBlip in Data.MonsterBlips) { PlaceMapDot(ref index, monsterBlip, x, y, 7f); } HideUnusedDots(index); } private static void PlaceMapDot(ref int index, Blip b, float w, float h, float dotSize) { //IL_0008: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_005c: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if (index < 96 && WorldToMapViewport(b.WorldPos, out var viewport) && !(viewport.x < 0f) && !(viewport.x > 1f) && !(viewport.y < 0f) && !(viewport.y > 1f)) { Vector2 anchoredPosition = default(Vector2); ((Vector2)(ref anchoredPosition))..ctor((viewport.x - 0.5f) * w, (viewport.y - 0.5f) * h); RawImage dot = GetDot(index++); ((Graphic)dot).color = b.Color; ((Graphic)dot).rectTransform.sizeDelta = new Vector2(dotSize, dotSize); ((Graphic)dot).rectTransform.anchoredPosition = anchoredPosition; if (!((Component)dot).gameObject.activeSelf) { ((Component)dot).gameObject.SetActive(true); } } } private static void RenderRadarDots() { //IL_0005: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) float num = _radar.sizeDelta.x * 0.5f; float num2 = Mathf.Max(1f, Plugin.RadarRange.Value); float scale = num / num2; float yaw = 0f; if (Plugin.RadarRotateWithCamera.Value && (Object)(object)Camera.main != (Object)null) { yaw = ((Component)Camera.main).transform.eulerAngles.y; } int index = 0; foreach (Blip monsterBlip in Data.MonsterBlips) { PlaceDot(ref index, monsterBlip, Data.LocalPos, scale, num, yaw, 8f); } foreach (Blip playerBlip in Data.PlayerBlips) { PlaceDot(ref index, playerBlip, Data.LocalPos, scale, num, yaw, 7f); } HideUnusedDots(index); } private static void HideUnusedDots(int usedCount) { for (int i = usedCount; i < _dots.Count; i++) { if (((Component)_dots[i]).gameObject.activeSelf) { ((Component)_dots[i]).gameObject.SetActive(false); } } } private static void PlaceDot(ref int index, Blip b, Vector3 origin, float scale, float radius, float yaw, float dotSize) { //IL_0008: 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_001b: 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_00a1: 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_00c5: 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_0087: 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) if (index < 96) { float num = b.WorldPos.x - origin.x; float num2 = b.WorldPos.z - origin.z; if (yaw != 0f) { float num3 = (0f - yaw) * (MathF.PI / 180f); float num4 = Mathf.Cos(num3); float num5 = Mathf.Sin(num3); float num6 = num * num4 - num2 * num5; float num7 = num * num5 + num2 * num4; num = num6; num2 = num7; } Vector2 anchoredPosition = default(Vector2); ((Vector2)(ref anchoredPosition))..ctor(num * scale, num2 * scale); if (((Vector2)(ref anchoredPosition)).magnitude > radius) { anchoredPosition = ((Vector2)(ref anchoredPosition)).normalized * radius; } RawImage dot = GetDot(index++); ((Graphic)dot).color = b.Color; ((Graphic)dot).rectTransform.sizeDelta = new Vector2(dotSize, dotSize); ((Graphic)dot).rectTransform.anchoredPosition = anchoredPosition; if (!((Component)dot).gameObject.activeSelf) { ((Component)dot).gameObject.SetActive(true); } } } private static RawImage GetDot(int index) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_0078: Unknown result type (might be due to invalid IL or missing references) Vector2 val2 = default(Vector2); while (_dots.Count <= index) { RawImage val = MakeRaw("Dot", (Transform)(object)_radar, Color.white); val.texture = (Texture)(object)Circle; RectTransform rectTransform = ((Graphic)val).rectTransform; RectTransform rectTransform2 = ((Graphic)val).rectTransform; ((Vector2)(ref val2))..ctor(0.5f, 0.5f); rectTransform2.anchorMax = val2; rectTransform.anchorMin = val2; ((Graphic)val).rectTransform.pivot = new Vector2(0.5f, 0.5f); ((Graphic)val).rectTransform.sizeDelta = new Vector2(8f, 8f); _dots.Add(val); } return _dots[index]; } private static string DiffHex(Difficulty d) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)d != 1) { if ((int)d == 2) { return "#FF4033"; } return "#FFE633"; } return "#FF9933"; } } internal struct Blip { public Vector3 WorldPos; public Color Color; } internal class MonsterGroup { public string Name; public Difficulty Difficulty; public int Total; public int Active; } internal class HudData { public bool InLevel; public int TotalMapValue; public int LooseValue; public int RoomValue; private static FieldInfo _bankedField; private static bool _bankedLookupDone; public int ExtractionGoal; public int CurrentHaul; private const int MaxBlips = 80; public readonly List Monsters = new List(); public readonly List MonsterBlips = new List(); public readonly List PlayerBlips = new List(); public Vector3 LocalPos; public bool FollowingDeathHead; public bool HasLocal; public bool DiagRunManagerNull; public bool DiagPlayerAvatarNull; public bool DiagEnemyDirectorNull; public bool DiagRunIsLevel; public int RawValuableCount; public int RawEnemyCount; public int RawPlayerCount; public string DiagError; private static float CartBankedValue() { if (!_bankedLookupDone) { _bankedLookupDone = true; try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { type = assemblies[i].GetType("SoloHost.CartDimension"); if (type != null) { break; } } if (type != null) { _bankedField = type.GetField("BankedTotalMirror", BindingFlags.Static | BindingFlags.Public); } Plugin.Log.LogInfo((object)((_bankedField != null) ? "[SoloHUD] Cart-banked value will be included in map value." : "[SoloHUD] SoloHost cart banking not found - map value is valuables only.")); } catch { _bankedField = null; } } try { return (_bankedField != null) ? ((float)_bankedField.GetValue(null)) : 0f; } catch { return 0f; } } public void Refresh() { //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) Monsters.Clear(); MonsterBlips.Clear(); PlayerBlips.Clear(); TotalMapValue = 0; LooseValue = 0; RoomValue = 0; ExtractionGoal = 0; CurrentHaul = 0; HasLocal = false; InLevel = false; DiagError = null; try { DiagRunManagerNull = (Object)(object)RunManager.instance == (Object)null; DiagPlayerAvatarNull = (Object)(object)PlayerAvatar.instance == (Object)null; DiagEnemyDirectorNull = (Object)(object)EnemyDirector.instance == (Object)null; ValuableObject[] array = Object.FindObjectsOfType(); RawValuableCount = array.Length; float num = 0f; float num2 = 0f; float num3 = 0f; HashSet hashSet = new HashSet(); List list = (((Object)(object)RoundDirector.instance != (Object)null) ? RoundDirector.instance.dollarHaulList : null); if (list != null) { foreach (GameObject item in list) { if ((Object)(object)item != (Object)null) { hashSet.Add(item); } } } List list2 = MyRooms(); ValuableObject[] array2 = array; foreach (ValuableObject val in array2) { if (!((Object)(object)val == (Object)null)) { float dollarValueCurrent = val.dollarValueCurrent; num += dollarValueCurrent; PhysGrabObjectImpactDetector val2 = (((Object)(object)val.physGrabObject != (Object)null) ? val.physGrabObject.impactDetector : null); if ((!((Object)(object)val2 != (Object)null) || !val2.inCart) && !hashSet.Contains(((Component)val).gameObject)) { num2 += dollarValueCurrent; } if (list2 != null && SharesRoom(val.roomVolumeCheck, list2)) { num3 += dollarValueCurrent; } } } LooseValue = Mathf.RoundToInt(num2); RoomValue = Mathf.RoundToInt(num3); TotalMapValue = Mathf.RoundToInt(num + CartBankedValue()); RawEnemyCount = ((!DiagEnemyDirectorNull && EnemyDirector.instance.enemiesSpawned != null) ? EnemyDirector.instance.enemiesSpawned.Count : 0); GameDirector instance = GameDirector.instance; RawPlayerCount = (((Object)(object)instance != (Object)null && instance.PlayerList != null) ? instance.PlayerList.Count : 0); if (!DiagRunManagerNull) { try { DiagRunIsLevel = SemiFunc.RunIsLevel(); } catch (Exception ex) { DiagRunIsLevel = false; DiagError = "RunIsLevel: " + ex.Message; } } else { DiagRunIsLevel = false; } if (!DiagRunManagerNull && !DiagPlayerAvatarNull && DiagRunIsLevel) { InLevel = true; LocalPos = LocalViewPosition(PlayerAvatar.instance); HasLocal = true; RefreshMonsters(); RefreshPlayers(); RoundDirector instance2 = RoundDirector.instance; if ((Object)(object)instance2 != (Object)null) { CurrentHaul = instance2.currentHaul; ExtractionGoal = instance2.haulGoal; } } } catch (Exception ex2) { InLevel = false; DiagError = ex2.GetType().Name + ": " + ex2.Message; Plugin.Log.LogWarning((object)("SoloHUD scan error: " + DiagError)); } } private static List MyRooms() { PlayerAvatar instance = PlayerAvatar.instance; if ((Object)(object)instance == (Object)null) { return null; } RoomVolumeCheck roomVolumeCheck = instance.RoomVolumeCheck; if ((instance.isDisabled || instance.deadSet) && (Object)(object)instance.playerDeathHead != (Object)null && (Object)(object)instance.playerDeathHead.physGrabObject != (Object)null && (Object)(object)instance.playerDeathHead.physGrabObject.roomVolumeCheck != (Object)null) { roomVolumeCheck = instance.playerDeathHead.physGrabObject.roomVolumeCheck; } if (!((Object)(object)roomVolumeCheck != (Object)null)) { return null; } return roomVolumeCheck.CurrentRooms; } private static bool SharesRoom(RoomVolumeCheck check, List rooms) { if ((Object)(object)check == (Object)null || check.CurrentRooms == null || rooms.Count == 0) { return false; } foreach (RoomVolume currentRoom in check.CurrentRooms) { if ((Object)(object)currentRoom != (Object)null && rooms.Contains(currentRoom)) { return true; } } return false; } private Vector3 LocalViewPosition(PlayerAvatar me) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) FollowingDeathHead = false; if ((Object)(object)me == (Object)null) { return Vector3.zero; } bool num = me.isDisabled || me.deadSet; PlayerDeathHead playerDeathHead = me.playerDeathHead; if (num && (Object)(object)playerDeathHead != (Object)null) { PhysGrabObject physGrabObject = playerDeathHead.physGrabObject; FollowingDeathHead = true; if (!((Object)(object)physGrabObject != (Object)null)) { return ((Component)playerDeathHead).transform.position; } return ((Component)physGrabObject).transform.position; } return ((Component)me).transform.position; } private void RefreshMonsters() { //IL_007a: 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_0103: 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_0110: 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) //IL_011a: Unknown result type (might be due to invalid IL or missing references) EnemyDirector instance = EnemyDirector.instance; if ((Object)(object)instance == (Object)null || instance.enemiesSpawned == null) { return; } Dictionary dictionary = new Dictionary(); foreach (EnemyParent item in instance.enemiesSpawned) { if (!((Object)(object)item == (Object)null)) { string text = (string.IsNullOrEmpty(item.enemyName) ? "Unknown" : item.enemyName); if (!dictionary.TryGetValue(text, out var value)) { value = (dictionary[text] = new MonsterGroup { Name = text, Difficulty = item.difficulty }); Monsters.Add(value); } value.Total++; if (item.Spawned) { value.Active++; } if (item.Spawned && (Object)(object)item.Enemy != (Object)null && MonsterBlips.Count < 80) { MonsterBlips.Add(new Blip { WorldPos = ((Component)item.Enemy).transform.position, Color = DifficultyColor(item.difficulty) }); } } } Monsters.Sort(delegate(MonsterGroup a, MonsterGroup b) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected I4, but got Unknown //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected I4, but got Unknown int num = ((int)b.Difficulty).CompareTo((int)a.Difficulty); return (num == 0) ? b.Total.CompareTo(a.Total) : num; }); } private void RefreshPlayers() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) GameDirector instance = GameDirector.instance; if ((Object)(object)instance == (Object)null || instance.PlayerList == null) { return; } Color color = default(Color); foreach (PlayerAvatar player in instance.PlayerList) { if (!((Object)(object)player == (Object)null) && !player.isDisabled) { if (player.deadSet) { ((Color)(ref color))..ctor(0.6f, 0.6f, 0.6f); } else if (player.isLocal) { ((Color)(ref color))..ctor(0.3f, 1f, 0.4f); } else { ((Color)(ref color))..ctor(0.35f, 0.8f, 1f); } PlayerBlips.Add(new Blip { WorldPos = ((Component)player).transform.position, Color = color }); } } } internal static Color DifficultyColor(Difficulty d) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0041: 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) if ((int)d != 1) { if ((int)d == 2) { return new Color(1f, 0.25f, 0.2f); } return new Color(1f, 0.9f, 0.2f); } return new Color(1f, 0.6f, 0.1f); } } internal static class HudSettings { [HarmonyPatch(typeof(MenuPageSettingsPage), "Start")] internal static class GameplayPagePatch { private static void Postfix(MenuPageSettingsPage __instance) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 if (!Plugin.Ready || (Object)(object)__instance == (Object)null || !Plugin.ShowInGameSettings.Value || (int)__instance.settingType != 1) { return; } try { ((MonoBehaviour)__instance).StartCoroutine(AddTo(__instance)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SoloHUD] Gameplay page hook failed: " + ex.Message)); } } } [HarmonyPatch(typeof(MenuPageSettingsControls), "Start")] internal static class ControlsPagePatch { private static void Postfix(MenuPageSettingsControls __instance) { if (!Plugin.Ready || (Object)(object)__instance == (Object)null || !Plugin.ShowInGameSettings.Value) { return; } try { ((MonoBehaviour)__instance).StartCoroutine(HudKeyRow.AddTo(__instance)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SoloHUD] Controls page hook failed: " + ex.Message)); } } } private const string Tag = "SoloHUD Row"; private const string Prefix = "HUD "; private static IEnumerator AddTo(MenuPageSettingsPage page) { yield return null; Loc.Tick(Time.unscaledTime); if ((Object)(object)page == (Object)null || ((Component)page).GetComponentsInChildren(true).Any((Transform t) => (Object)(object)t != (Object)null && ((Object)t).name == "SoloHUD Row")) { yield break; } MenuSlider[] componentsInChildren = ((Component)page).GetComponentsInChildren(true); MenuSlider sliderTemplate = ((IEnumerable)componentsInChildren).FirstOrDefault((Func)((MenuSlider s) => (Object)(object)s != (Object)null && !s.hasCustomOptions)) ?? componentsInChildren.FirstOrDefault(); MenuTwoOptions toggleTemplate = ((Component)page).GetComponentsInChildren(true).FirstOrDefault(); if ((Object)(object)sliderTemplate == (Object)null || (Object)(object)toggleTemplate == (Object)null) { Plugin.Log.LogWarning((object)($"[SoloHUD] Gameplay page has no row to copy (slider={(Object)(object)sliderTemplate != (Object)null}, " + $"toggle={(Object)(object)toggleTemplate != (Object)null}) — leaving it alone.")); yield break; } List list = (from t in ((Component)page).GetComponentsInChildren(true) where (Object)(object)t != (Object)null && ((Object)(object)((Component)t).GetComponent() != (Object)null || (Object)(object)((Component)t).GetComponent() != (Object)null) orderby t.localPosition.y descending select t).ToList(); Transform val = list[list.Count - 1]; Transform parent = val.parent; float gap = ((list.Count > 1) ? Mathf.Abs(list[0].localPosition.y - list[1].localPosition.y) : 34f); if (gap < 1f) { gap = 34f; } float y = val.localPosition.y; int added = 0; Heading("SOLOHUD", major: true); Heading("Info Panel", major: false); Toggle("Info Panel", Plugin.ShowInfoPanel); Toggle("Map Value", Plugin.ShowMapValue); Toggle("Still Out Value", Plugin.ShowLooseValue); Toggle("Room Value", Plugin.ShowRoomValue); Toggle("Monster List", Plugin.ShowMonsterList); Slider("Monster Lines", Steps(1, 1, 30, ""), () => Plugin.MonsterListMaxLines.Value - 1, delegate(int i) { Plugin.MonsterListMaxLines.Value = i + 1; }); Slider("Panel Text Size", Steps(8, 1, 23, ""), () => Mathf.RoundToInt(Plugin.PanelFontSize.Value) - 8, delegate(int i) { Plugin.PanelFontSize.Value = 8 + i; }); Slider("Panel Background", Steps(0, 10, 11, "%"), () => Mathf.RoundToInt(Plugin.PanelOpacity.Value * 10f), delegate(int i) { Plugin.PanelOpacity.Value = (float)i / 10f; }); Heading("Minimap", major: false); Toggle("Minimap", Plugin.ShowRadar); Slider("Minimap Size", Steps(60, 20, 13, ""), () => Mathf.RoundToInt((Plugin.RadarSize.Value - 60f) / 20f), delegate(int i) { Plugin.RadarSize.Value = 60f + (float)i * 20f; }); Slider("Minimap Range", Steps(10, 5, 19, "m"), () => Mathf.RoundToInt((Plugin.RadarRange.Value - 10f) / 5f), delegate(int i) { Plugin.RadarRange.Value = 10f + (float)i * 5f; }); Toggle("Minimap Real Map", Plugin.UseGameMap); Toggle("Minimap Screen Look", Plugin.UseMapScreenLook); Toggle("Hide With Tab Map", Plugin.HideWhileMapOpen); MenuScrollBox[] componentsInChildren2 = ((Component)page).GetComponentsInChildren(true); foreach (MenuScrollBox val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null)) { try { val2.RecalculateScrollHeight(); } catch { } } } Plugin.Log.LogInfo((object)$"[SoloHUD] Added {added} row(s) to the game's Gameplay settings."); void Heading(string text, bool major) { y -= (major ? (gap * 1.5f) : gap); Header((Component)(object)toggleTemplate, TitleOf((Component)(object)toggleTemplate), parent, y, text, major, "SoloHUD Row"); } void Slider(string name, string[] labels, Func read, Action write) { y -= gap; if (AddSlider(sliderTemplate, parent, y, name, labels, read, write)) { added++; } } void Toggle(string name, ConfigEntry entry) { y -= gap; if (AddToggle(toggleTemplate, parent, y, name, () => entry.Value, delegate(bool v) { entry.Value = v; })) { added++; } } } internal static GameObject CloneDormant(Component template, Transform parent, float y, string tag) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0081: Unknown result type (might be due to invalid IL or missing references) GameObject gameObject = template.gameObject; bool activeSelf = gameObject.activeSelf; gameObject.SetActive(false); GameObject val; try { val = Object.Instantiate(gameObject, parent); } finally { gameObject.SetActive(activeSelf); } ((Object)val).name = tag; val.transform.localPosition = new Vector3(template.transform.localPosition.x, y, template.transform.localPosition.z); val.transform.localScale = template.transform.localScale; val.transform.localRotation = template.transform.localRotation; MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren(true); foreach (MonoBehaviour val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && ((object)val2).GetType().Name.IndexOf("Localize", StringComparison.OrdinalIgnoreCase) >= 0) { Object.DestroyImmediate((Object)(object)val2); } } return val; } private static bool AddSlider(MenuSlider template, Transform parent, float y, string name, string[] labels, Func read, Action write) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown try { GameObject val = CloneDormant((Component)(object)template, parent, y, "SoloHUD Row"); MenuSlider component = val.GetComponent(); if ((Object)(object)component == (Object)null) { Object.DestroyImmediate((Object)(object)val); return false; } Strip(val); Strip(val); Strip(val); component.onChange = new UnityEvent(); component.customOptions = new List(); component.hasCustomOptions = false; component.hasCustomValues = false; component.hasBar = true; component.wrapAround = false; component.buttonSegmentJump = 1; component.pointerSegmentJump = 1; component.startValue = 0; component.endValue = labels.Length - 1; component.stringAtStartOfValue = ""; component.stringAtEndOfValue = ""; component.elementName = "HUD " + Loc.T(name); int num = Mathf.Clamp(read(), 0, labels.Length - 1); component.settingsValue = (float)num / (float)(labels.Length - 1); PruneClicks(val, (Component)(object)component, "OnIncrease", "OnDecrease"); val.AddComponent().Bind(component, "HUD " + Loc.T(name), labels, write); val.SetActive(true); return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SoloHUD] Couldn't add the '" + name + "' row: " + ex.Message)); return false; } } private static bool AddToggle(MenuTwoOptions template, Transform parent, float y, string name, Func read, Action write) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown try { GameObject val = CloneDormant((Component)(object)template, parent, y, "SoloHUD Row"); MenuTwoOptions two = val.GetComponent(); if ((Object)(object)two == (Object)null) { Object.DestroyImmediate((Object)(object)val); return false; } two.onOption1 = new UnityEvent(); two.onOption2 = new UnityEvent(); two.fetchSetting = new UnityEvent(); two.customEvents = true; two.customFetch = true; two.settingSet = false; two.settingName = "HUD " + Loc.T(name); two.fetchSetting.AddListener((UnityAction)delegate { try { two.startSettingFetch = read(); } catch { } }); two.onOption1.AddListener((UnityAction)delegate { try { write(obj: true); } catch { } }); two.onOption2.AddListener((UnityAction)delegate { try { write(obj: false); } catch { } }); PruneClicks(val, (Component)(object)two, "OnOption1", "OnOption2"); val.AddComponent().Bind(two, "HUD " + Loc.T(name)); val.SetActive(true); return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SoloHUD] Couldn't add the '" + name + "' row: " + ex.Message)); return false; } } internal static TextMeshProUGUI TitleOf(Component row) { HashSet exclude = new HashSet(); MenuTwoOptions val = (MenuTwoOptions)(object)((row is MenuTwoOptions) ? row : null); if (val != null) { exclude.Add(val.option1TextMesh); exclude.Add(val.option2TextMesh); } MenuBigButton component = row.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.menuButton != (Object)null) { exclude.Add(component.menuButton.buttonText); } return ((IEnumerable)row.GetComponentsInChildren(true)).FirstOrDefault((Func)((TextMeshProUGUI t) => (Object)(object)t != (Object)null && !exclude.Contains(t))); } internal static void Header(Component row, TextMeshProUGUI title, Transform parent, float y, string text, bool major, string tag) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_012c: 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_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_015e: 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_0170: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0289: 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) if ((Object)(object)row == (Object)null || (Object)(object)title == (Object)null || (Object)(object)parent == (Object)null) { return; } try { Vector3 val = parent.InverseTransformPoint(((TMP_Text)title).transform.position); float x = val.x; float num = val.y - row.transform.localPosition.y; GameObject val2 = Object.Instantiate(((Component)title).gameObject, parent); ((Object)val2).name = tag; foreach (Transform item in ((IEnumerable)val2.transform).Cast().ToList()) { Object.DestroyImmediate((Object)(object)((Component)item).gameObject); } Component[] components = val2.GetComponents(); foreach (Component val3 in components) { if (!((Object)(object)val3 == (Object)null) && !(val3 is Transform) && !(val3 is TextMeshProUGUI) && !(val3 is CanvasRenderer)) { Object.DestroyImmediate((Object)(object)val3); } } val2.transform.localPosition = new Vector3(x, y + num, val.z); val2.transform.localRotation = ((((TMP_Text)title).transform.rotation == Quaternion.identity) ? Quaternion.identity : (Quaternion.Inverse(parent.rotation) * ((TMP_Text)title).transform.rotation)); val2.transform.localScale = (Vector3)((((TMP_Text)title).transform.lossyScale.x > 0f && parent.lossyScale.x > 0f) ? new Vector3(((TMP_Text)title).transform.lossyScale.x / parent.lossyScale.x, ((TMP_Text)title).transform.lossyScale.y / parent.lossyScale.y, 1f) : Vector3.one); TextMeshProUGUI component = val2.GetComponent(); text = Loc.T(text); ((TMP_Text)component).text = (major ? text : ("— " + text + " —")); ((TMP_Text)component).fontStyle = (FontStyles)1; ((TMP_Text)component).enableWordWrapping = false; ((TMP_Text)component).overflowMode = (TextOverflowModes)0; if (major) { ((TMP_Text)component).fontSize = ((TMP_Text)title).fontSize * 1.25f; ((Graphic)component).color = new Color(0.68f, 0.84f, 0.51f, 1f); } else { ((Graphic)component).color = new Color(((Graphic)component).color.r, ((Graphic)component).color.g, ((Graphic)component).color.b, ((Graphic)component).color.a * 0.75f); } val2.SetActive(true); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SoloHUD] Couldn't add the '" + text + "' heading: " + ex.Message)); } } private static void PruneClicks(GameObject clone, Component keep, params string[] keepMethods) { MenuButton[] componentsInChildren = clone.GetComponentsInChildren(true); foreach (MenuButton val in componentsInChildren) { ButtonClickedEvent val2 = (((Object)(object)val != (Object)null && (Object)(object)val.button != (Object)null) ? val.button.onClick : null); if (val2 == null) { continue; } for (int j = 0; j < ((UnityEventBase)val2).GetPersistentEventCount(); j++) { if ((object)((UnityEventBase)val2).GetPersistentTarget(j) != keep || Array.IndexOf(keepMethods, ((UnityEventBase)val2).GetPersistentMethodName(j)) < 0) { ((UnityEventBase)val2).SetPersistentListenerState(j, (UnityEventCallState)0); } } } } private static void Strip(GameObject go) where T : Component { T[] componentsInChildren = go.GetComponentsInChildren(true); foreach (T val in componentsInChildren) { if ((Object)(object)val != (Object)null) { Object.DestroyImmediate((Object)(object)val); } } } private static string[] Steps(int first, int step, int count, string suffix) { string[] array = new string[count]; for (int i = 0; i < count; i++) { array[i] = first + i * step + suffix; } return array; } } internal sealed class HudSliderRow : MonoBehaviour { private MenuSlider _slider; private string _name; private string[] _labels; private Action _write; private int _shown = -1; public void Bind(MenuSlider slider, string name, string[] labels, Action write) { _slider = slider; _name = name; _labels = labels; _write = write; } private void LateUpdate() { if ((Object)(object)_slider == (Object)null || _labels == null) { return; } if ((Object)(object)_slider.elementNameText != (Object)null && ((TMP_Text)_slider.elementNameText).text != _name) { ((TMP_Text)_slider.elementNameText).text = _name; } int num = Mathf.Clamp(_slider.currentValue, 0, _labels.Length - 1); if (_shown < 0) { _shown = num; try { _slider.SetBarScaleInstant(); } catch { } } else if (num != _shown) { _shown = num; try { _write(num); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SoloHUD] '" + _name + "' failed to apply: " + ex.Message)); } } string text = _labels[num]; if ((Object)(object)_slider.segmentText != (Object)null && ((TMP_Text)_slider.segmentText).text != text) { ((TMP_Text)_slider.segmentText).text = text; } if ((Object)(object)_slider.segmentMaskText != (Object)null && ((TMP_Text)_slider.segmentMaskText).text != text) { ((TMP_Text)_slider.segmentMaskText).text = text; } } } internal sealed class HudToggleRow : MonoBehaviour { private string _name; private TextMeshProUGUI[] _titles = (TextMeshProUGUI[])(object)new TextMeshProUGUI[0]; public void Bind(MenuTwoOptions two, string name) { _name = name; _titles = (from t in ((Component)two).GetComponentsInChildren(true) where (Object)(object)t != (Object)null && (Object)(object)t != (Object)(object)two.option1TextMesh && (Object)(object)t != (Object)(object)two.option2TextMesh select t).ToArray(); LateUpdate(); } private void LateUpdate() { TextMeshProUGUI[] titles = _titles; foreach (TextMeshProUGUI val in titles) { if ((Object)(object)val != (Object)null && ((TMP_Text)val).text != _name) { ((TMP_Text)val).text = _name; } } } } internal sealed class HudKeyRow : MonoBehaviour { private const string Tag = "SoloHUD Key Row"; private MenuBigButton _big; private ConfigEntry _entry; private string _title; private TextMeshProUGUI[] _titles = (TextMeshProUGUI[])(object)new TextMeshProUGUI[0]; private bool _capturing; private float _armedAt; public void Bind(MenuBigButton big, ConfigEntry entry, string title) { _big = big; _entry = entry; _title = title; TextMeshProUGUI keyText = (((Object)(object)big.menuButton != (Object)null) ? big.menuButton.buttonText : null); _title = Loc.T(_title); _titles = (from t in ((Component)big).GetComponentsInChildren(true) where (Object)(object)t != (Object)null && (Object)(object)t != (Object)(object)keyText select t).ToArray(); Show(); } public void BeginCapture() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!_capturing) { _capturing = true; _armedAt = Time.unscaledTime; if ((Object)(object)_big != (Object)null) { _big.state = (State)1; } SetText("..."); } } private void Update() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Invalid comparison between Unknown and I4 //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Invalid comparison between Unknown and I4 //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Invalid comparison between Unknown and I4 //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_big != (Object)null) { _big.buttonTitle = _title; } TextMeshProUGUI[] titles = _titles; foreach (TextMeshProUGUI val in titles) { if ((Object)(object)val != (Object)null && ((TMP_Text)val).text != _title) { ((TMP_Text)val).text = _title; } } if (!_capturing) { Show(); return; } Keyboard current = Keyboard.current; if (current == null) { Finish(); } else { if (Time.unscaledTime - _armedAt < 0.1f) { return; } Enumerator enumerator = current.allKeys.GetEnumerator(); try { while (enumerator.MoveNext()) { KeyControl current2 = enumerator.Current; if (current2 != null && ((ButtonControl)current2).wasPressedThisFrame) { if ((int)current2.keyCode == 60) { Finish(); break; } _entry.Value = (Key)(((int)current2.keyCode != 65 && (int)current2.keyCode != 71) ? ((int)current2.keyCode) : 0); Plugin.Log.LogInfo((object)$"[SoloHUD] {_title} key set to {_entry.Value} from the game's settings."); Finish(); break; } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } } private void Finish() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) _capturing = false; if ((Object)(object)_big != (Object)null) { _big.state = (State)0; } Show(); } private void Show() { //IL_0007: 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_0019: Unknown result type (might be due to invalid IL or missing references) SetText(((int)_entry.Value == 0) ? "OFF" : ((object)_entry.Value/*cast due to .constrained prefix*/).ToString()); } private void SetText(string text) { if (!((Object)(object)_big == (Object)null)) { _big.buttonName = text; if ((Object)(object)_big.menuButton != (Object)null && (Object)(object)_big.menuButton.buttonText != (Object)null) { ((TMP_Text)_big.menuButton.buttonText).text = text; } } } internal static IEnumerator AddTo(MenuPageSettingsControls page) { yield return null; yield return null; if ((Object)(object)page == (Object)null || ((Component)page).GetComponentsInChildren(true).Any((Transform t) => (Object)(object)t != (Object)null && ((Object)t).name == "SoloHUD Key Row")) { yield break; } MenuKeybind val = ((Component)page).GetComponentsInChildren(true).FirstOrDefault(); if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"[SoloHUD] No keybind row to copy — leaving the Controls page alone."); yield break; } Transform parent = ((Component)val).transform.parent; List list = (from b in ((Component)parent).GetComponentsInChildren(true) where (Object)(object)b != (Object)null && (Object)(object)((Component)b).transform.parent == (Object)(object)parent select ((Component)b).transform into t orderby t.localPosition.y descending select t).ToList(); float num = ((list.Count > 1) ? Mathf.Abs(list[0].localPosition.y - list[1].localPosition.y) : 60f); if (num < 1f) { num = 60f; } float num2 = ((list.Count > 0) ? list[list.Count - 1].localPosition.y : ((Component)val).transform.localPosition.y); num2 -= num; HudSettings.Header((Component)(object)val, HudSettings.TitleOf((Component)(object)val), parent, num2, "SOLOHUD", major: true, "SoloHUD Key Row"); num2 -= num; Add(val, parent, num2, Plugin.ToggleKey, "SoloHUD Show/Hide"); num2 -= num; Add(val, parent, num2, Plugin.MonsterListKey, "SoloHUD Monster List"); MenuScrollBox componentInChildren = ((Component)page).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { try { componentInChildren.RecalculateScrollHeight(); } catch { } } Plugin.Log.LogInfo((object)"[SoloHUD] Added its keys to the game's Controls settings."); } private static void Add(MenuKeybind template, Transform parent, float y, ConfigEntry entry, string title) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown try { GameObject val = HudSettings.CloneDormant((Component)(object)template, parent, y, "SoloHUD Key Row"); MenuKeybind component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } MenuBigButton component2 = val.GetComponent(); if ((Object)(object)component2 == (Object)null) { Object.DestroyImmediate((Object)(object)val); return; } HudKeyRow hudKeyRow = val.AddComponent(); hudKeyRow.Bind(component2, entry, title); Button val2 = (((Object)(object)component2.menuButton != (Object)null) ? component2.menuButton.button : null); if ((Object)(object)val2 != (Object)null) { ((UnityEvent)val2.onClick).AddListener(new UnityAction(hudKeyRow.BeginCapture)); } val.SetActive(true); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SoloHUD] Couldn't add the '" + title + "' key row: " + ex.Message)); } } } [BepInPlugin("com.solo.repo.solohud", "SoloHUD", "1.14.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "com.solo.repo.solohud"; public const string Name = "SoloHUD"; public const string Version = "1.14.0"; internal static ManualLogSource Log; internal static bool Ready; internal static Plugin Instance; internal static ConfigEntry ToggleKey; internal static ConfigEntry MonsterListKey; internal static ConfigEntry HideWhileMapOpen; internal static ConfigEntry ShowInfoPanel; internal static ConfigEntry ShowRadar; internal static ConfigEntry RadarRange; internal static ConfigEntry RadarSize; internal static ConfigEntry RadarRotateWithCamera; internal static ConfigEntry UseGameMap; internal static ConfigEntry PanelOpacity; internal static ConfigEntry PanelOffsetX; internal static ConfigEntry PanelOffsetY; internal static ConfigEntry UseMapScreenLook; internal static ConfigEntry MonsterListMaxLines; internal static ConfigEntry PanelFontSize; internal static ConfigEntry PanelMaxHeightFraction; internal static ConfigEntry ShowMapValue; internal static ConfigEntry ShowLooseValue; internal static ConfigEntry ShowRoomValue; internal static ConfigEntry ShowMonsterList; internal static ConfigEntry ShowInGameSettings; internal static ConfigEntry DumpTranslationList; private void Awake() { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Expected O, but got Unknown //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Expected O, but got Unknown //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; ToggleKey = ((BaseUnityPlugin)this).Config.Bind("General", "ToggleKey", (Key)94, "Key to show/hide the whole overlay (Unity Input System key name). None switches it off. Also rebindable from the game's Controls settings."); MonsterListKey = ((BaseUnityPlugin)this).Config.Bind("General", "MonsterListKey", (Key)32, "Hold this key to show the FULL monster list (every type, uncapped), like a stat screen. None switches it off. Also rebindable from the game's Controls settings."); HideWhileMapOpen = ((BaseUnityPlugin)this).Config.Bind("General", "HideWhileMapOpen", true, "Hide the overlay while you hold the map (Tab), so it doesn't cover the game's upgrade/stat screen."); ShowInfoPanel = ((BaseUnityPlugin)this).Config.Bind("General", "ShowInfoPanel", true, "Show the top-left info panel (map value + monster roster)."); ShowRadar = ((BaseUnityPlugin)this).Config.Bind("General", "ShowRadar", true, "Show the radar with live monster and player positions."); PanelOpacity = ((BaseUnityPlugin)this).Config.Bind("General", "PanelOpacity", 0f, new ConfigDescription("Darkness of the plate behind the info panel. 0 = fully transparent (text only).", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); PanelOffsetX = ((BaseUnityPlugin)this).Config.Bind("General", "PanelOffsetX", 16f, "Info panel distance from the left edge, in pixels."); PanelOffsetY = ((BaseUnityPlugin)this).Config.Bind("General", "PanelOffsetY", 130f, "Info panel distance from the bottom edge. The default clears the game's mission text."); MonsterListMaxLines = ((BaseUnityPlugin)this).Config.Bind("General", "MonsterListMaxLines", 8, new ConfigDescription("Max monster TYPES listed in the panel before it collapses to '+N more'. The panel also auto-shrinks this further if needed to stay off the top HUD.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 30), Array.Empty())); PanelFontSize = ((BaseUnityPlugin)this).Config.Bind("General", "PanelFontSize", 14f, new ConfigDescription("Font size of the info panel. Lower = more compact / more monsters fit.", (AcceptableValueBase)(object)new AcceptableValueRange(6f, 40f), Array.Empty())); PanelMaxHeightFraction = ((BaseUnityPlugin)this).Config.Bind("General", "PanelMaxHeightFraction", 0.55f, new ConfigDescription("Tallest the info panel may grow, as a fraction of screen height. Stops it from reaching the game's health/energy HUD in the top-left; excess monsters collapse to '+N more'.", (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 0.95f), Array.Empty())); ShowMapValue = ((BaseUnityPlugin)this).Config.Bind("Values", "ShowMapValue", true, "Show the total value of every valuable in the level, carts and extractions included."); ShowLooseValue = ((BaseUnityPlugin)this).Config.Bind("Values", "ShowLooseValue", true, "Show the value still out there to collect: valuables not riding in a cart and not already in an extraction point."); ShowRoomValue = ((BaseUnityPlugin)this).Config.Bind("Values", "ShowRoomValue", true, "Show the value of the valuables in the room you are standing in."); ShowMonsterList = ((BaseUnityPlugin)this).Config.Bind("General", "ShowMonsterList", true, "Show the monster roster in the info panel. The full list on the hold key works either way."); ShowInGameSettings = ((BaseUnityPlugin)this).Config.Bind("General", "ShowInGameSettings", true, "Add SoloHUD's settings to the game's own Gameplay settings page, and its two keys to the Controls page, so everything can be changed without leaving the game."); RadarRange = ((BaseUnityPlugin)this).Config.Bind("Radar", "RangeMeters", 40f, "World distance from you that the radar edge represents. Lower = more zoomed in."); RadarSize = ((BaseUnityPlugin)this).Config.Bind("Radar", "SizePixels", 120f, "Minimap size in pixels (at 1080p reference scale). Applies live, no restart needed."); RadarRotateWithCamera = ((BaseUnityPlugin)this).Config.Bind("Radar", "RotateWithCamera", true, "Only used by the fallback dot radar: if true, 'up' is the direction you're facing."); UseGameMap = ((BaseUnityPlugin)this).Config.Bind("Radar", "UseGameMap", true, "Show the real Tab map in the minimap by keeping the game's map render alive. Set false to fall back to the simple dot radar."); UseMapScreenLook = ((BaseUnityPlugin)this).Config.Bind("Radar", "UseMapScreenLook", true, "Draw the minimap through the map device's own screen shader, so it gets the same green CRT tint and scanlines. Set false if the minimap renders wrong."); DumpTranslationList = ((BaseUnityPlugin)this).Config.Bind("General", "WriteTranslationList", false, "Write every line this mod shows to lang/_english.txt as you play, ready to be copied into a new language file. For translating; off otherwise."); Loc.Init("SoloHUD", ((BaseUnityPlugin)this).Info.Location, (Action)Log.LogInfo, (Action)Log.LogWarning, DumpTranslationList.Value); Ready = true; Harmony val = new Harmony("com.solo.repo.solohud"); val.PatchAll(typeof(Plugin).Assembly); int num = 0; foreach (MethodBase patchedMethod in val.GetPatchedMethods()) { num++; Log.LogInfo((object)("[SoloHUD] patched: " + patchedMethod.DeclaringType?.Name + "." + patchedMethod.Name)); } Log.LogInfo((object)string.Format("{0} v{1} loaded; Harmony applied {2} patches.", "SoloHUD", "1.14.0", num)); if (num == 0) { Log.LogError((object)"[SoloHUD] PatchAll applied ZERO patches — hooks will never fire!"); } } } [HarmonyPatch(typeof(RenderTextureMain), "Update")] internal static class RenderTextureMainUpdatePatch { private static void Postfix() { HudController.Tick(); } } [HarmonyPatch(typeof(RoundDirector), "Update")] internal static class RoundDirectorUpdatePatch { private static void Postfix() { HudController.Tick(); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { internal IgnoresAccessChecksToAttribute(string assemblyName) { } } }