using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("WhereIsMyAmulet")] [assembly: AssemblyDescription("Shows the distance to dropped amulet fragments in PEAK.")] [assembly: AssemblyProduct("WhereIsMyAmulet")] [assembly: ComVisible(false)] [assembly: Guid("ce0f5e2c-08a1-4f5f-8da4-a91c5c43a5a7")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [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 WhereIsMyAmulet { [BepInPlugin("com.wuyachiyu.WhereIsMyAmulet", "WhereIsMyAmulet", "1.0.0")] public sealed class WhereIsMyAmuletPlugin : BaseUnityPlugin { public const string PluginGuid = "com.wuyachiyu.WhereIsMyAmulet"; public const string PluginName = "WhereIsMyAmulet"; public const string PluginVersion = "1.0.0"; private readonly Dictionary _labels = new Dictionary(); private ManualLogSource _log; private Canvas _canvas; private TMP_FontAsset _font; private bool _loggedDiscovery; private ConfigEntry _enabled; private ConfigEntry _scanKey; private ConfigEntry _maxDistance; private ConfigEntry _fontSize; private ConfigEntry _showOffscreen; private void Awake() { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) _log = ((BaseUnityPlugin)this).Logger; _enabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Show labels for dropped amulet fragments."); _scanKey = ((BaseUnityPlugin)this).Config.Bind("General", "ScanKey", (KeyCode)99, "Press this key to scan for dropped amulet fragments."); _maxDistance = ((BaseUnityPlugin)this).Config.Bind("Display", "MaxDistance", 500f, "Maximum distance in metres for a label. Set to 0 for unlimited."); _fontSize = ((BaseUnityPlugin)this).Config.Bind("Display", "FontSize", 22f, "Distance label font size."); _showOffscreen = ((BaseUnityPlugin)this).Config.Bind("Display", "ShowOffscreenDirection", true, "Show a direction marker on the screen edge for offscreen fragments."); CreateCanvas(); _log.LogInfo((object)("WhereIsMyAmulet v1.0.0 loaded. Press " + ((object)_scanKey.Value/*cast due to .constrained prefix*/).ToString() + " to scan for dropped fragments.")); } private void Update() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!_enabled.Value) { ClearLabels(); return; } if (Input.GetKeyDown(_scanKey.Value)) { ScanItems(); } foreach (AmuletLabel item in _labels.Values.ToList()) { if (item.IsValid) { item.Update(Camera.main, _maxDistance.Value, _showOffscreen.Value); } else { RemoveLabel(item.InstanceId); } } } private void OnDestroy() { ClearLabels(); if ((Object)(object)_canvas != (Object)null) { Object.Destroy((Object)(object)((Component)_canvas).gameObject); } } private void CreateCanvas() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("WhereIsMyAmuletCanvas"); Object.DontDestroyOnLoad((Object)(object)val); val.layer = 5; _canvas = val.AddComponent(); _canvas.renderMode = (RenderMode)0; _canvas.sortingOrder = 32700; CanvasScaler obj = val.AddComponent(); obj.uiScaleMode = (ScaleMode)1; obj.referenceResolution = new Vector2(1920f, 1080f); val.AddComponent(); _font = FindFont(); } private void ScanItems() { //IL_006f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_font == (Object)null) { _font = FindFont(); } Item[] array = Object.FindObjectsByType((FindObjectsSortMode)0); HashSet hashSet = new HashSet(); Item[] array2 = array; Backpack backpack = default(Backpack); foreach (Item item in array2) { if ((Object)(object)item == (Object)null || !((Component)item).gameObject.activeInHierarchy || (int)item.itemState != 0) { continue; } if (Matches(item)) { int instanceID = ((Object)((Component)item).gameObject).GetInstanceID(); hashSet.Add(instanceID); AddLabel(instanceID, ((Component)item).transform, "Amulet", () => (Object)(object)item != (Object)null && ((Component)item).gameObject.activeInHierarchy && (int)item.itemState == 0); } ref Backpack reference = ref backpack; Item obj = item; reference = (Backpack)(object)((obj is Backpack) ? obj : null); if ((Object)(object)backpack != (Object)null && HasAmulet(((Item)backpack).data)) { int instanceID2 = ((Object)((Component)backpack).gameObject).GetInstanceID(); hashSet.Add(instanceID2); AddLabel(instanceID2, ((Component)backpack).transform, "Backpack\nAmulet", () => (Object)(object)backpack != (Object)null && ((Component)backpack).gameObject.activeInHierarchy && (int)((Item)backpack).itemState == 0 && HasAmulet(((Item)backpack).data)); } } foreach (int item2 in _labels.Keys.ToList()) { if (!hashSet.Contains(item2)) { RemoveLabel(item2); } } } private static bool Matches(Item item) { return ((Object)((Component)item).gameObject).name.IndexOf("amulet", StringComparison.OrdinalIgnoreCase) >= 0; } private void AddLabel(int id, Transform target, string title, Func isValid) { if (!_labels.ContainsKey(id)) { _labels.Add(id, new AmuletLabel(((Component)_canvas).transform, target, title, isValid, _font, _fontSize)); if (!_loggedDiscovery) { _log.LogInfo((object)("Found amulet target: " + title)); _loggedDiscovery = true; } } } private static bool HasAmulet(ItemInstanceData instanceData) { BackpackData val = default(BackpackData); if (instanceData == null || !instanceData.TryGetDataEntry((DataEntryKey)7, ref val) || val == null || val.itemSlots == null) { return false; } ItemSlot[] itemSlots = val.itemSlots; foreach (ItemSlot val2 in itemSlots) { if (val2 != null && !val2.IsEmpty() && (Object)(object)val2.prefab != (Object)null && Matches(val2.prefab)) { return true; } } return false; } private void RemoveLabel(int id) { if (_labels.TryGetValue(id, out var value)) { value.Dispose(); _labels.Remove(id); } } private void ClearLabels() { foreach (AmuletLabel value in _labels.Values) { value.Dispose(); } _labels.Clear(); } private static TMP_FontAsset FindFont() { try { if ((Object)(object)GUIManager.instance != (Object)null) { AscentUI componentInChildren = ((Component)GUIManager.instance).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.text != (Object)null && (Object)(object)((TMP_Text)componentInChildren.text).font != (Object)null) { return ((TMP_Text)componentInChildren.text).font; } if ((Object)(object)GUIManager.instance.heroDayText != (Object)null && (Object)(object)((TMP_Text)GUIManager.instance.heroDayText).font != (Object)null) { return ((TMP_Text)GUIManager.instance.heroDayText).font; } } TextMeshProUGUI val = Object.FindAnyObjectByType(); if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null) { return ((TMP_Text)val).font; } if ((Object)(object)TMP_Settings.defaultFontAsset != (Object)null) { return TMP_Settings.defaultFontAsset; } } catch (Exception ex) { Debug.LogWarning((object)("WhereIsMyAmulet: failed to find a game font: " + ex.Message)); } return null; } } internal sealed class AmuletLabel { private readonly int _instanceId; private readonly Transform _target; private readonly Func _isValid; private readonly string _title; private readonly GameObject _root; private readonly CanvasGroup _group; private readonly List _shadowTexts = new List(); private readonly TextMeshProUGUI _mainText; private readonly TextMeshProUGUI _arrow; private static readonly Vector2[] ShadowOffsets = (Vector2[])(object)new Vector2[8] { new Vector2(0f, 1f), new Vector2(0f, -1f), new Vector2(-1f, 0f), new Vector2(1f, 0f), new Vector2(-1f, 1f), new Vector2(1f, 1f), new Vector2(-1f, -1f), new Vector2(1f, -1f) }; public int InstanceId => _instanceId; public bool IsValid { get { if ((Object)(object)_target != (Object)null && _isValid != null) { return _isValid(); } return false; } } public AmuletLabel(Transform canvas, Transform target, string title, Func isValid, TMP_FontAsset font, ConfigEntry fontSize) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Expected O, but got Unknown //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) _instanceId = ((!((Object)(object)target == (Object)null)) ? ((Object)((Component)target).gameObject).GetInstanceID() : 0); _target = target; _title = title; _isValid = isValid; _root = new GameObject("AmuletDistanceLabel"); _root.transform.SetParent(canvas, false); _root.layer = 5; _group = _root.AddComponent(); _group.blocksRaycasts = false; _group.interactable = false; for (int i = 0; i < 8; i++) { TextMeshProUGUI val = CreateText("Shadow_" + i, font, fontSize.Value); ((Graphic)val).color = new Color(0f, 0f, 0f, 0.9f); ((TMP_Text)val).rectTransform.anchoredPosition = ShadowOffsets[i] * 1.5f; _shadowTexts.Add(val); } _mainText = CreateText("MainText", font, fontSize.Value); ((Graphic)_mainText).color = new Color(0.875f, 0.855f, 0.761f, 1f); GameObject val2 = new GameObject("OffscreenDirection"); val2.transform.SetParent(_root.transform, false); _arrow = val2.AddComponent(); val2.layer = 5; ((TMP_Text)_arrow).font = font; ((TMP_Text)_arrow).text = "^"; ((TMP_Text)_arrow).alignment = (TextAlignmentOptions)514; ((TMP_Text)_arrow).fontSize = 22f; ((Graphic)_arrow).color = new Color(1f, 0.85f, 0.2f, 1f); ((Graphic)_arrow).raycastTarget = false; ((TMP_Text)_arrow).rectTransform.sizeDelta = new Vector2(18f, 18f); ((TMP_Text)_arrow).rectTransform.anchoredPosition = new Vector2(0f, -28f); ((Behaviour)_arrow).enabled = false; } private TextMeshProUGUI CreateText(string name, TMP_FontAsset font, float size) { //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_001d: 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) //IL_0086: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(_root.transform, false); val.layer = 5; TextMeshProUGUI obj = val.AddComponent(); ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; ((Graphic)obj).raycastTarget = false; ((TMP_Text)obj).overflowMode = (TextOverflowModes)0; ((TMP_Text)obj).richText = true; ((TMP_Text)obj).font = font; ((TMP_Text)obj).fontSize = Mathf.Clamp(size, 10f, 64f); ((TMP_Text)obj).rectTransform.sizeDelta = new Vector2(260f, 90f); ((TMP_Text)obj).rectTransform.anchoredPosition = Vector2.zero; return obj; } public void Update(Camera camera, float maxDistance, bool showOffscreen) { //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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: 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_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_0208: 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_014d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)camera == (Object)null) { SetVisible(visible: false); return; } Vector3 val = _target.position + Vector3.up * 0.8f; Vector3 val2 = camera.WorldToViewportPoint(val); float num = Vector3.Distance(((Component)camera).transform.position, _target.position); bool flag = maxDistance <= 0f || num <= maxDistance; bool flag2 = val2.z > 0f; if (flag2 && val2.x >= 0f && val2.x <= 1f && val2.y >= 0f && val2.y <= 1f && flag) { _root.transform.position = camera.WorldToScreenPoint(val); SetText($"{_title}\n{num:F0}m"); ((Behaviour)_arrow).enabled = false; SetVisible(visible: true); return; } if (!showOffscreen || !flag) { SetVisible(visible: false); return; } Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(val2.x - 0.5f, val2.y - 0.5f); if (!flag2) { val3 = -val3; } if (((Vector2)(ref val3)).sqrMagnitude < 0.001f) { val3 = Vector2.up; } ((Vector2)(ref val3)).Normalize(); Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor((float)Screen.width * 0.5f, (float)Screen.height * 0.5f); float num2 = (float)Mathf.Min(Screen.width, Screen.height) * 0.42f; _root.transform.position = Vector2.op_Implicit(val4 + val3 * num2); SetText($"{num:F0}m"); ((Behaviour)_arrow).enabled = true; ((Transform)((TMP_Text)_arrow).rectTransform).localRotation = Quaternion.Euler(0f, 0f, Mathf.Atan2(val3.y, val3.x) * 57.29578f - 90f); SetVisible(visible: true); } public void Dispose() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } } private void SetVisible(bool visible) { _group.alpha = (visible ? 1f : 0f); } private void SetText(string value) { ((TMP_Text)_mainText).text = value; foreach (TextMeshProUGUI shadowText in _shadowTexts) { ((TMP_Text)shadowText).text = value; } } } }