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.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Zichen-ValuablesScanner-1.2.2")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+97ae45c624f8b7fff2d14028e0383f3703f6fcff")] [assembly: AssemblyProduct("Zichen-ValuablesScanner-1.2.2")] [assembly: AssemblyTitle("Zichen-ValuablesScanner-1.2.2")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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; } } } public enum DisplayLanguage { 中文, English } [BepInPlugin("zichen.valuablesscanner", "A.Valuables Scanner", "1.2.2")] public class ZichenValuablesScannerPlugin : BaseUnityPlugin { private sealed class EnemyLabelInfo { public Enemy Enemy; public string Name = string.Empty; public Transform ReferenceTransform; public float LabelYOffset; public float DistanceSquared; public int CachedDistanceMeters = -1; public bool CachedShowDistance; public bool CachedIsMasked; public string PlainText = string.Empty; public string RichText = string.Empty; public float NextRuntimeRefreshTime; public int CachedLayoutFontSize = int.MinValue; public Vector2 CachedLayoutSize; } private struct EnemyFrameState { public bool IsUsable; public bool IsAliveAndSpawned; public Transform ReferenceTransform; public Vector3 ReferencePosition; } private enum TeamShareMode { None, Valuable, LotteryCoinBox } private sealed class ScanLabel { public Component Target; public PhysGrabObject PhysGrabObject; public Renderer[] Renderers = Array.Empty(); public string DisplayName = string.Empty; public bool IsValuable; public bool IsItem; public bool IsCart; public bool IsLotteryCoinBox; public bool IsSmallCart; public string ColorHex = "#62d8ff"; public Vector3 Position; public Vector3 LastAnchorPosition; public bool HasAnchorPosition; public string PlainText = string.Empty; public string RichText = string.Empty; public float DistanceSquared; public int DistanceMeters; public int CachedTextDistanceMeters = int.MinValue; public int CachedTextValue = int.MinValue; public bool CachedShowDistanceMeters; public bool CachedShowValuableNames; public bool CachedShowValuablePrices; public bool CachedIsMasked; public TeamShareMode ShareMode; public bool SharedWithTeam; public float NextRuntimeRefreshTime; public int CachedLayoutFontSize = int.MinValue; public Vector2 CachedLayoutSize; } private struct CartScanInfo { public bool IsCart; public bool IsSmallCart; } [CompilerGenerated] private sealed class d__392 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator { private int <>1__state; private string <>2__current; private int <>l__initialThreadId; private GameObject gameObject; public GameObject <>3__gameObject; private Component[] 5__2; private int 5__3; string IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__392(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_0079; } <>1__state = -1; if ((Object)(object)gameObject == (Object)null) { return false; } 5__2 = gameObject.GetComponents(); 5__3 = 0; goto IL_0089; IL_0079: 5__3++; goto IL_0089; IL_0089: if (5__3 < 5__2.Length) { Component val = 5__2[5__3]; if (!((Object)(object)val == (Object)null)) { <>2__current = ((object)val).GetType().Name; <>1__state = 1; return true; } goto IL_0079; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { d__392 d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; d__ = this; } else { d__ = new d__392(0); } d__.gameObject = <>3__gameObject; return d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [CompilerGenerated] private sealed class d__384 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public ZichenValuablesScannerPlugin <>4__this; private float 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__384(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown int num = <>1__state; ZichenValuablesScannerPlugin zichenValuablesScannerPlugin = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = Time.unscaledTime; break; case 1: <>1__state = -1; break; } if (!AreResourceDumpSourcesReady()) { if (Time.unscaledTime - 5__2 >= 30f) { ((BaseUnityPlugin)zichenValuablesScannerPlugin).Logger.LogWarning((object)"[NameDump] Timed out waiting for item and level resources."); return false; } <>2__current = (object)new WaitForSecondsRealtime(1f); <>1__state = 1; return true; } zichenValuablesScannerPlugin.DumpItemResources(); zichenValuablesScannerPlugin.DumpValuableResources(); ((BaseUnityPlugin)zichenValuablesScannerPlugin).Logger.LogInfo((object)"[NameDump] Completed item and valuable resource dump."); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "zichen.valuablesscanner"; public const string PluginVersion = "1.2.2"; public const string PluginName = "A.Valuables Scanner"; private static ZichenValuablesScannerPlugin Instance; private const string InfoSection = "模组信息"; private const string GlobalSection = "A.全局设置"; private const string ScannerSection = "B.扫描设置"; private const string ValuablesSubSection = "B1.贵重品扫描"; private const string ItemsSubSection = "B2.装备武器扫描"; private const string LotterySubSection = "B3.装饰箱扫描"; private const string CartSubSection = "B4.购物车扫描"; private const string EnemyScannerSection = "B5.怪物扫描"; private const string LotteryCoinBoxNameZh = "装饰箱"; private const string LotteryCoinBoxNameEn = "Decor Box"; private const int MinimumScanIntervalSeconds = 1; private const int MaximumScanIntervalSeconds = 5; private const int FixedScanHoldSeconds = 5; private const int MinimumScanDistanceMeters = 1; private const int MaximumScanDistanceMeters = 100; private const int TeamShareMaxDistanceMeters = 15; private const float ContainmentRefreshIntervalSeconds = 0.12f; private const int FarFontShrinkPercent = 30; private const float FontScaleDistanceMeters = 30f; private const float EnemyRefreshIntervalSeconds = 0.25f; private const float EnemyProximityRefreshIntervalSeconds = 0.12f; private const float EnemyLabelRefreshIntervalSeconds = 0.12f; private const float EnemyListCleanupIntervalSeconds = 1f; private const float ValuableValueRefreshIntervalSeconds = 0.12f; private const float LocalPlayerRefreshIntervalSeconds = 0.25f; private const float ScanLabelRefreshIntervalSeconds = 0.08f; private static readonly bool EnableStartupResourceNameDump = false; private static readonly bool EnableScanDebugLogging = false; private static readonly FieldInfo ValuableCurrentValueField = typeof(ValuableObject).GetField("dollarValueCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ValuableValueSetField = typeof(ValuableObject).GetField("dollarValueSet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ValuablePhysGrabObjectField = typeof(ValuableObject).GetField("physGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ItemNameField = typeof(ItemAttributes).GetField("itemName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ItemPhysGrabObjectField = typeof(ItemAttributes).GetField("physGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ItemShopItemField = typeof(ItemAttributes).GetField("shopItem", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ItemPromptNameField = typeof(ItemAttributes).GetField("promptName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ItemAssetNameField = typeof(ItemAttributes).GetField("itemAssetName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ItemInstanceNameField = typeof(ItemAttributes).GetField("instanceName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ItemTagField = typeof(ItemAttributes).GetField("itemTag", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ItemTypeField = typeof(ItemAttributes).GetField("itemType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ItemEquippableField = typeof(ItemAttributes).GetField("itemEquippable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabObjectDeadField = typeof(PhysGrabObject).GetField("dead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabObjectIsHiddenField = typeof(PhysGrabObject).GetField("isHidden", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabObjectImpactDetectorField = typeof(PhysGrabObject).GetField("impactDetector", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabObjectPlayerGrabbingField = typeof(PhysGrabObject).GetField("playerGrabbing", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabObjectImpactDetectorInCartField = typeof(PhysGrabObjectImpactDetector).GetField("inCart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabberGrabbedPhysGrabObjectField = typeof(PhysGrabber).GetField("grabbedPhysGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabberGrabbedField = typeof(PhysGrabber).GetField("grabbed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabberPlayerAvatarField = typeof(PhysGrabber).GetField("playerAvatar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabCartItemsInCartField = typeof(PhysGrabCart).GetField("itemsInCart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabCartInCartField = typeof(PhysGrabCart).GetField("physGrabInCart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabCartIsSmallField = typeof(PhysGrabCart).GetField("isSmallCart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabInCartObjectsField = typeof(PhysGrabInCart).GetField("inCartObjects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PhysGrabInCartCartObjectPhysGrabObjectField = typeof(PhysGrabInCart).GetNestedType("CartObject", BindingFlags.Public | BindingFlags.NonPublic)?.GetField("physGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo RoundDirectorInstanceField = typeof(RoundDirector).GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo RoundDirectorDollarHaulListField = typeof(RoundDirector).GetField("dollarHaulList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo RoundDirectorValuableBoxHaulListField = typeof(RoundDirector).GetField("valuableBoxHaulList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ValuableDiscoverCustomPhysGrabObjectField = typeof(ValuableDiscoverCustom).GetField("physGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo ValuableDiscoverCustomColorCornerField = typeof(ValuableDiscoverCustom).GetField("colorCorner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo EnemyParentField = typeof(Enemy).GetField("EnemyParent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo EnemyParentEnemyField = typeof(EnemyParent).GetField("Enemy", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo EnemyParentNameField = typeof(EnemyParent).GetField("enemyName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo EnemyParentLocalizedNameField = typeof(EnemyParent).GetField("enemyNameLocalized", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly MethodInfo LocalizedAssetGetStringMethod = typeof(LocalizedAsset).GetMethod("GetLocalizedString", Type.EmptyTypes); private static readonly FieldInfo EnemyParentSpawnedField = typeof(EnemyParent).GetField("Spawned", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo EnemyHealthField = typeof(Enemy).GetField("Health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo EnemyHealthDeadField = typeof(EnemyHealth).GetField("dead", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo EnemyCenterTransformField = typeof(Enemy).GetField("CenterTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo EnemyTypeField = typeof(Enemy).GetField("Type", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PlayerIsLocalField = typeof(PlayerAvatar).GetField("isLocal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PlayerTransformField = typeof(PlayerAvatar).GetField("playerTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PlayerDeadSetField = typeof(PlayerAvatar).GetField("deadSet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PlayerSpectatingField = typeof(PlayerAvatar).GetField("spectating", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private static readonly FieldInfo PlayerIsDisabledField = typeof(PlayerAvatar).GetField("isDisabled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); private readonly List labels = new List(); private readonly Stack scanLabelPool = new Stack(); private readonly Dictionary labelStyleCache = new Dictionary(); private readonly Dictionary enemyLabelStyleCache = new Dictionary(); private readonly Dictionary objectRendererCache = new Dictionary(); private readonly Dictionary objectDisplayNameCache = new Dictionary(); private readonly Dictionary objectPhysGrabCache = new Dictionary(); private readonly Dictionary itemHasValuableCache = new Dictionary(); private readonly Dictionary itemShopItemCache = new Dictionary(); private readonly Dictionary itemCartInfoCache = new Dictionary(); private readonly Dictionary itemShouldScanCache = new Dictionary(); private readonly Dictionary customDiscoverColorCache = new Dictionary(); private readonly Dictionary valuableValueCache = new Dictionary(); private readonly Dictionary valuableValueCacheExpiry = new Dictionary(); private readonly Dictionary physGrabHiddenOrDeadFrameCache = new Dictionary(); private readonly Dictionary enemyFrameStateCache = new Dictionary(); private readonly GUIContent labelContent = new GUIContent(); private readonly HashSet seenObjects = new HashSet(); private readonly HashSet cartObjectSet = new HashSet(ReferenceObjectComparer.Instance); private readonly HashSet haulObjectSet = new HashSet(ReferenceObjectComparer.Instance); private readonly HashSet sharedValuableIds = new HashSet(); private readonly HashSet sharedCustomDiscoverIds = new HashSet(); private readonly HashSet proximityUnlockedScanTargetIds = new HashSet(); private readonly HashSet localHeldPhysGrabObjects = new HashSet(); private readonly Dictionary localHeldStateCache = new Dictionary(); private readonly Dictionary playerAvatarFieldCache = new Dictionary(); private ConfigEntry moduleNameInfo; private ConfigEntry moduleVersionInfo; private ConfigEntry displayLanguage; private ConfigEntry scannerEnabled; private ConfigEntry shareScansWithTeam; private ConfigEntry scanExploreMode; private ConfigEntry showDistanceMeters; private ConfigEntry showValuables; private ConfigEntry showValuableNames; private ConfigEntry showValuablePrices; private ConfigEntry showItems; private ConfigEntry showItemNames; private ConfigEntry showLotteryCoinBoxes; private ConfigEntry showCarts; private ConfigEntry showBigCarts; private ConfigEntry showSmallCarts; private ConfigEntry scanKey; private ConfigEntry scanIntervalSeconds; private ConfigEntry scanDistanceMeters; private ConfigEntry fontSize; private ConfigEntry enemyOverlayEnabled; private ConfigEntry enemyProximityAutoShowEnabled; private ConfigEntry enemyProximityAutoShowDistance; private ConfigEntry enemyNicknameEnabled; private ConfigEntry modEnabled; private float visibleTimer; private float scanCooldownTimer; private int containmentSetFrame = -1; private float enemyVisibleTimer; private float enemyProximityVisibleTimer; private readonly List enemyLabels = new List(); private readonly Stack enemyLabelPool = new Stack(); private readonly HashSet enemiesInsideProximityRange = new HashSet(); private readonly Dictionary enemyProximityLingerTimers = new Dictionary(); private readonly Dictionary enemyProximityPopTimers = new Dictionary(); private readonly List enemyProximityTimerKeys = new List(); private readonly List expiredEnemyProximityKeys = new List(); private readonly Dictionary enemyRendererCache = new Dictionary(); private readonly Dictionary enemyColliderCache = new Dictionary(); private readonly Dictionary enemyDisplayNameCache = new Dictionary(); private readonly Dictionary enemyLabelYOffsetCache = new Dictionary(); private readonly Dictionary enemyCenterTransformCache = new Dictionary(); private const float ProximityAutoShowLingerSeconds = 5f; private const float EnemyProximityPopSeconds = 1.2f; private const float EnemyProximityPopFontMultiplier = 2f; private DisplayLanguage enemyDisplayNameCacheLanguage; private bool enemyDisplayNameCacheNicknames = true; private float nextEnemyProximityRefreshTime; private float nextEnemyLabelRefreshTime; private float nextEnemyListCleanupTime; private float nextContainmentRefreshTime; private int cachedLocalPositionFrame = -1; private Vector3 cachedLocalPosition; private Camera cachedCamera; private int cachedGuiScaleFrame = -1; private Camera cachedGuiScaleCamera; private float cachedGuiScaleX = 1f; private float cachedGuiScaleY = 1f; private int cachedPhysGrabStateFrame = -1; private int cachedEnemyStateFrame = -1; private int cachedScanSettingsFrame = -1; private int cachedScanLocalPlayerFrame = -1; private bool cachedScanLocalPlayerReady; private PlayerAvatar cachedScanLocalPlayer; private int cachedScanDistanceMeters = 15; private float cachedScanDistanceSquared = 225f; private int cachedScanFontSize = 28; private bool cachedScanExploreMode; private bool cachedShowDistanceMeters; private bool cachedShowValuableNames = true; private bool cachedShowValuablePrices = true; private PlayerAvatar cachedLocalPlayer; private bool cachedLocalPlayerIsLocal; private readonly List grabberObjectsCache = new List(); private float nextGrabberRefreshTime; private float nextLocalHeldRefreshTime; private float nextLocalPlayerRefreshTime; private DisplayLanguage objectDisplayNameCacheLanguage; private Harmony harmony; private static readonly List trackedValuables = new List(); private static readonly HashSet trackedValuableSet = new HashSet(); private static readonly List trackedItems = new List(); private static readonly HashSet trackedItemSet = new HashSet(); private static readonly List trackedEnemies = new List(); private static readonly HashSet trackedEnemySet = new HashSet(); private static readonly List trackedCarts = new List(); private static readonly HashSet trackedCartSet = new HashSet(); private static readonly List trackedDiscoverCustoms = new List(); private static readonly HashSet trackedDiscoverCustomSet = new HashSet(); private static readonly List trackedGrabbers = new List(); private static readonly HashSet trackedGrabberSet = new HashSet(); private static float nextEnemyDirectorSyncTime; private const int ScanInputKeyValue = 329; private static readonly InputKey ScanInputKey = (InputKey)329; private static string lastAppliedScanKey; private bool resourceNameDumpStarted; private static readonly string[] AvailableKeybinds = new string[55] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "Space", "Enter", "Tab", "LeftShift", "RightShift", "LeftControl", "RightControl" }; private static string cachedOfficialGreenHex; private static int officialColorCacheFrame = -1; private static readonly Regex WhitespaceRegex = new Regex("\\s+", RegexOptions.Compiled); private static readonly string[] ItemKeywords = new string[22] { "weapon", "gun", "melee", "tool", "grenade", "mine", "drone", "tracker", "medkit", "health", "flashlight", "orb", "upgrade", "cart", "pistol", "shotgun", "revolver", "sword", "bat", "hammer", "spear", "mace" }; private static bool inputActionsRegistered; private static InputManager registeredInputManager; private static Dictionary registeredInputActions; private const float ResourceDumpRetryIntervalSeconds = 1f; private const float ResourceDumpTimeoutSeconds = 30f; private static DisplayLanguage InstanceLanguage { get { if (!((Object)(object)Instance == (Object)null) && Instance.displayLanguage != null) { return Instance.displayLanguage.Value; } return DisplayLanguage.中文; } } private void Awake() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown DetachFromManager(); Instance = this; ResetConfigIfVersionChanged(); BindConfig(); scanKey.SettingChanged += delegate { RebindScanKey(); }; ((BaseUnityPlugin)this).Logger.LogInfo((object)"zichen-valuables-scanner loaded."); harmony = new Harmony("zichen.valuablesscanner"); ApplyHarmonyPatches(); if (EnableStartupResourceNameDump) { StartResourceNameDump(); } } private void DetachFromManager() { try { ((Component)this).transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to mark plugin host persistent: " + ex.GetType().Name + ": " + ex.Message)); } } private bool IsModEnabled() { if (modEnabled != null) { return modEnabled.Value; } return true; } private static bool IsStaticModEnabled() { ZichenValuablesScannerPlugin instance = Instance; if (!((Object)(object)instance == (Object)null)) { return instance.IsModEnabled(); } return true; } private void LogScanDebug(string message) { if (EnableScanDebugLogging) { ((BaseUnityPlugin)this).Logger.LogInfo((object)message); } } internal static string GetOfficialValueColorHex() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (officialColorCacheFrame == Time.frameCount && cachedOfficialGreenHex != null) { return cachedOfficialGreenHex; } officialColorCacheFrame = Time.frameCount; try { if ((Object)(object)WorldSpaceUIValue.instance != (Object)null) { cachedOfficialGreenHex = ColorUtility.ToHtmlStringRGB(WorldSpaceUIValue.instance.colorValue); return cachedOfficialGreenHex; } } catch { } cachedOfficialGreenHex = "00C832"; return cachedOfficialGreenHex; } private void BindConfig() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown moduleNameInfo = ((BaseUnityPlugin)this).Config.Bind("模组信息", "模组名称", "价值扫描器", new ConfigDescription("当前模组的中文名称。此处只是提示,不影响功能。", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 1000, CustomDrawer = DrawInfo, ReadOnly = true } })); moduleNameInfo.Value = "价值扫描器"; moduleVersionInfo = ((BaseUnityPlugin)this).Config.Bind("模组信息", "模组版本号", "1.2.2", new ConfigDescription("当前模组版本号。此处只是提示,不影响功能。", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 990, CustomDrawer = DrawInfo, ReadOnly = true } })); moduleVersionInfo.Value = "1.2.2"; modEnabled = ((BaseUnityPlugin)this).Config.Bind("A.全局设置", "模组启用", true, ConfigDescriptionWithOrder("关闭后整个模组所有扫描和显示功能都不生效。默认开启。", 1005)); displayLanguage = ((BaseUnityPlugin)this).Config.Bind("A.全局设置", "语言/Language", DisplayLanguage.中文, ConfigDescriptionWithOrder("选择扫描标签显示语言。默认中文,English 会显示原始英文名称。", 1000)); enemyNicknameEnabled = ((BaseUnityPlugin)this).Config.Bind("A.全局设置", "敌人名字优化", true, ConfigDescriptionWithOrder("开启后怪物显示社区昵称(如 大眼哥 等)。关闭后显示标准中文名。默认开启。", 995)); scannerEnabled = ((BaseUnityPlugin)this).Config.Bind("B.扫描设置", "启用", true, ConfigDescriptionWithOrder("关闭后整个扫描显示都不生效。", 900)); shareScansWithTeam = ((BaseUnityPlugin)this).Config.Bind("B.扫描设置", "信息共享队友", true, ConfigDescriptionWithOrder("开启后,只有你主动按扫描键时,且目标距离自己不超过 15 米的贵重品和装饰箱,才会走游戏原生发现同步,队友不装这个模组也能收到发现效果。默认开启;若扫描探索模式开启,则会等目标解除 ? 后才触发一次同步。默认解锁距离为:贵重品 4 米、其他扫描目标 6 米、怪物 20 米。", 895)); scanExploreMode = ((BaseUnityPlugin)this).Config.Bind("B.扫描设置", "扫描探索模式", false, ConfigDescriptionWithOrder("开启后扫描标签会先显示 ?,只有目标第一次进入解锁距离后才会显示正常名称、价格和米数。默认解锁距离为:贵重品 4 米、其他扫描目标 6 米、怪物 20 米;贵重品与装饰箱的信息共享也会等到解除 ? 后才触发一次。默认关闭。", 890)); showValuables = ((BaseUnityPlugin)this).Config.Bind("B1.贵重品扫描", "启用", true, ConfigDescriptionWithOrder("显示可回收贵重品。", 890)); showValuableNames = ((BaseUnityPlugin)this).Config.Bind("B1.贵重品扫描", "显示名称", true, ConfigDescriptionWithOrder("开启后贵重品扫描标签显示物品名称。默认开启。", 889)); showValuablePrices = ((BaseUnityPlugin)this).Config.Bind("B1.贵重品扫描", "显示价格", false, ConfigDescriptionWithOrder("开启后贵重品扫描标签显示当前价格。默认关闭。", 888)); showItems = ((BaseUnityPlugin)this).Config.Bind("B2.装备武器扫描", "启用", true, ConfigDescriptionWithOrder("显示枪、近战、血包、手雷等装备/武器。", 880)); showItemNames = ((BaseUnityPlugin)this).Config.Bind("B2.装备武器扫描", "显示名称", true, ConfigDescriptionWithOrder("开启后装备武器标签显示名称。默认开启。", 879)); showLotteryCoinBoxes = ((BaseUnityPlugin)this).Config.Bind("B3.装饰箱扫描", "启用", true, ConfigDescriptionWithOrder("显示关卡中的投币机、硬币宝箱、代币箱和装饰箱。不同类型用不同颜色区分。默认开启。", 870)); showCarts = ((BaseUnityPlugin)this).Config.Bind("B4.购物车扫描", "启用", false, ConfigDescriptionWithOrder("购物车扫描总开关。关闭后大购物车和小购物车都不会显示。默认关闭。", 865)); showBigCarts = ((BaseUnityPlugin)this).Config.Bind("B4.购物车扫描", "显示大购物车", true, ConfigDescriptionWithOrder("开启后扫描时显示大购物车。默认开启。", 860)); showSmallCarts = ((BaseUnityPlugin)this).Config.Bind("B4.购物车扫描", "显示小购物车", true, ConfigDescriptionWithOrder("开启后扫描时显示小购物车。默认开启。", 859)); showDistanceMeters = ((BaseUnityPlugin)this).Config.Bind("B.扫描设置", "显示米数", false, ConfigDescriptionWithOrder("开启后扫描标签显示距离米数;关闭后物品、贵重品、装饰箱、购物车和怪物都不显示米数。默认关闭。", 875)); fontSize = ((BaseUnityPlugin)this).Config.Bind("B.扫描设置", "字体大小", 26, ConfigDescriptionWithOrder("局内物品和怪物扫描标签的字体大小。", (AcceptableValueBase)(object)new AcceptableValueRange(8, 48), 874)); scanKey = ((BaseUnityPlugin)this).Config.Bind("B.扫描设置", "扫描按键", "F", ConfigDescriptionWithOrder("按下这个按键后显示附近贵重品、装备、购物车、装饰箱和怪物,固定显示5秒。", (AcceptableValueBase)(object)new AcceptableValueList(AvailableKeybinds), 870)); scanIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind("B.扫描设置", "扫描冷却/秒", 1, ConfigDescriptionWithOrder("按下扫描按键后,多少秒内再次按下不会重新显示。范围1-5秒,每次调整1秒。", (AcceptableValueBase)(object)new AcceptableValueRange(1, 5), 860)); scanDistanceMeters = ((BaseUnityPlugin)this).Config.Bind("B.扫描设置", "扫描距离/米", 15, ConfigDescriptionWithOrder("按下扫描按键时,只扫描并显示距离自己多少米以内的物品和怪物。范围1-100米,每次调整1米。默认15米。", (AcceptableValueBase)(object)new AcceptableValueRange(1, 100), 850)); enemyOverlayEnabled = ((BaseUnityPlugin)this).Config.Bind("B5.怪物扫描", "启用", true, ConfigDescriptionWithOrder("关闭后不再显示怪物局内标签;显示按键、扫描距离、字体大小和米数显示同步使用 B.扫描设置 的设置。默认开启。", 800)); enemyProximityAutoShowEnabled = ((BaseUnityPlugin)this).Config.Bind("B5.怪物扫描", "启用靠近自动显示", true, ConfigDescriptionWithOrder("怪物进入靠近自动显示距离时,会临时显示怪物标签;怪物离开范围后5秒恢复。靠近自动显示距离可独立大于 B.扫描设置 的扫描距离。", 790)); enemyProximityAutoShowDistance = ((BaseUnityPlugin)this).Config.Bind("B5.怪物扫描", "靠近自动显示距离/米", 30, ConfigDescriptionWithOrder("怪物距离你多少米以内时自动临时显示。这个距离可以独立大于 B.扫描设置 的扫描距离。默认30米。", (AcceptableValueBase)(object)new AcceptableValueRange(1, 100), 780)); } private void ResetConfigIfVersionChanged() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; string text = ReadConfigPluginVersion(configFilePath); if (!string.IsNullOrWhiteSpace(text) && !(text == "1.2.2")) { ResetConfigFileToDefaults(configFilePath); ((BaseUnityPlugin)this).Logger.LogWarning((object)"Config version changed. Old config was reset to defaults."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to reset config by version: " + ex.Message)); } } private static string ReadConfigPluginVersion(string configPath) { if (!File.Exists(configPath)) { return null; } Match match = Regex.Match(File.ReadAllText(configPath), "(?m)^模组版本号\\s*=\\s*(.+?)\\s*$"); if (!match.Success) { return null; } return match.Groups[1].Value.Trim(); } private void ResetConfigFileToDefaults(string configPath) { ((BaseUnityPlugin)this).Config.Clear(); if (File.Exists(configPath)) { File.Delete(configPath); } ((BaseUnityPlugin)this).Config.Reload(); } private static ConfigDescription ConfigDescriptionWithOrder(string description, int order) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown return new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = order } }); } private static ConfigDescription ConfigDescriptionWithOrder(string description, AcceptableValueBase acceptableValues, int order) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown return new ConfigDescription(description, acceptableValues, new object[1] { new ConfigurationManagerAttributes { Order = order } }); } private static void DrawInfo(ConfigEntryBase entry) { GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(entry.Definition.Key, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.Label(entry.BoxedValue?.ToString() ?? string.Empty, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(160f) }); GUILayout.EndHorizontal(); } private void Update() { //IL_0104: Unknown result type (might be due to invalid IL or missing references) if (!IsModEnabled()) { visibleTimer = 0f; scanCooldownTimer = 0f; ClearScanLabels(); ClearEnemyLabels(); ClearEnemyProximityTracking(); enemyVisibleTimer = 0f; enemyProximityVisibleTimer = 0f; return; } if ((Object)(object)InputManager.instance != (Object)null && (!inputActionsRegistered || registeredInputManager != InputManager.instance)) { EnsureInputActionsRegistered(); } if (!CanUseLocalScan()) { visibleTimer = 0f; scanCooldownTimer = 0f; ClearScanLabels(); } else if (scannerEnabled == null || !scannerEnabled.Value) { visibleTimer = 0f; scanCooldownTimer = 0f; ClearScanLabels(); } else { if (scanCooldownTimer > 0f) { scanCooldownTimer = Mathf.Max(0f, scanCooldownTimer - Time.deltaTime); } if ((Object)(object)InputManager.instance != (Object)null && SemiFunc.InputDown(ScanInputKey)) { if (scanCooldownTimer <= 0f) { visibleTimer = GetScanHoldSeconds(); scanCooldownTimer = ClampScanInterval((scanIntervalSeconds == null) ? 1f : ((float)scanIntervalSeconds.Value)); LogScanDebug($"[ScanDebug] InputDown accepted. visibleTimer={visibleTimer:F2}, cooldown={scanCooldownTimer:F2}, trackedValuables={trackedValuables.Count}, trackedItems={trackedItems.Count}, trackedEnemies={trackedEnemies.Count}"); RefreshLabels(); } else { LogScanDebug($"[ScanDebug] InputDown ignored by cooldown. remaining={scanCooldownTimer:F2}"); } } if (visibleTimer > 0f) { visibleTimer = Mathf.Max(0f, visibleTimer - Time.deltaTime); } if (visibleTimer <= 0f) { ClearScanLabels(); } } UpdateEnemyOverlayState(); } private void RefreshLabels() { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_0638: Unknown result type (might be due to invalid IL or missing references) //IL_063d: Unknown result type (might be due to invalid IL or missing references) //IL_064a: Unknown result type (might be due to invalid IL or missing references) //IL_064f: Unknown result type (might be due to invalid IL or missing references) //IL_0651: Unknown result type (might be due to invalid IL or missing references) //IL_0653: Unknown result type (might be due to invalid IL or missing references) //IL_0655: Unknown result type (might be due to invalid IL or missing references) //IL_065a: Unknown result type (might be due to invalid IL or missing references) //IL_0702: Unknown result type (might be due to invalid IL or missing references) //IL_0704: Unknown result type (might be due to invalid IL or missing references) //IL_070b: Unknown result type (might be due to invalid IL or missing references) //IL_070d: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0421: 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_0428: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_0502: Unknown result type (might be due to invalid IL or missing references) //IL_0504: Unknown result type (might be due to invalid IL or missing references) //IL_050b: Unknown result type (might be due to invalid IL or missing references) //IL_050d: Unknown result type (might be due to invalid IL or missing references) ClearScanLabels(); seenObjects.Clear(); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; int num6 = 0; if (!TryGetScanOriginPosition(out var position)) { LogScanDebug("[ScanDebug] RefreshLabels aborted: no local scan origin."); return; } float scanDistanceSquared = GetScanDistanceSquared(); bool showDistance = ShouldShowDistanceMeters(); bool showName = ShouldShowValuableNames(); bool showPrice = ShouldShowValuablePrices(); ForceRefreshContainmentSets(); Vector3 val; if (showValuables == null || showValuables.Value) { PruneTrackedCollection(trackedValuables, trackedValuableSet); foreach (ValuableObject trackedValuable in trackedValuables) { num++; if (!IsObjectUsable(((Object)(object)trackedValuable == (Object)null) ? null : ((Component)trackedValuable).gameObject)) { continue; } PhysGrabObject physGrabObjectCached = GetPhysGrabObjectCached((Component)(object)trackedValuable, ValuablePhysGrabObjectField); if (IsPhysGrabObjectHiddenOrDead(physGrabObjectCached) || IsHeldByLocalPlayer(physGrabObjectCached) || IsObjectInCart((Component)(object)trackedValuable, physGrabObjectCached) || IsObjectInHaul((Component)(object)trackedValuable, physGrabObjectCached)) { continue; } Renderer[] usableRenderersCached = GetUsableRenderersCached((Component)(object)trackedValuable); Vector3 objectAnchorPosition = GetObjectAnchorPosition(((Component)trackedValuable).transform, physGrabObjectCached); Vector3 objectCenter = GetObjectCenter(((Component)trackedValuable).transform, physGrabObjectCached, usableRenderersCached); val = objectCenter - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (!(sqrMagnitude > scanDistanceSquared)) { int instanceID = ((Object)trackedValuable).GetInstanceID(); seenObjects.Add(instanceID); int distanceMeters = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude)); string valuableDisplayNameCached = GetValuableDisplayNameCached(trackedValuable); ScanLabel scanLabel = RentScanLabel(); scanLabel.Target = (Component)(object)trackedValuable; scanLabel.PhysGrabObject = physGrabObjectCached; scanLabel.IsValuable = true; scanLabel.ShareMode = TeamShareMode.Valuable; scanLabel.DisplayName = valuableDisplayNameCached; scanLabel.Renderers = usableRenderersCached; scanLabel.Position = objectCenter; scanLabel.LastAnchorPosition = objectAnchorPosition; scanLabel.HasAnchorPosition = true; scanLabel.DistanceSquared = sqrMagnitude; scanLabel.DistanceMeters = distanceMeters; if (!RefreshValuableLabelText(scanLabel, trackedValuable, distanceMeters, sqrMagnitude, showDistance, showName, showPrice)) { ReturnScanLabel(scanLabel); continue; } labels.Add(scanLabel); num2++; } } } bool flag = showLotteryCoinBoxes != null && showLotteryCoinBoxes.Value; bool flag2 = showCarts == null || showCarts.Value; bool flag3 = flag2 && ((showBigCarts != null && showBigCarts.Value) || (showSmallCarts != null && showSmallCarts.Value)); if ((showItems != null && showItems.Value) || flag3) { PruneTrackedCollection(trackedItems, trackedItemSet); foreach (ItemAttributes trackedItem in trackedItems) { num3++; if (!IsObjectUsable(((Object)(object)trackedItem == (Object)null) ? null : ((Component)trackedItem).gameObject) || HasValuableObjectCached(trackedItem)) { continue; } PhysGrabObject physGrabObjectCached2 = GetPhysGrabObjectCached((Component)(object)trackedItem, ItemPhysGrabObjectField); if (IsPhysGrabObjectHiddenOrDead(physGrabObjectCached2) || IsHeldByLocalPlayer(physGrabObjectCached2) || IsObjectInCart((Component)(object)trackedItem, physGrabObjectCached2) || IsObjectInHaul((Component)(object)trackedItem, physGrabObjectCached2) || IsShopItemCached(trackedItem)) { continue; } CartScanInfo cartScanInfoCached = GetCartScanInfoCached((Component)(object)trackedItem, physGrabObjectCached2); bool isCart = cartScanInfoCached.IsCart; bool isSmallCart = cartScanInfoCached.IsSmallCart; if ((isCart && !flag2) || (isCart && !isSmallCart && (showBigCarts == null || !showBigCarts.Value)) || (isCart && isSmallCart && (showSmallCarts == null || !showSmallCarts.Value)) || (!isCart && !ShouldScanItemCached(trackedItem)) || (!isCart && (showItems == null || !showItems.Value))) { continue; } Renderer[] usableRenderersCached2 = GetUsableRenderersCached((Component)(object)trackedItem); Vector3 objectAnchorPosition2 = GetObjectAnchorPosition(((Component)trackedItem).transform, physGrabObjectCached2); Vector3 objectCenter2 = GetObjectCenter(((Component)trackedItem).transform, physGrabObjectCached2, usableRenderersCached2); val = objectCenter2 - position; float sqrMagnitude2 = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude2 > scanDistanceSquared) { continue; } string text; string colorHex; if (isCart) { text = ((InstanceLanguage != DisplayLanguage.English) ? (isSmallCart ? "小购物车" : "大购物车") : (isSmallCart ? "Small Cart" : "Cart")); colorHex = "#62d8ff"; } else { text = GetItemDisplayNameCached(trackedItem); colorHex = "#62d8ff"; } if (!string.IsNullOrWhiteSpace(text)) { int distanceMeters2 = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude2)); ScanLabel scanLabel2 = RentScanLabel(); scanLabel2.Target = (Component)(object)trackedItem; scanLabel2.PhysGrabObject = physGrabObjectCached2; scanLabel2.IsItem = true; scanLabel2.IsCart = isCart; scanLabel2.IsSmallCart = isSmallCart; scanLabel2.ShareMode = TeamShareMode.None; scanLabel2.ColorHex = colorHex; scanLabel2.DisplayName = text; scanLabel2.Renderers = usableRenderersCached2; scanLabel2.Position = objectCenter2; scanLabel2.LastAnchorPosition = objectAnchorPosition2; scanLabel2.HasAnchorPosition = true; scanLabel2.DistanceSquared = sqrMagnitude2; scanLabel2.DistanceMeters = distanceMeters2; if (!RefreshItemLabelText(scanLabel2, distanceMeters2, sqrMagnitude2, showDistance)) { ReturnScanLabel(scanLabel2); continue; } labels.Add(scanLabel2); num4++; } } } if (flag) { PruneTrackedCollection(trackedDiscoverCustoms, trackedDiscoverCustomSet); foreach (ValuableDiscoverCustom trackedDiscoverCustom in trackedDiscoverCustoms) { num5++; if ((Object)(object)trackedDiscoverCustom == (Object)null || !IsObjectUsable(((Component)trackedDiscoverCustom).gameObject) || seenObjects.Contains(((Object)trackedDiscoverCustom).GetInstanceID())) { continue; } PhysGrabObject physGrabObjectCached3 = GetPhysGrabObjectCached((Component)(object)trackedDiscoverCustom, ValuableDiscoverCustomPhysGrabObjectField); if (IsPhysGrabObjectHiddenOrDead(physGrabObjectCached3) || IsHeldByLocalPlayer(physGrabObjectCached3) || IsObjectInCart((Component)(object)trackedDiscoverCustom, physGrabObjectCached3) || IsObjectInHaul((Component)(object)trackedDiscoverCustom, physGrabObjectCached3)) { continue; } Renderer[] usableRenderersCached3 = GetUsableRenderersCached((Component)(object)trackedDiscoverCustom); Vector3 objectAnchorPosition3 = GetObjectAnchorPosition(((Component)trackedDiscoverCustom).transform, physGrabObjectCached3); Vector3 objectCenter3 = GetObjectCenter(((Component)trackedDiscoverCustom).transform, physGrabObjectCached3, usableRenderersCached3); val = objectCenter3 - position; float sqrMagnitude3 = ((Vector3)(ref val)).sqrMagnitude; if (!(sqrMagnitude3 > scanDistanceSquared)) { int instanceID2 = ((Object)trackedDiscoverCustom).GetInstanceID(); seenObjects.Add(instanceID2); int distanceMeters3 = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude3)); string customDiscoverColorHexCached = GetCustomDiscoverColorHexCached(trackedDiscoverCustom); string displayName = ((InstanceLanguage == DisplayLanguage.English) ? "Decor Box" : "装饰箱"); ScanLabel scanLabel3 = RentScanLabel(); scanLabel3.Target = (Component)(object)trackedDiscoverCustom; scanLabel3.PhysGrabObject = physGrabObjectCached3; scanLabel3.IsItem = true; scanLabel3.IsLotteryCoinBox = true; scanLabel3.ShareMode = TeamShareMode.LotteryCoinBox; scanLabel3.ColorHex = customDiscoverColorHexCached; scanLabel3.DisplayName = displayName; scanLabel3.Renderers = usableRenderersCached3; scanLabel3.Position = objectCenter3; scanLabel3.LastAnchorPosition = objectAnchorPosition3; scanLabel3.HasAnchorPosition = true; scanLabel3.DistanceSquared = sqrMagnitude3; scanLabel3.DistanceMeters = distanceMeters3; if (!RefreshItemLabelText(scanLabel3, distanceMeters3, sqrMagnitude3, showDistance)) { ReturnScanLabel(scanLabel3); continue; } labels.Add(scanLabel3); num6++; } } } labels.Sort(CompareScanLabels); LogScanDebug($"[ScanDebug] RefreshLabels done. valuableCandidates={num}, valuableAdded={num2}, itemCandidates={num3}, itemAdded={num4}, customCandidates={num5}, customAdded={num6}, totalLabels={labels.Count}, visibleTimer={visibleTimer:F2}"); } private static int CompareScanLabels(ScanLabel a, ScanLabel b) { int num = a.DistanceSquared.CompareTo(b.DistanceSquared); if (num == 0) { return GetLabelSortPriority(a).CompareTo(GetLabelSortPriority(b)); } return num; } private ScanLabel RentScanLabel() { if (scanLabelPool.Count > 0) { return scanLabelPool.Pop(); } return new ScanLabel(); } private void ReturnScanLabel(ScanLabel label) { //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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) if (label != null) { label.Target = null; label.PhysGrabObject = null; label.Renderers = Array.Empty(); label.DisplayName = string.Empty; label.IsValuable = false; label.IsItem = false; label.IsCart = false; label.IsLotteryCoinBox = false; label.IsSmallCart = false; label.ColorHex = "#62d8ff"; label.Position = Vector3.zero; label.LastAnchorPosition = Vector3.zero; label.HasAnchorPosition = false; label.PlainText = string.Empty; label.RichText = string.Empty; label.DistanceSquared = 0f; label.DistanceMeters = 0; label.CachedTextDistanceMeters = int.MinValue; label.CachedTextValue = int.MinValue; label.CachedShowDistanceMeters = false; label.CachedShowValuableNames = false; label.CachedShowValuablePrices = false; label.CachedIsMasked = false; label.ShareMode = TeamShareMode.None; label.SharedWithTeam = false; label.NextRuntimeRefreshTime = 0f; label.CachedLayoutFontSize = int.MinValue; label.CachedLayoutSize = Vector2.zero; scanLabelPool.Push(label); } } private void ClearScanLabels() { if (labels.Count != 0) { for (int i = 0; i < labels.Count; i++) { ReturnScanLabel(labels[i]); } labels.Clear(); } } private static int GetLabelSortPriority(ScanLabel label) { if (label.IsValuable) { return 0; } if (label.IsCart && !label.IsSmallCart) { return 3; } if (label.IsCart && label.IsSmallCart) { return 4; } if (label.IsLotteryCoinBox) { return 2; } return 1; } private bool RevealValuableToTeam(ValuableObject valuable) { if ((Object)(object)valuable == (Object)null) { return false; } int instanceID = ((Object)valuable).GetInstanceID(); if (sharedValuableIds.Contains(instanceID)) { return true; } try { valuable.Discover((State)0); sharedValuableIds.Add(instanceID); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Native valuable reveal failed: " + ex.GetType().Name + ": " + ex.Message)); return false; } } private bool RevealCustomDiscoverToTeam(ValuableDiscoverCustom custom) { if ((Object)(object)custom == (Object)null) { return false; } int instanceID = ((Object)custom).GetInstanceID(); if (sharedCustomDiscoverIds.Contains(instanceID)) { return true; } try { custom.Discover(); sharedCustomDiscoverIds.Add(instanceID); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Native custom discover reveal failed: " + ex.GetType().Name + ": " + ex.Message)); return false; } } private void UpdateEnemyOverlayState() { //IL_0076: Unknown result type (might be due to invalid IL or missing references) if (!CanUseLocalScan()) { ClearEnemyLabels(); ClearEnemyProximityTracking(); enemyVisibleTimer = 0f; enemyProximityVisibleTimer = 0f; return; } if (enemyOverlayEnabled == null || !enemyOverlayEnabled.Value) { ClearEnemyLabels(); ClearEnemyProximityTracking(); enemyVisibleTimer = 0f; enemyProximityVisibleTimer = 0f; return; } SyncTrackedEnemiesFromDirector(); if ((Object)(object)InputManager.instance != (Object)null && SemiFunc.InputHold(ScanInputKey)) { enemyVisibleTimer = GetScanHoldSeconds(); } if (enemyVisibleTimer > 0f) { enemyVisibleTimer -= Time.deltaTime; } bool flag = UpdateEnemyProximityAutoShowState(); UpdateEnemyProximityPopTimers(); if (!(enemyVisibleTimer > 0f || flag)) { ClearEnemyLabels(); nextEnemyLabelRefreshTime = 0f; } else if (enemyLabels.Count == 0 || Time.unscaledTime >= nextEnemyLabelRefreshTime) { RefreshEnemyLabels(); nextEnemyLabelRefreshTime = Time.unscaledTime + 0.12f; } } private bool UpdateEnemyProximityAutoShowState() { if (enemyProximityAutoShowEnabled == null || !enemyProximityAutoShowEnabled.Value) { enemyProximityVisibleTimer = 0f; ClearEnemyProximityTracking(); return false; } if (Time.unscaledTime >= nextEnemyProximityRefreshTime) { UpdateEnemiesWithinProximityDistance(enemyProximityAutoShowDistance.Value); nextEnemyProximityRefreshTime = Time.unscaledTime + 0.12f; } UpdateEnemyProximityLingerTimers(); bool flag = enemyProximityLingerTimers.Count > 0; enemyProximityVisibleTimer = (flag ? 5f : 0f); return flag; } private bool UpdateEnemiesWithinProximityDistance(float distance) { //IL_0046: 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_004c: 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) enemiesInsideProximityRange.Clear(); if (!TryGetScanOriginPosition(out var position)) { return false; } float num = distance * distance; CleanupTrackedEnemiesThrottled(); foreach (Enemy trackedEnemy in trackedEnemies) { if (!TryGetEnemyFrameState(trackedEnemy, out var state)) { continue; } Vector3 val = state.ReferencePosition - position; if (((Vector3)(ref val)).sqrMagnitude <= num) { int enemyKey = GetEnemyKey(trackedEnemy); enemiesInsideProximityRange.Add(enemyKey); if (!enemyProximityLingerTimers.ContainsKey(enemyKey) && !enemyProximityPopTimers.ContainsKey(enemyKey)) { enemyProximityPopTimers[enemyKey] = 1.2f; } enemyProximityLingerTimers[enemyKey] = 5f; } } return enemiesInsideProximityRange.Count > 0; } private void UpdateEnemyProximityLingerTimers() { if (enemyProximityLingerTimers.Count == 0) { return; } enemyProximityTimerKeys.Clear(); expiredEnemyProximityKeys.Clear(); foreach (KeyValuePair enemyProximityLingerTimer in enemyProximityLingerTimers) { enemyProximityTimerKeys.Add(enemyProximityLingerTimer.Key); } for (int i = 0; i < enemyProximityTimerKeys.Count; i++) { int num = enemyProximityTimerKeys[i]; if (!enemiesInsideProximityRange.Contains(num) && enemyProximityLingerTimers.TryGetValue(num, out var value)) { float num2 = value - Time.deltaTime; if (num2 <= 0f) { expiredEnemyProximityKeys.Add(num); } else { enemyProximityLingerTimers[num] = num2; } } } for (int j = 0; j < expiredEnemyProximityKeys.Count; j++) { enemyProximityLingerTimers.Remove(expiredEnemyProximityKeys[j]); } } private void UpdateEnemyProximityPopTimers() { if (enemyProximityPopTimers.Count == 0) { return; } enemyProximityTimerKeys.Clear(); expiredEnemyProximityKeys.Clear(); foreach (KeyValuePair enemyProximityPopTimer in enemyProximityPopTimers) { enemyProximityTimerKeys.Add(enemyProximityPopTimer.Key); } for (int i = 0; i < enemyProximityTimerKeys.Count; i++) { int num = enemyProximityTimerKeys[i]; if (enemyProximityPopTimers.TryGetValue(num, out var value)) { float num2 = value - Time.deltaTime; if (num2 <= 0f) { expiredEnemyProximityKeys.Add(num); } else { enemyProximityPopTimers[num] = num2; } } } for (int j = 0; j < expiredEnemyProximityKeys.Count; j++) { enemyProximityPopTimers.Remove(expiredEnemyProximityKeys[j]); } } private void ClearEnemyProximityTracking() { enemiesInsideProximityRange.Clear(); enemyProximityLingerTimers.Clear(); enemyProximityPopTimers.Clear(); enemyProximityTimerKeys.Clear(); expiredEnemyProximityKeys.Clear(); nextEnemyProximityRefreshTime = 0f; } private void RefreshEnemyLabels() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) ClearEnemyLabels(); if (!TryGetScanOriginPosition(out var position)) { return; } CleanupTrackedEnemiesThrottled(); float activeEnemyLabelDistanceSquared = GetActiveEnemyLabelDistanceSquared(); foreach (Enemy trackedEnemy in trackedEnemies) { if (TryGetEnemyFrameState(trackedEnemy, out var state) && state.IsUsable) { string enemyDisplayNameCached = GetEnemyDisplayNameCached(trackedEnemy); Transform referenceTransform = state.ReferenceTransform; Vector3 val = state.ReferencePosition - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (!(sqrMagnitude > activeEnemyLabelDistanceSquared)) { float enemyLabelYOffsetCached = GetEnemyLabelYOffsetCached(trackedEnemy, referenceTransform); EnemyLabelInfo enemyLabelInfo = RentEnemyLabel(); enemyLabelInfo.Enemy = trackedEnemy; enemyLabelInfo.Name = enemyDisplayNameCached; enemyLabelInfo.ReferenceTransform = referenceTransform; enemyLabelInfo.LabelYOffset = enemyLabelYOffsetCached; enemyLabelInfo.DistanceSquared = sqrMagnitude; enemyLabels.Add(enemyLabelInfo); } } } enemyLabels.Sort(CompareEnemyLabelsByDistance); } private static int CompareEnemyLabelsByDistance(EnemyLabelInfo a, EnemyLabelInfo b) { return a.DistanceSquared.CompareTo(b.DistanceSquared); } private EnemyLabelInfo RentEnemyLabel() { if (enemyLabelPool.Count > 0) { return enemyLabelPool.Pop(); } return new EnemyLabelInfo(); } private void ClearEnemyLabels() { //IL_0099: 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) if (enemyLabels.Count == 0) { return; } for (int i = 0; i < enemyLabels.Count; i++) { EnemyLabelInfo enemyLabelInfo = enemyLabels[i]; if (enemyLabelInfo != null) { enemyLabelInfo.Enemy = null; enemyLabelInfo.Name = string.Empty; enemyLabelInfo.ReferenceTransform = null; enemyLabelInfo.LabelYOffset = 0f; enemyLabelInfo.DistanceSquared = 0f; enemyLabelInfo.CachedDistanceMeters = -1; enemyLabelInfo.CachedShowDistance = false; enemyLabelInfo.CachedIsMasked = false; enemyLabelInfo.PlainText = string.Empty; enemyLabelInfo.RichText = string.Empty; enemyLabelInfo.NextRuntimeRefreshTime = 0f; enemyLabelInfo.CachedLayoutFontSize = int.MinValue; enemyLabelInfo.CachedLayoutSize = Vector2.zero; enemyLabelPool.Push(enemyLabelInfo); } } enemyLabels.Clear(); } private string GetEnemyDisplayNameCached(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return "未知怪物"; } DisplayLanguage instanceLanguage = InstanceLanguage; bool flag = instanceLanguage == DisplayLanguage.中文 && enemyNicknameEnabled != null && enemyNicknameEnabled.Value; if (enemyDisplayNameCacheLanguage != instanceLanguage || enemyDisplayNameCacheNicknames != flag) { enemyDisplayNameCache.Clear(); enemyDisplayNameCacheLanguage = instanceLanguage; enemyDisplayNameCacheNicknames = flag; } int enemyKey = GetEnemyKey(enemy); if (!enemyDisplayNameCache.TryGetValue(enemyKey, out var value) || string.IsNullOrWhiteSpace(value)) { value = GetEnemyDisplayName(enemy, instanceLanguage, flag); enemyDisplayNameCache[enemyKey] = value; } return value; } private Transform GetEnemyCenterTransformCached(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return null; } int enemyKey = GetEnemyKey(enemy); if (enemyCenterTransformCache.TryGetValue(enemyKey, out var value) && (Object)(object)value != (Object)null) { return value; } object? obj = EnemyCenterTransformField?.GetValue(enemy); Transform val = (Transform)((obj is Transform) ? obj : null); if ((Object)(object)val != (Object)null) { enemyCenterTransformCache[enemyKey] = val; } return val; } private void CleanupTrackedEnemiesThrottled() { if (!(Time.unscaledTime < nextEnemyListCleanupTime)) { PruneTrackedCollection(trackedEnemies, trackedEnemySet); nextEnemyListCleanupTime = Time.unscaledTime + 1f; } } private float GetEnemyLabelYOffsetCached(Enemy enemy, Transform centerTransform) { if ((Object)(object)enemy == (Object)null) { return 1.1f; } int enemyKey = GetEnemyKey(enemy); if (!enemyLabelYOffsetCache.TryGetValue(enemyKey, out var value) || value <= 0.01f) { value = GetEnemyLabelYOffset(enemy, centerTransform); enemyLabelYOffsetCache[enemyKey] = value; } return value; } private float GetEnemyLabelYOffset(Enemy enemy, Transform centerTransform) { //IL_0053: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) float result = 1.1f; Transform transform = ((Component)enemy).transform; if ((Object)(object)transform == (Object)null) { return result; } Renderer[] enemyRenderersCached = GetEnemyRenderersCached(enemy); Collider[] enemyCollidersCached = GetEnemyCollidersCached(enemy); float num = float.MinValue; bool flag = false; Renderer[] array = enemyRenderersCached; foreach (Renderer val in array) { if (!((Object)(object)val == (Object)null) && val.enabled) { Bounds bounds = val.bounds; float y = ((Bounds)(ref bounds)).max.y; if (y > num) { num = y; } flag = true; } } if (!flag) { Collider[] array2 = enemyCollidersCached; foreach (Collider val2 in array2) { if (!((Object)(object)val2 == (Object)null) && val2.enabled) { Bounds bounds2 = val2.bounds; float y2 = ((Bounds)(ref bounds2)).max.y; if (y2 > num) { num = y2; } flag = true; } } } if (flag) { Vector3 val3 = (((Object)(object)centerTransform != (Object)null) ? centerTransform.position : transform.position); result = Mathf.Max(0.5f, num - val3.y + 0.3f); } return result; } private Renderer[] GetEnemyRenderersCached(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return Array.Empty(); } int enemyKey = GetEnemyKey(enemy); if (!enemyRendererCache.TryGetValue(enemyKey, out var value) || value == null) { value = ((Component)enemy).GetComponentsInChildren(false) ?? Array.Empty(); enemyRendererCache[enemyKey] = value; } return value; } private Collider[] GetEnemyCollidersCached(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return Array.Empty(); } int enemyKey = GetEnemyKey(enemy); if (!enemyColliderCache.TryGetValue(enemyKey, out var value) || value == null) { value = ((Component)enemy).GetComponentsInChildren(false) ?? Array.Empty(); enemyColliderCache[enemyKey] = value; } return value; } private void ClearEnemyRuntimeCaches() { ClearEnemyLabels(); ClearEnemyProximityTracking(); enemyLabelStyleCache.Clear(); enemyRendererCache.Clear(); enemyColliderCache.Clear(); enemyDisplayNameCache.Clear(); enemyLabelYOffsetCache.Clear(); enemyCenterTransformCache.Clear(); enemyFrameStateCache.Clear(); cachedEnemyStateFrame = -1; nextEnemyLabelRefreshTime = 0f; nextEnemyListCleanupTime = 0f; } private static int GetEnemyKey(Enemy enemy) { return ((Object)enemy).GetInstanceID(); } private static bool IsEnemyDrawableFast(Enemy enemy) { if ((Object)(object)enemy != (Object)null && (Object)(object)((Component)enemy).gameObject != (Object)null) { return ((Component)enemy).gameObject.activeInHierarchy; } return false; } private bool ShouldLimitEnemyLabelsToProximity() { if (enemyProximityAutoShowEnabled != null && enemyProximityAutoShowEnabled.Value && enemyVisibleTimer <= 0f) { return enemyProximityLingerTimers.Count > 0; } return false; } private int GetActiveEnemyLabelDistanceMeters() { int num = GetScanDistanceMeters(); if (enemyProximityLingerTimers.Count > 0) { int num2 = Mathf.Clamp((enemyProximityAutoShowDistance == null) ? 30 : enemyProximityAutoShowDistance.Value, 1, 100); return Mathf.Max(num, num2); } return num; } private float GetActiveEnemyLabelDistanceSquared() { int activeEnemyLabelDistanceMeters = GetActiveEnemyLabelDistanceMeters(); return activeEnemyLabelDistanceMeters * activeEnemyLabelDistanceMeters; } private string GetEnemyDisplayName(Enemy enemy) { DisplayLanguage instanceLanguage = InstanceLanguage; bool useNicknames = instanceLanguage == DisplayLanguage.中文 && enemyNicknameEnabled != null && enemyNicknameEnabled.Value; return GetEnemyDisplayName(enemy, instanceLanguage, useNicknames); } private string GetEnemyDisplayName(Enemy enemy, DisplayLanguage language, bool useNicknames) { if ((Object)(object)enemy == (Object)null) { return "未知怪物"; } object enemyParent = EnemyParentField?.GetValue(enemy); if (TryGetEnemyParentDisplayName(enemyParent, out var name)) { return EnemyNameLocalizer.Translate(name, language, useNicknames); } object obj = EnemyTypeField?.GetValue(enemy); if (obj != null) { string text = obj.ToString(); if (!string.IsNullOrWhiteSpace(text)) { return EnemyNameLocalizer.Translate(text, language, useNicknames); } } string text2 = CleanName(((Object)(object)((Component)enemy).gameObject == (Object)null) ? string.Empty : ((Object)((Component)enemy).gameObject).name); if (!string.IsNullOrWhiteSpace(text2)) { return EnemyNameLocalizer.Translate(text2, language, useNicknames); } return "未知怪物"; } private bool TryGetEnemyParentDisplayName(object enemyParent, out string name) { name = string.Empty; if (enemyParent == null) { return false; } string text = EnemyParentNameField?.GetValue(enemyParent) as string; if (!IsInternalEnemyName(text)) { name = text.Trim(); return true; } object obj = EnemyParentLocalizedNameField?.GetValue(enemyParent); if (obj != null) { try { string text2 = LocalizedAssetGetStringMethod?.Invoke(obj, null) as string; if (!IsInternalEnemyName(text2)) { name = text2.Trim(); return true; } } catch { } } return false; } private static bool IsInternalEnemyName(string name) { if (string.IsNullOrWhiteSpace(name)) { return true; } string a = name.Trim(); if (!string.Equals(a, "ENM", StringComparison.OrdinalIgnoreCase)) { return string.Equals(a, "Enemy", StringComparison.OrdinalIgnoreCase); } return true; } private bool TryGetEnemyFrameState(Enemy enemy, out EnemyFrameState state) { state = default(EnemyFrameState); if ((Object)(object)enemy == (Object)null) { return false; } if (cachedEnemyStateFrame != Time.frameCount) { cachedEnemyStateFrame = Time.frameCount; enemyFrameStateCache.Clear(); } int enemyKey = GetEnemyKey(enemy); if (!enemyFrameStateCache.TryGetValue(enemyKey, out state)) { state = BuildEnemyFrameState(enemy); enemyFrameStateCache[enemyKey] = state; } if (state.IsUsable) { return state.IsAliveAndSpawned; } return false; } private EnemyFrameState BuildEnemyFrameState(Enemy enemy) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) EnemyFrameState result = default(EnemyFrameState); if ((Object)(object)enemy == (Object)null || (Object)(object)((Component)enemy).gameObject == (Object)null) { return result; } int isUsable; if (((Component)enemy).gameObject.activeInHierarchy) { Scene scene = ((Component)enemy).gameObject.scene; isUsable = (((Scene)(ref scene)).IsValid() ? 1 : 0); } else { isUsable = 0; } result.IsUsable = (byte)isUsable != 0; if (!result.IsUsable) { return result; } result.ReferenceTransform = GetEnemyCenterTransformCached(enemy); result.ReferencePosition = (((Object)(object)result.ReferenceTransform != (Object)null) ? result.ReferenceTransform.position : ((Component)enemy).transform.position); object obj = EnemyHealthField?.GetValue(enemy); if (obj != null) { object obj2 = EnemyHealthDeadField?.GetValue(obj); bool flag = default(bool); int num; if (obj2 is bool) { flag = (bool)obj2; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return result; } } object obj3 = EnemyParentField?.GetValue(enemy); if (obj3 != null) { object obj4 = EnemyParentSpawnedField?.GetValue(obj3); if (obj4 is bool && !(bool)obj4) { return result; } } result.IsAliveAndSpawned = true; return result; } private void OnGUI() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) Event current = Event.current; if ((current != null && (int)current.type != 7) || !CanUseLocalScan()) { return; } bool flag = visibleTimer > 0f && labels.Count > 0; bool flag2 = enemyLabels.Count > 0; if (!flag && !flag2) { return; } Camera worldCameraCached = GetWorldCameraCached(); if ((Object)(object)worldCameraCached == (Object)null || !TryGetScanOriginPosition(out var position)) { return; } int maxDistance = GetScanDistanceMeters(); if (flag) { float scanDistanceSquared = GetScanDistanceSquared(); int configuredFontSize = GetConfiguredFontSize(); bool showDistance = ShouldShowDistanceMeters(); bool showValuableName = ShouldShowValuableNames(); bool showValuablePrice = ShouldShowValuablePrices(); RefreshContainmentSetsForFrame(); for (int num = labels.Count - 1; num >= 0; num--) { ScanLabel label = labels[num]; if (!TryRefreshLabel(label, position, scanDistanceSquared, showDistance, showValuableName, showValuablePrice)) { ReturnScanLabel(label); labels.RemoveAt(num); } else { int shrinkPercent = 30; DrawLabel(worldCameraCached, label, maxDistance, configuredFontSize, shrinkPercent); } } } if (flag2) { DrawEnemyWorldLabels(worldCameraCached, position, GetActiveEnemyLabelDistanceMeters()); } } private void DrawEnemyWorldLabels(Camera camera, Vector3 localPosition, int enemyMaxDistance) { //IL_00ab: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_025f: 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_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) if (enemyLabels.Count == 0 || (Object)(object)camera == (Object)null) { return; } bool flag = ShouldLimitEnemyLabelsToProximity(); float num = Mathf.Max(1f, (float)enemyMaxDistance); num *= num; int configuredFontSize = GetConfiguredFontSize(); bool flag2 = ShouldShowDistanceMeters(); for (int i = 0; i < enemyLabels.Count; i++) { EnemyLabelInfo enemyLabelInfo = enemyLabels[i]; Enemy enemy = enemyLabelInfo.Enemy; if (!IsEnemyDrawableFast(enemy)) { continue; } int enemyKey = GetEnemyKey(enemy); if (flag && !enemyProximityLingerTimers.ContainsKey(enemyKey)) { continue; } Vector3 val = (((Object)(object)enemyLabelInfo.ReferenceTransform != (Object)null) ? enemyLabelInfo.ReferenceTransform.position : ((Component)enemy).transform.position); Vector3 val2 = val - localPosition; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude > num) { continue; } float num2 = ((enemyLabelInfo.LabelYOffset > 0.01f) ? enemyLabelInfo.LabelYOffset : 1.1f); Vector3 worldPosition = val + Vector3.up * num2; if (TryWorldToGuiPoint(camera, worldPosition, out var guiPosition, out var cameraDepth)) { int num3 = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude)); bool flag3 = !IsScanTargetUnlockedByProximity((Component)(object)enemy, sqrMagnitude); bool flag4 = flag2 && !flag3; bool num4 = Time.unscaledTime >= enemyLabelInfo.NextRuntimeRefreshTime || enemyLabelInfo.CachedDistanceMeters != num3 || enemyLabelInfo.CachedShowDistance != flag4 || enemyLabelInfo.CachedIsMasked != flag3 || string.IsNullOrWhiteSpace(enemyLabelInfo.PlainText); int distanceScaledFontSize = GetDistanceScaledFontSize(configuredFontSize, 30, cameraDepth, enemyMaxDistance, 48); if (num4) { string text = (flag3 ? BuildMaskedLabelText() : (string.IsNullOrWhiteSpace(enemyLabelInfo.Name) ? GetEnemyDisplayName(enemy) : enemyLabelInfo.Name)); enemyLabelInfo.CachedDistanceMeters = num3; enemyLabelInfo.CachedShowDistance = flag4; enemyLabelInfo.CachedIsMasked = flag3; enemyLabelInfo.PlainText = (flag4 ? $"{text} {num3}m" : text); enemyLabelInfo.RichText = "" + enemyLabelInfo.PlainText + ""; enemyLabelInfo.NextRuntimeRefreshTime = Time.unscaledTime + 0.08f; enemyLabelInfo.CachedLayoutFontSize = int.MinValue; } GUIStyle centeredLabelStyle = GetCenteredLabelStyle(distanceScaledFontSize, shadow: false); Vector2 enemyLabelSizeCached = GetEnemyLabelSizeCached(enemyLabelInfo, centeredLabelStyle); GUI.Label(new Rect(guiPosition.x - enemyLabelSizeCached.x / 2f, guiPosition.y - enemyLabelSizeCached.y / 2f, enemyLabelSizeCached.x + 14f, enemyLabelSizeCached.y + 4f), enemyLabelInfo.RichText, centeredLabelStyle); } } } private GUIStyle GetCenteredLabelStyle(int fontSize, bool shadow) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) int key = (shadow ? (-fontSize) : fontSize); if (enemyLabelStyleCache.TryGetValue(key, out var value)) { return value; } GUIStyle val = new GUIStyle(GUI.skin.label); val.fontSize = fontSize; val.fontStyle = (FontStyle)1; val.alignment = (TextAnchor)4; val.normal.textColor = (shadow ? Color.black : Color.white); enemyLabelStyleCache[key] = val; return val; } private void DrawLabel(Camera camera, ScanLabel label, int maxDistance, int baseFontSize, int shrinkPercent) { //IL_0007: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) if (label != null && TryWorldToGuiPoint(camera, label.Position, out var guiPosition, out var cameraDepth)) { int distanceScaledFontSize = GetDistanceScaledFontSize(baseFontSize, shrinkPercent, cameraDepth, maxDistance, 48); GUIStyle centeredStyle = GetCenteredStyle(distanceScaledFontSize, shadow: false); Vector2 scanLabelSizeCached = GetScanLabelSizeCached(label, centeredStyle); float num = Mathf.Clamp(scanLabelSizeCached.x + 18f, 80f, 420f); float num2 = scanLabelSizeCached.y + 6f; GUI.Label(new Rect(guiPosition.x - num / 2f, guiPosition.y - num2 / 2f, num, num2), label.RichText, centeredStyle); } } private bool TryRefreshLabel(ScanLabel label, Vector3 localPosition, float maxDistanceSquared, bool showDistance, bool showValuableName, bool showValuablePrice) { //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0142: 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_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) if (label == null || (Object)(object)label.Target == (Object)null || !IsObjectUsable(label.Target.gameObject)) { return false; } if (!(Time.unscaledTime >= label.NextRuntimeRefreshTime) && label.CachedShowDistanceMeters == showDistance && (!label.IsValuable || (label.CachedShowValuableNames == showValuableName && label.CachedShowValuablePrices == showValuablePrice))) { return true; } PhysGrabObject physGrabObject = label.PhysGrabObject; if (IsPhysGrabObjectHiddenOrDead(physGrabObject) || IsHeldByLocalPlayer(physGrabObject) || IsObjectInCart(label.Target, physGrabObject) || IsObjectInHaul(label.Target, physGrabObject)) { return false; } if (label.IsCart && showCarts != null && !showCarts.Value) { return false; } if (label.IsCart && !label.IsSmallCart && (showBigCarts == null || !showBigCarts.Value)) { return false; } if (label.IsCart && label.IsSmallCart && (showSmallCarts == null || !showSmallCarts.Value)) { return false; } if (label.IsLotteryCoinBox && (showLotteryCoinBoxes == null || !showLotteryCoinBoxes.Value)) { return false; } Transform transform = label.Target.transform; Vector3 objectAnchorPosition = GetObjectAnchorPosition(transform, physGrabObject); Vector3 val = label.Position; Vector3 val2; if (label.HasAnchorPosition) { val2 = objectAnchorPosition - label.LastAnchorPosition; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.0001f)) { goto IL_0188; } } val = GetObjectCenter(transform, physGrabObject, label.Renderers); label.LastAnchorPosition = objectAnchorPosition; label.HasAnchorPosition = true; goto IL_0188; IL_0188: val2 = val - localPosition; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude > maxDistanceSquared) { return false; } int distanceMeters = Mathf.RoundToInt(Mathf.Sqrt(sqrMagnitude)); if (label.IsValuable) { Component target = label.Target; ValuableObject val3 = (ValuableObject)(object)((target is ValuableObject) ? target : null); if (val3 != null) { if (!RefreshValuableLabelText(label, val3, distanceMeters, sqrMagnitude, showDistance, showValuableName, showValuablePrice)) { return false; } goto IL_01f8; } } if (label.IsItem && !RefreshItemLabelText(label, distanceMeters, sqrMagnitude, showDistance)) { return false; } goto IL_01f8; IL_01f8: label.Position = val; label.DistanceSquared = sqrMagnitude; label.DistanceMeters = distanceMeters; label.NextRuntimeRefreshTime = Time.unscaledTime + 0.08f; TryShareLabelWithTeamIfNeeded(label); return true; } private void TryShareLabelWithTeamIfNeeded(ScanLabel label) { if (label == null || label.SharedWithTeam || label.ShareMode == TeamShareMode.None || shareScansWithTeam == null || !shareScansWithTeam.Value || !IsScanTargetUnlockedByProximity(label.Target, label.DistanceSquared) || label.DistanceMeters > 15) { return; } if (label.ShareMode == TeamShareMode.Valuable) { Component target = label.Target; ValuableObject val = (ValuableObject)(object)((target is ValuableObject) ? target : null); if (val != null) { label.SharedWithTeam = RevealValuableToTeam(val); return; } } if (label.ShareMode == TeamShareMode.LotteryCoinBox) { Component target2 = label.Target; ValuableDiscoverCustom val2 = (ValuableDiscoverCustom)(object)((target2 is ValuableDiscoverCustom) ? target2 : null); if (val2 != null) { label.SharedWithTeam = RevealCustomDiscoverToTeam(val2); } } } private GUIStyle GetCenteredStyle(int size, bool shadow) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0072: 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) Dictionary dictionary = labelStyleCache; if (dictionary.TryGetValue(size, out var value)) { return value; } GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, richText = true, fontSize = size, fontStyle = (FontStyle)1, wordWrap = false, clipping = (TextClipping)0 }; val.normal.textColor = (Color)(shadow ? new Color(0f, 0f, 0f, 0.88f) : Color.white); dictionary[size] = val; return val; } private static int GetDistanceScaledFontSize(int baseSize, int shrinkPercent, float distance, float maxDistance, int maxSize) { baseSize = Mathf.Clamp(baseSize, 8, maxSize); shrinkPercent = Mathf.Clamp(shrinkPercent, 0, 75); if (maxDistance <= 0.1f || shrinkPercent <= 0) { return baseSize; } float num = Mathf.Max(1f, Mathf.Min(maxDistance, 30f)); float num2 = Mathf.Clamp01(distance / num); float num3 = 1f + (float)shrinkPercent / 100f; float num4 = 1f - (float)shrinkPercent / 100f; float num5 = Mathf.Lerp(num3, num4, num2); return Mathf.Clamp(Mathf.RoundToInt((float)baseSize * num5), 8, maxSize); } private static bool IsObjectUsable(GameObject gameObject) { //IL_0012: 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 ((Object)(object)gameObject != (Object)null && gameObject.activeInHierarchy) { Scene scene = gameObject.scene; return ((Scene)(ref scene)).IsValid(); } return false; } private bool IsPhysGrabObjectHiddenOrDead(PhysGrabObject physGrabObject) { if ((Object)(object)physGrabObject == (Object)null) { return false; } if (cachedPhysGrabStateFrame != Time.frameCount) { cachedPhysGrabStateFrame = Time.frameCount; physGrabHiddenOrDeadFrameCache.Clear(); } int instanceID = ((Object)physGrabObject).GetInstanceID(); if (physGrabHiddenOrDeadFrameCache.TryGetValue(instanceID, out var value)) { return value; } bool flag = false; object obj = PhysGrabObjectDeadField?.GetValue(physGrabObject); bool flag2 = default(bool); int num; if (obj is bool) { flag2 = (bool)obj; num = 1; } else { num = 0; } if (((uint)num & (flag2 ? 1u : 0u)) != 0) { flag = true; } else { obj = PhysGrabObjectIsHiddenField?.GetValue(physGrabObject); bool flag3 = default(bool); int num2; if (obj is bool) { flag3 = (bool)obj; num2 = 1; } else { num2 = 0; } if (((uint)num2 & (flag3 ? 1u : 0u)) != 0) { flag = true; } } physGrabHiddenOrDeadFrameCache[instanceID] = flag; return flag; } private bool IsObjectInCart(Component component, PhysGrabObject physGrabObject) { if (!IsObjectInReferenceSet(component, physGrabObject, cartObjectSet)) { return IsPhysGrabObjectMarkedInCart(physGrabObject); } return true; } private bool IsObjectInHaul(Component component, PhysGrabObject physGrabObject) { return IsObjectInReferenceSet(component, physGrabObject, haulObjectSet); } private static void ClearTrackedCollection(List list, HashSet set) where T : Object { list.Clear(); set.Clear(); } private static void PruneTrackedCollection(List list, HashSet set) where T : Object { bool flag = false; for (int num = list.Count - 1; num >= 0; num--) { if (!((Object)(object)list[num] != (Object)null)) { list.RemoveAt(num); flag = true; } } if (!flag) { return; } set.Clear(); for (int i = 0; i < list.Count; i++) { T val = list[i]; if ((Object)(object)val != (Object)null) { set.Add(val); } } } private static bool IsObjectInReferenceSet(Component component, PhysGrabObject physGrabObject, HashSet set) { if (set == null || set.Count == 0) { return false; } GameObject val = (((Object)(object)component == (Object)null) ? null : component.gameObject); GameObject val2 = (((Object)(object)physGrabObject == (Object)null) ? null : ((Component)physGrabObject).gameObject); if (((Object)(object)component != (Object)null && set.Contains(component)) || ((Object)(object)val != (Object)null && set.Contains(val)) || ((Object)(object)physGrabObject != (Object)null && set.Contains(physGrabObject)) || ((Object)(object)val2 != (Object)null && set.Contains(val2))) { return true; } return false; } private static bool IsPhysGrabObjectMarkedInCart(PhysGrabObject physGrabObject) { if ((Object)(object)physGrabObject == (Object)null) { return false; } object obj = PhysGrabObjectImpactDetectorField?.GetValue(physGrabObject); bool flag = default(bool); int num; if (obj != null) { object obj2 = PhysGrabObjectImpactDetectorInCartField?.GetValue(obj); if (obj2 is bool) { flag = (bool)obj2; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static bool IsCartObject(Component component, PhysGrabObject physGrabObject) { if ((Object)(object)component != (Object)null && ((Object)(object)component.GetComponent() != (Object)null || (Object)(object)component.GetComponentInParent() != (Object)null || (Object)(object)component.GetComponentInChildren(false) != (Object)null)) { return true; } if ((Object)(object)physGrabObject != (Object)null) { if (!((Object)(object)((Component)physGrabObject).GetComponent() != (Object)null) && !((Object)(object)((Component)physGrabObject).GetComponentInParent() != (Object)null)) { return (Object)(object)((Component)physGrabObject).GetComponentInChildren(false) != (Object)null; } return true; } return false; } private static bool ShouldScanItem(ItemAttributes item) { if ((Object)(object)item == (Object)null) { return false; } if (ItemEquippableField?.GetValue(item) != null) { return true; } object obj = ItemTypeField?.GetValue(item); if (obj != null && !string.IsNullOrWhiteSpace(obj.ToString())) { return true; } if (!string.IsNullOrWhiteSpace(ReadTrimmedString(ItemNameField?.GetValue(item))) || !string.IsNullOrWhiteSpace(ReadTrimmedString(ItemPromptNameField?.GetValue(item))) || !string.IsNullOrWhiteSpace(ReadTrimmedString(ItemAssetNameField?.GetValue(item))) || !string.IsNullOrWhiteSpace(ReadTrimmedString(ItemInstanceNameField?.GetValue(item))) || !string.IsNullOrWhiteSpace(ReadTrimmedString(ItemTagField?.GetValue(item)))) { return true; } string text = (((Object)(object)((Component)item).gameObject == (Object)null) ? string.Empty : ((Object)((Component)item).gameObject).name.ToLowerInvariant()); for (int i = 0; i < ItemKeywords.Length; i++) { if (text.Contains(ItemKeywords[i])) { return true; } } return false; } private bool ShouldScanItemCached(ItemAttributes item) { if ((Object)(object)item == (Object)null) { return false; } int instanceID = ((Object)item).GetInstanceID(); if (!itemShouldScanCache.TryGetValue(instanceID, out var value)) { value = ShouldScanItem(item); itemShouldScanCache[instanceID] = value; } return value; } private void PrimeTrackedItemCaches(ItemAttributes item) { if (!((Object)(object)item == (Object)null)) { HasValuableObjectCached(item); IsShopItemCached(item); PhysGrabObject physGrabObjectCached = GetPhysGrabObjectCached((Component)(object)item, ItemPhysGrabObjectField); GetCartScanInfoCached((Component)(object)item, physGrabObjectCached); ShouldScanItemCached(item); } } private PhysGrabObject GetPhysGrabObjectCached(Component component, FieldInfo field) { if ((Object)(object)component == (Object)null || field == null) { return null; } int instanceID = ((Object)component).GetInstanceID(); if (!objectPhysGrabCache.TryGetValue(instanceID, out var value)) { object? value2 = field.GetValue(component); value = (PhysGrabObject)((value2 is PhysGrabObject) ? value2 : null); objectPhysGrabCache[instanceID] = value; } return value; } private bool HasValuableObjectCached(ItemAttributes item) { if ((Object)(object)item == (Object)null) { return false; } int instanceID = ((Object)item).GetInstanceID(); if (!itemHasValuableCache.TryGetValue(instanceID, out var value)) { value = (Object)(object)((Component)item).GetComponent() != (Object)null; itemHasValuableCache[instanceID] = value; } return value; } private bool IsShopItemCached(ItemAttributes item) { if ((Object)(object)item == (Object)null) { return false; } int instanceID = ((Object)item).GetInstanceID(); if (!itemShopItemCache.TryGetValue(instanceID, out var value)) { object obj = ItemShopItemField?.GetValue(item); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } value = (byte)((uint)num & (flag ? 1u : 0u)) != 0; itemShopItemCache[instanceID] = value; } return value; } private string GetCustomDiscoverColorHexCached(ValuableDiscoverCustom custom) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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) //IL_005d: 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) if ((Object)(object)custom == (Object)null) { return "FFFFFF"; } int instanceID = ((Object)custom).GetInstanceID(); if (!customDiscoverColorCache.TryGetValue(instanceID, out var value) || string.IsNullOrWhiteSpace(value)) { value = ((ValuableDiscoverCustomColorCornerField?.GetValue(custom) is Color val && val.r + val.g + val.b > 0.05f) ? ColorUtility.ToHtmlStringRGB(val) : "FFFFFF"); customDiscoverColorCache[instanceID] = value; } return value; } private CartScanInfo GetCartScanInfoCached(Component component, PhysGrabObject physGrabObject) { if ((Object)(object)component == (Object)null) { return default(CartScanInfo); } int instanceID = ((Object)component).GetInstanceID(); if (itemCartInfoCache.TryGetValue(instanceID, out var value)) { return value; } value.IsCart = IsCartObject(component, physGrabObject); if (value.IsCart && (Object)(object)physGrabObject != (Object)null) { PhysGrabCart val = ((Component)physGrabObject).GetComponent() ?? ((Component)physGrabObject).GetComponentInParent() ?? ((Component)physGrabObject).GetComponentInChildren(); bool flag = default(bool); int num; if ((Object)(object)val != (Object)null) { object obj = PhysGrabCartIsSmallField?.GetValue(val); if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } } else { num = 0; } value.IsSmallCart = (byte)((uint)num & (flag ? 1u : 0u)) != 0; } itemCartInfoCache[instanceID] = value; return value; } private static Renderer[] GetUsableRenderers(Component root) { if (!((Object)(object)root == (Object)null)) { return root.GetComponentsInChildren(false); } return Array.Empty(); } private Renderer[] GetUsableRenderersCached(Component root) { if ((Object)(object)root == (Object)null) { return Array.Empty(); } int instanceID = ((Object)root).GetInstanceID(); if (!objectRendererCache.TryGetValue(instanceID, out var value) || value == null) { value = GetUsableRenderers(root); objectRendererCache[instanceID] = value; } return value; } private bool IsHeldByLocalPlayer(PhysGrabObject physGrabObject) { if ((Object)(object)physGrabObject == (Object)null) { return false; } PlayerAvatar localPlayerCached = GetLocalPlayerCached(); if ((Object)(object)localPlayerCached == (Object)null) { return false; } int instanceID = ((Object)physGrabObject).GetInstanceID(); RefreshLocalHeldObjects(localPlayerCached); if (localHeldPhysGrabObjects.Contains(physGrabObject)) { localHeldStateCache[instanceID] = true; return true; } if (localHeldStateCache.TryGetValue(instanceID, out var value)) { return value; } if (PhysGrabObjectPlayerGrabbingField?.GetValue(physGrabObject) is IEnumerable enumerable) { foreach (object item in enumerable) { if (IsLocalGrabberObject(item, localPlayerCached)) { localHeldPhysGrabObjects.Add(physGrabObject); localHeldStateCache[instanceID] = true; return true; } } } localHeldStateCache[instanceID] = false; return false; } private void RefreshLocalHeldObjects(PlayerAvatar localPlayer) { if ((Object)(object)localPlayer == (Object)null || Time.unscaledTime < nextLocalHeldRefreshTime) { return; } localHeldPhysGrabObjects.Clear(); localHeldStateCache.Clear(); foreach (PhysGrabber item in GetGrabberObjectsCached()) { if ((Object)(object)item == (Object)null) { continue; } object obj = PhysGrabberGrabbedField?.GetValue(item); if (!(obj is bool) || (bool)obj) { object? obj2 = PhysGrabberGrabbedPhysGrabObjectField?.GetValue(item); PhysGrabObject val = (PhysGrabObject)((obj2 is PhysGrabObject) ? obj2 : null); if (!((Object)(object)val == (Object)null) && IsLocalGrabberObject(item, localPlayer)) { localHeldPhysGrabObjects.Add(val); localHeldStateCache[((Object)val).GetInstanceID()] = true; } } } nextLocalHeldRefreshTime = Time.unscaledTime + 0.12f; } private List GetGrabberObjectsCached() { if (Time.unscaledTime < nextGrabberRefreshTime) { return grabberObjectsCache; } PruneTrackedCollection(trackedGrabbers, trackedGrabberSet); grabberObjectsCache.Clear(); for (int i = 0; i < trackedGrabbers.Count; i++) { PhysGrabber val = trackedGrabbers[i]; if ((Object)(object)val != (Object)null) { grabberObjectsCache.Add(val); } } nextGrabberRefreshTime = Time.unscaledTime + 0.12f; return grabberObjectsCache; } private bool IsLocalGrabberObject(object grabberObject, PlayerAvatar localPlayer) { if (grabberObject == null || (Object)(object)localPlayer == (Object)null) { return false; } if (grabberObject == localPlayer) { return true; } Component val = (Component)((grabberObject is Component) ? grabberObject : null); if (val != null && (val.GetComponentInParent() == localPlayer || val.GetComponentInChildren(true) == localPlayer)) { return true; } PhysGrabber val2 = (PhysGrabber)((grabberObject is PhysGrabber) ? grabberObject : null); if (val2 != null && PhysGrabberPlayerAvatarField?.GetValue(val2) == localPlayer) { return true; } Type type = grabberObject.GetType(); if (!playerAvatarFieldCache.TryGetValue(type, out var value)) { value = type.GetField("playerAvatar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); playerAvatarFieldCache[type] = value; } return value?.GetValue(grabberObject) == localPlayer; } private static Vector3 GetObjectAnchorPosition(Transform fallback, PhysGrabObject physGrabObject) { //IL_0025: 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_0013: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)physGrabObject != (Object)null)) { if (!((Object)(object)fallback == (Object)null)) { return fallback.position; } return Vector3.zero; } return ((Component)physGrabObject).transform.position; } private static Vector3 GetObjectCenter(Transform fallback, PhysGrabObject physGrabObject) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) return GetObjectCenter(fallback, physGrabObject, null); } private static Vector3 GetObjectCenter(Transform fallback, PhysGrabObject physGrabObject, Renderer[] renderers) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) Vector3 objectAnchorPosition = GetObjectAnchorPosition(fallback, physGrabObject); if (TryGetVisualBoundsCenter((Component)(object)fallback, objectAnchorPosition, renderers, out var center)) { return center; } return objectAnchorPosition; } private static bool TryGetVisualBoundsCenter(Component root, Vector3 anchor, out Vector3 center) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return TryGetVisualBoundsCenter(root, anchor, null, out center); } private static bool TryGetVisualBoundsCenter(Component root, Vector3 anchor, Renderer[] cachedRenderers, out Vector3 center) { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_009a: 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_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) center = Vector3.zero; if ((Object)(object)root == (Object)null) { return false; } Bounds val = default(Bounds); bool flag = false; Renderer[] array = cachedRenderers ?? GetUsableRenderers(root); foreach (Renderer val2 in array) { if ((Object)(object)val2 == (Object)null || !val2.enabled) { continue; } Bounds bounds = val2.bounds; Vector3 val3 = ((Bounds)(ref bounds)).size; if (((Vector3)(ref val3)).sqrMagnitude <= 0.0001f) { continue; } val3 = ((Bounds)(ref bounds)).extents; float num = Mathf.Max(1.5f, ((Vector3)(ref val3)).magnitude * 4f); val3 = ((Bounds)(ref bounds)).center - anchor; if (!(((Vector3)(ref val3)).sqrMagnitude > num * num)) { if (!flag) { val = bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(bounds); } } } if (!flag) { return false; } center = ((Bounds)(ref val)).center; return true; } private static bool TryGetBoundsCenter(Component root, out Vector3 center) { //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_0049: 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_00a7: 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_009e: Unknown result type (might be due to invalid IL or missing references) center = Vector3.zero; if ((Object)(object)root == (Object)null) { return false; } Bounds val = default(Bounds); bool flag = false; Renderer[] componentsInChildren = root.GetComponentsInChildren(false); foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && val2.enabled) { if (!flag) { val = val2.bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(val2.bounds); } } } if (!flag) { Collider[] componentsInChildren2 = root.GetComponentsInChildren(false); foreach (Collider val3 in componentsInChildren2) { if (!((Object)(object)val3 == (Object)null) && val3.enabled) { if (!flag) { val = val3.bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(val3.bounds); } } } } if (!flag) { return false; } center = ((Bounds)(ref val)).center; return true; } private static void FillCartObjectSet(HashSet result) { result.Clear(); PruneTrackedCollection(trackedCarts, trackedCartSet); foreach (PhysGrabCart trackedCart in trackedCarts) { if ((Object)(object)trackedCart == (Object)null) { continue; } AddEnumerableObjects(result, PhysGrabCartItemsInCartField?.GetValue(trackedCart)); object obj = PhysGrabCartInCartField?.GetValue(trackedCart); if (!(((obj == null) ? null : PhysGrabInCartObjectsField?.GetValue(obj)) is IEnumerable enumerable)) { continue; } foreach (object item in enumerable) { AddReferenceObject(result, PhysGrabInCartCartObjectPhysGrabObjectField?.GetValue(item)); } } } private void RefreshContainmentSetsForFrame() { if (containmentSetFrame != Time.frameCount) { containmentSetFrame = Time.frameCount; if (!(Time.unscaledTime < nextContainmentRefreshTime)) { nextContainmentRefreshTime = Time.unscaledTime + 0.12f; FillCartAndHaulObjectSets(); } } } private void ForceRefreshContainmentSets() { containmentSetFrame = Time.frameCount; nextContainmentRefreshTime = Time.unscaledTime + 0.12f; FillCartAndHaulObjectSets(); } private void FillCartAndHaulObjectSets() { FillCartObjectSet(cartObjectSet); FillDollarHaulObjectSet(haulObjectSet); } private static void FillDollarHaulObjectSet(HashSet result) { result.Clear(); object obj = RoundDirectorInstanceField?.GetValue(null); if (obj != null) { AddEnumerableObjects(result, RoundDirectorDollarHaulListField?.GetValue(obj)); AddEnumerableObjects(result, RoundDirectorValuableBoxHaulListField?.GetValue(obj)); } } private static void AddEnumerableObjects(HashSet result, object rawList) { if (!(rawList is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { AddReferenceObject(result, item); } } private static void AddReferenceObject(HashSet result, object item) { if (item != null) { result.Add(item); GameObject objectGameObject = GetObjectGameObject(item); if ((Object)(object)objectGameObject != (Object)null) { result.Add(objectGameObject); } } } private static GameObject GetObjectGameObject(object value) { GameObject val = (GameObject)((value is GameObject) ? value : null); if (val != null) { return val; } Component val2 = (Component)((value is Component) ? value : null); if (val2 != null) { return val2.gameObject; } return null; } private static float GetValuableCurrentValue(ValuableObject valuable) { if ((Object)(object)valuable == (Object)null) { return 0f; } object obj = ValuableValueSetField?.GetValue(valuable); if (obj is bool && !(bool)obj) { return 0f; } if (ValuableCurrentValueField?.GetValue(valuable) is float num) { return Mathf.Max(0f, num); } return 0f; } private float GetValuableCurrentValueCached(ValuableObject valuable) { if ((Object)(object)valuable == (Object)null) { return 0f; } int instanceID = ((Object)valuable).GetInstanceID(); if (valuableValueCache.TryGetValue(instanceID, out var value) && valuableValueCacheExpiry.TryGetValue(instanceID, out var value2) && Time.unscaledTime < value2) { return value; } float valuableCurrentValue = GetValuableCurrentValue(valuable); valuableValueCache[instanceID] = valuableCurrentValue; valuableValueCacheExpiry[instanceID] = Time.unscaledTime + 0.12f; return valuableCurrentValue; } private static string GetItemDisplayName(ItemAttributes item) { string text = ReadTrimmedString(ItemNameField?.GetValue(item)); if (!string.IsNullOrWhiteSpace(text)) { return TranslateItemName(text); } text = ReadTrimmedString(ItemPromptNameField?.GetValue(item)); if (!string.IsNullOrWhiteSpace(text)) { return TranslateItemName(text); } text = ReadTrimmedString(ItemAssetNameField?.GetValue(item)); if (!string.IsNullOrWhiteSpace(text)) { return TranslateItemName(text); } text = ReadTrimmedString(ItemInstanceNameField?.GetValue(item)); if (!string.IsNullOrWhiteSpace(text)) { return TranslateItemName(text); } text = ReadTrimmedString(ItemTagField?.GetValue(item)); if (!string.IsNullOrWhiteSpace(text)) { return TranslateItemName(text); } text = CleanName(((Object)(object)item == (Object)null) ? string.Empty : ((Object)((Component)item).gameObject).name); if (!string.IsNullOrWhiteSpace(text)) { return TranslateItemName(text); } return TranslateItemName(string.Empty); } private string GetValuableDisplayNameCached(ValuableObject valuable) { if ((Object)(object)valuable == (Object)null) { return TranslateItemName(string.Empty); } EnsureObjectDisplayNameCacheLanguage(); int instanceID = ((Object)valuable).GetInstanceID(); if (!objectDisplayNameCache.TryGetValue(instanceID, out var value) || string.IsNullOrWhiteSpace(value)) { value = TranslateItemName(((Object)(object)((Component)valuable).gameObject == (Object)null) ? string.Empty : ((Object)((Component)valuable).gameObject).name); objectDisplayNameCache[instanceID] = value; } return value; } private string GetItemDisplayNameCached(ItemAttributes item) { if ((Object)(object)item == (Object)null) { return TranslateItemName(string.Empty); } EnsureObjectDisplayNameCacheLanguage(); int instanceID = ((Object)item).GetInstanceID(); if (!objectDisplayNameCache.TryGetValue(instanceID, out var value) || string.IsNullOrWhiteSpace(value)) { value = GetItemDisplayName(item); objectDisplayNameCache[instanceID] = value; } return value; } private void EnsureObjectDisplayNameCacheLanguage() { DisplayLanguage instanceLanguage = InstanceLanguage; if (objectDisplayNameCacheLanguage != instanceLanguage) { objectDisplayNameCacheLanguage = instanceLanguage; objectDisplayNameCache.Clear(); } } private static string ReadTrimmedString(object value) { if (value == null) { return string.Empty; } string text = (value as string) ?? value.ToString(); if (!string.IsNullOrWhiteSpace(text)) { return text.Trim(); } return string.Empty; } private static string TranslateItemName(string rawName) { string text = CleanName(rawName); rawName = ItemNameLocalizer.CleanDisplayName(text); if (string.IsNullOrWhiteSpace(rawName)) { rawName = (string.IsNullOrWhiteSpace(text) ? "未知物品" : text); } if (InstanceLanguage == DisplayLanguage.English) { return rawName; } return ItemNameLocalizer.Translate(rawName); } private static string CleanName(string rawName) { if (string.IsNullOrWhiteSpace(rawName)) { return "未知物品"; } string input = rawName.Replace("(Clone)", string.Empty).Trim(); input = WhitespaceRegex.Replace(input, " "); if (!string.IsNullOrWhiteSpace(input)) { return input; } return "未知物品"; } private static string FormatMoney(int value) { return SemiFunc.DollarGetString(Mathf.Max(0, value)); } private string BuildValuableLabelText(string name, int value, int distanceMeters) { return BuildValuableLabelText(name, value, distanceMeters, ShouldShowValuableNames(), ShouldShowValuablePrices(), ShouldShowDistanceMeters()); } private static string BuildValuableLabelText(string name, int value, int distanceMeters, bool showName, bool showPrice, bool showDistance) { string priceText = (showPrice ? FormatMoney(value) : null); return BuildValuableLabelText(name, priceText, distanceMeters, showName, showPrice, showDistance); } private static string BuildValuableLabelText(string name, string priceText, int distanceMeters, bool showName, bool showPrice, bool showDistance) { string text = ((!showName) ? null : (string.IsNullOrWhiteSpace(name) ? "Unknown" : name.Trim())); string text2 = null; if (showPrice) { text2 = ((string.IsNullOrWhiteSpace(priceText) || priceText == "?") ? "?" : ("$" + priceText)); } string text3 = (showDistance ? $"{Mathf.Max(0, distanceMeters)}m" : null); if (text != null) { if (text2 != null) { if (text3 == null) { return text + " " + text2; } return text + " " + text2 + " " + text3; } if (text3 == null) { return text; } return text + " " + text3; } if (text2 != null) { if (text3 == null) { return text2; } return text2 + " " + text3; } return text3 ?? string.Empty; } private static string BuildMaskedLabelText() { return "?"; } private string BuildItemLabelText(string name, int distanceMeters, bool isLotteryCoinBox = false, bool isCart = false) { if (string.IsNullOrWhiteSpace(name)) { return string.Empty; } return BuildItemLabelText(name, distanceMeters, ShouldShowDistanceMeters()); } private static string BuildItemLabelText(string name, int distanceMeters, bool showDistance) { if (showDistance) { return $"{name.Trim()} {Mathf.Max(0, distanceMeters)}m"; } return name.Trim(); } private void RefreshFrameScanSettings() { if (cachedScanSettingsFrame != Time.frameCount) { cachedScanSettingsFrame = Time.frameCount; cachedScanDistanceMeters = Mathf.Clamp((scanDistanceMeters == null) ? 15 : scanDistanceMeters.Value, 1, 100); cachedScanDistanceSquared = cachedScanDistanceMeters * cachedScanDistanceMeters; cachedScanFontSize = Mathf.Clamp((fontSize == null) ? 28 : fontSize.Value, 8, 48); cachedScanExploreMode = scanExploreMode == null || scanExploreMode.Value; cachedShowDistanceMeters = showDistanceMeters == null || showDistanceMeters.Value; cachedShowValuableNames = showValuableNames == null || showValuableNames.Value; cachedShowValuablePrices = showValuablePrices == null || showValuablePrices.Value; } } private bool IsScanExploreModeEnabled() { RefreshFrameScanSettings(); return cachedScanExploreMode; } private bool ShouldShowDistanceMeters() { RefreshFrameScanSettings(); return cachedShowDistanceMeters; } private bool ShouldShowValuableNames() { RefreshFrameScanSettings(); return cachedShowValuableNames; } private bool ShouldShowValuablePrices() { RefreshFrameScanSettings(); return cachedShowValuablePrices; } private static string WrapItemTextColor(string text, string colorHex) { return "" + text + ""; } private bool RefreshValuableLabelText(ScanLabel label, ValuableObject valuable, int distanceMeters, float distanceSquared, bool showDistance, bool showName, bool showPrice) { bool flag = label == null || !IsScanTargetUnlockedByProximity(label.Target, distanceSquared); int num = ((showPrice && !flag) ? Mathf.RoundToInt(GetValuableCurrentValueCached(valuable)) : 0); string text = (flag ? BuildMaskedLabelText() : BuildValuableLabelText(label.DisplayName, num, distanceMeters, showName, showPrice, showDistance)); if (label.CachedTextDistanceMeters == distanceMeters && label.CachedTextValue == num && label.CachedShowDistanceMeters == showDistance && label.CachedShowValuableNames == showName && label.CachedShowValuablePrices == showPrice && label.CachedIsMasked == flag && !string.IsNullOrWhiteSpace(label.PlainText)) { return true; } if (string.IsNullOrWhiteSpace(text)) { return false; } label.PlainText = text; label.RichText = "" + text + ""; label.CachedTextDistanceMeters = distanceMeters; label.CachedTextValue = num; label.CachedShowDistanceMeters = showDistance; label.CachedShowValuableNames = showName; label.CachedShowValuablePrices = showPrice; label.CachedIsMasked = flag; label.CachedLayoutFontSize = int.MinValue; return true; } private bool IsScanTargetUnlockedByProximity(Component target, float distanceSquared) { if (!IsScanExploreModeEnabled()) { return true; } if ((Object)(object)target == (Object)null) { return false; } int instanceID = ((Object)target).GetInstanceID(); if (proximityUnlockedScanTargetIds.Contains(instanceID)) { return true; } float num = ((target is Enemy) ? 400f : ((!(target is ValuableObject)) ? 36f : 16f)); float num2 = num; if (distanceSquared > num2) { return false; } proximityUnlockedScanTargetIds.Add(instanceID); return true; } private bool RefreshItemLabelText(ScanLabel label, int distanceMeters, float distanceSquared, bool showDistance) { if (label == null) { return false; } bool flag = !IsScanTargetUnlockedByProximity(label.Target, distanceSquared); if (label.CachedTextDistanceMeters == distanceMeters && label.CachedShowDistanceMeters == showDistance && label.CachedIsMasked == flag && !string.IsNullOrWhiteSpace(label.PlainText)) { return true; } string text = (flag ? BuildMaskedLabelText() : BuildItemLabelText(label.DisplayName, distanceMeters, showDistance)); if (string.IsNullOrWhiteSpace(text)) { return false; } label.PlainText = text; label.RichText = WrapItemTextColor(text, label.ColorHex); label.CachedTextDistanceMeters = distanceMeters; label.CachedShowDistanceMeters = showDistance; label.CachedIsMasked = flag; label.CachedLayoutFontSize = int.MinValue; return true; } private Vector2 GetScanLabelSizeCached(ScanLabel label, GUIStyle style) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (label.CachedLayoutFontSize == style.fontSize && ((Vector2)(ref label.CachedLayoutSize)).sqrMagnitude > 0f) { return label.CachedLayoutSize; } labelContent.text = label.PlainText; Vector2 val = style.CalcSize(labelContent); label.CachedLayoutFontSize = style.fontSize; label.CachedLayoutSize = val; return val; } private Vector2 GetEnemyLabelSizeCached(EnemyLabelInfo info, GUIStyle style) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (info.CachedLayoutFontSize == style.fontSize && ((Vector2)(ref info.CachedLayoutSize)).sqrMagnitude > 0f) { return info.CachedLayoutSize; } labelContent.text = info.PlainText; Vector2 val = style.CalcSize(labelContent); info.CachedLayoutFontSize = style.fontSize; info.CachedLayoutSize = val; return val; } private bool CanUseLocalScan() { PlayerAvatar localPlayer; return TryGetScanLocalPlayer(out localPlayer); } private bool TryGetScanLocalPlayer(out PlayerAvatar localPlayer) { if (cachedScanLocalPlayerFrame == Time.frameCount) { localPlayer = cachedScanLocalPlayer; return cachedScanLocalPlayerReady; } localPlayer = GetLocalPlayerCached(); bool flag = IsPlayerAvatarReadyForScan(localPlayer); cachedScanLocalPlayerFrame = Time.frameCount; cachedScanLocalPlayerReady = flag; cachedScanLocalPlayer = (flag ? localPlayer : null); localPlayer = cachedScanLocalPlayer; return flag; } private bool TryGetScanOriginPosition(out Vector3 position) { //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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; if (!TryGetScanLocalPlayer(out var localPlayer)) { return false; } object? obj = PlayerTransformField?.GetValue(localPlayer); Transform val = (Transform)((obj is Transform) ? obj : null); position = (((Object)(object)val == (Object)null) ? ((Component)localPlayer).transform.position : val.position); cachedLocalPosition = position; cachedLocalPositionFrame = Time.frameCount; return true; } private bool TryGetLocalPosition(out Vector3 position) { //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_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (cachedLocalPositionFrame == Time.frameCount) { position = cachedLocalPosition; return true; } PlayerAvatar localPlayerCached = GetLocalPlayerCached(); if ((Object)(object)localPlayerCached != (Object)null) { object? obj = PlayerTransformField?.GetValue(localPlayerCached); Transform val = (Transform)((obj is Transform) ? obj : null); position = (((Object)(object)val == (Object)null) ? ((Component)localPlayerCached).transform.position : val.position); cachedLocalPosition = position; cachedLocalPositionFrame = Time.frameCount; return true; } Camera worldCameraCached = GetWorldCameraCached(); if ((Object)(object)worldCameraCached != (Object)null) { position = ((Component)worldCameraCached).transform.position; cachedLocalPosition = position; cachedLocalPositionFrame = Time.frameCount; return true; } position = Vector3.zero; return false; } private PlayerAvatar GetLocalPlayerCached() { if (IsPlayerAvatarUsable(cachedLocalPlayer) && (cachedLocalPlayerIsLocal || IsPlayerAvatarLocal(cachedLocalPlayer))) { cachedLocalPlayerIsLocal = true; return cachedLocalPlayer; } if (Time.unscaledTime < nextLocalPlayerRefreshTime) { return null; } cachedLocalPlayer = GetLocalPlayer(out var isLocalPlayer); cachedLocalPlayerIsLocal = isLocalPlayer; nextLocalPlayerRefreshTime = Time.unscaledTime + 0.25f; return cachedLocalPlayer; } private static PlayerAvatar GetLocalPlayer(out bool isLocalPlayer) { isLocalPlayer = false; PlayerAvatar[] array = Object.FindObjectsOfType(); foreach (PlayerAvatar val in array) { if (IsPlayerAvatarUsable(val) && IsPlayerAvatarLocal(val)) { isLocalPlayer = true; return val; } } return null; } private static bool IsPlayerAvatarUsable(PlayerAvatar player) { //IL_002a: 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) if ((Object)(object)player != (Object)null && (Object)(object)((Component)player).gameObject != (Object)null && ((Component)player).gameObject.activeInHierarchy) { Scene scene = ((Component)player).gameObject.scene; return ((Scene)(ref scene)).IsValid(); } return false; } private static bool IsPlayerAvatarLocal(PlayerAvatar player) { bool flag = default(bool); int num; if ((Object)(object)player != (Object)null) { object obj = PlayerIsLocalField?.GetValue(player); if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static bool IsPlayerAvatarReadyForScan(PlayerAvatar player) { if (!IsPlayerAvatarUsable(player) || !IsPlayerAvatarLocal(player)) { return false; } object obj = PlayerDeadSetField?.GetValue(player); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return false; } obj = PlayerSpectatingField?.GetValue(player); bool flag2 = default(bool); int num2; if (obj is bool) { flag2 = (bool)obj; num2 = 1; } else { num2 = 0; } if (((uint)num2 & (flag2 ? 1u : 0u)) != 0) { return false; } obj = PlayerIsDisabledField?.GetValue(player); bool flag3 = default(bool); int num3; if (obj is bool) { flag3 = (bool)obj; num3 = 1; } else { num3 = 0; } if (((uint)num3 & (flag3 ? 1u : 0u)) != 0) { return false; } return true; } private static Camera GetWorldCamera() { Camera main = Camera.main; if (IsCameraUsable(main)) { return main; } Camera val = Object.FindObjectOfType(); if (!IsCameraUsable(val)) { return null; } return val; } private Camera GetWorldCameraCached() { if (IsCameraUsable(cachedCamera)) { return cachedCamera; } cachedCamera = GetWorldCamera(); return cachedCamera; } private static bool IsCameraUsable(Camera camera) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)camera != (Object)null && (Object)(object)((Component)camera).gameObject != (Object)null) { Scene scene = ((Component)camera).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { return ((Behaviour)camera).isActiveAndEnabled; } } return false; } private int GetScanHoldSeconds() { return 5; } private int GetScanDistanceMeters() { RefreshFrameScanSettings(); return cachedScanDistanceMeters; } private float GetScanDistanceSquared() { RefreshFrameScanSettings(); return cachedScanDistanceSquared; } private int GetConfiguredFontSize() { RefreshFrameScanSettings(); return cachedScanFontSize; } private bool TryWorldToGuiPoint(Camera camera, Vector3 worldPosition, out Vector2 guiPosition) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) float cameraDepth; return TryWorldToGuiPoint(camera, worldPosition, out guiPosition, out cameraDepth); } private bool TryWorldToGuiPoint(Camera camera, Vector3 worldPosition, out Vector2 guiPosition, out float cameraDepth) { //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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) guiPosition = Vector2.zero; cameraDepth = 0f; if ((Object)(object)camera == (Object)null) { return false; } Vector3 val = camera.WorldToScreenPoint(worldPosition); if (val.z <= 0f) { return false; } cameraDepth = val.z; GetGuiProjectionScale(camera, out var scaleX, out var scaleY); float num = val.x * scaleX; float num2 = val.y * scaleY; guiPosition = new Vector2(num, (float)Screen.height - num2); return true; } private void GetGuiProjectionScale(Camera camera, out float scaleX, out float scaleY) { if (cachedGuiScaleFrame == Time.frameCount && cachedGuiScaleCamera == camera) { scaleX = cachedGuiScaleX; scaleY = cachedGuiScaleY; return; } float num = ((camera.pixelWidth > 0) ? camera.pixelWidth : Screen.width); float num2 = ((camera.pixelHeight > 0) ? camera.pixelHeight : Screen.height); if ((Object)(object)camera.targetTexture != (Object)null) { num = Mathf.Max(1, ((Texture)camera.targetTexture).width); num2 = Mathf.Max(1, ((Texture)camera.targetTexture).height); } cachedGuiScaleFrame = Time.frameCount; cachedGuiScaleCamera = camera; cachedGuiScaleX = (float)Screen.width / Mathf.Max(1f, num); cachedGuiScaleY = (float)Screen.height / Mathf.Max(1f, num2); scaleX = cachedGuiScaleX; scaleY = cachedGuiScaleY; } internal static string KeybindNameToBindingPath(string name) { if (string.IsNullOrEmpty(name)) { return "/f"; } if (name.Length == 1 && name[0] >= '0' && name[0] <= '9') { return "/" + name; } if (name.Length == 1 && char.IsLetter(name[0])) { return "/" + name.ToLowerInvariant(); } if (name.Length > 1 && name[0] == 'F' && int.TryParse(name.Substring(1), out var _)) { return "/" + name; } return name switch { "Space" => "/space", "Enter" => "/enter", "Tab" => "/tab", "LeftShift" => "/leftShift", "RightShift" => "/rightShift", "LeftControl" => "/leftCtrl", "RightControl" => "/rightCtrl", _ => "/" + char.ToLower(name[0]) + name.Substring(1), }; } internal static void RebindScanKey() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Instance == (Object)null) && Instance.scanKey != null && !((Object)(object)InputManager.instance == (Object)null)) { EnsureInputActionsRegistered(); string value = Instance.scanKey.Value; if (!(lastAppliedScanKey == value)) { lastAppliedScanKey = value; InputManager.instance.Rebind(ScanInputKey, KeybindNameToBindingPath(value)); } } } private void ApplyHarmonyPatches() { PatchPostfix(typeof(InputManager), "InitializeInputs", "InputManagerInitializeInputsPostfix"); PatchPostfix(typeof(PlayerController), "Start", "PlayerControllerStartPostfix"); PatchPostfix(typeof(Enemy), "Awake", "EnemyAwakePostfix"); PatchPostfix(typeof(EnemyParent), "Awake", "EnemyParentAwakePostfix"); PatchPostfix(typeof(ValuableObject), "Start", "ValuableObjectStartPostfix"); PatchPostfix(typeof(ItemAttributes), "Start", "ItemAttributesStartPostfix"); PatchPostfix(typeof(EnemyParent), "SpawnRPC", "EnemyParentSpawnRPCPostfix"); PatchPostfix(typeof(PhysGrabCart), "Start", "PhysGrabCartStartPostfix"); PatchPostfix(typeof(ValuableDiscoverCustom), "Awake", "ValuableDiscoverCustomAwakePostfix"); PatchPostfix(typeof(PhysGrabber), "Start", "PhysGrabberStartPostfix"); PatchPrefix(typeof(LevelGenerator), "StartRoomGeneration", "LevelGeneratorStartRoomGenerationPrefix"); PatchPostfix(typeof(LevelGenerator), "GenerateDone", "LevelGeneratorGenerateDonePostfix"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valuables scanner Harmony patches applied."); } private void PatchPrefix(Type originalType, string originalName, string patchName) { PatchMethod(originalType, originalName, patchName, prefix: true); } private void PatchPostfix(Type originalType, string originalName, string patchName) { PatchMethod(originalType, originalName, patchName, prefix: false); } private void PatchMethod(Type originalType, string originalName, string patchName, bool prefix) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(originalType, originalName, (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(ZichenValuablesScannerPlugin), patchName, (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to find Harmony patch target: " + originalType?.Name + "." + originalName + " -> " + patchName)); } else { HarmonyMethod val = new HarmonyMethod(methodInfo2); if (prefix) { harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void EnsureInputActionsRegistered() { //IL_007f: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) InputManager instance = InputManager.instance; if ((Object)(object)instance == (Object)null) { return; } Dictionary dictionary = (((Object)(object)registeredInputManager == (Object)(object)instance) ? registeredInputActions : null); if (dictionary == null) { dictionary = Traverse.Create((object)instance).Field>("inputActions").Value; registeredInputManager = instance; registeredInputActions = dictionary; } if (dictionary != null && (!inputActionsRegistered || !((Object)(object)registeredInputManager == (Object)(object)instance) || !dictionary.TryGetValue(ScanInputKey, out var value) || value == null || !value.enabled)) { if (!dictionary.TryGetValue(ScanInputKey, out var value2)) { value2 = new InputAction("ValuablesScannerScan", (InputActionType)0, KeybindNameToBindingPath(((Object)(object)Instance != (Object)null) ? Instance.scanKey.Value : "F"), (string)null, (string)null, (string)null); dictionary.Add(ScanInputKey, value2); lastAppliedScanKey = (((Object)(object)Instance != (Object)null) ? Instance.scanKey.Value : "F"); } value2.Enable(); registeredInputManager = instance; registeredInputActions = dictionary; inputActionsRegistered = true; } } private static float ClampScanInterval(float value) { return Mathf.Clamp(value, 1f, 5f); } private static void InputManagerInitializeInputsPostfix() { if (IsStaticModEnabled()) { EnsureInputActionsRegistered(); } } private static void PlayerControllerStartPostfix() { if (IsStaticModEnabled()) { RebindScanKey(); } } private static void ValuableObjectStartPostfix(ValuableObject __instance) { if (IsStaticModEnabled()) { AddTrackedUnique(trackedValuables, trackedValuableSet, __instance); } } private static void ItemAttributesStartPostfix(ItemAttributes __instance) { if (IsStaticModEnabled()) { AddTrackedUnique(trackedItems, trackedItemSet, __instance); Instance?.PrimeTrackedItemCaches(__instance); } } private static void EnemyParentSpawnRPCPostfix(EnemyParent __instance) { if (IsStaticModEnabled()) { TrackEnemyFromParent(__instance); } } private static void EnemyAwakePostfix(Enemy __instance) { if (IsStaticModEnabled()) { TrackEnemy(__instance); } } private static void EnemyParentAwakePostfix(EnemyParent __instance) { if (IsStaticModEnabled()) { TrackEnemyFromParent(__instance); } } private static void PhysGrabCartStartPostfix(PhysGrabCart __instance) { if (IsStaticModEnabled()) { AddTrackedUnique(trackedCarts, trackedCartSet, __instance); } } private static void ValuableDiscoverCustomAwakePostfix(ValuableDiscoverCustom __instance) { if (IsStaticModEnabled()) { AddTrackedUnique(trackedDiscoverCustoms, trackedDiscoverCustomSet, __instance); } } private static void PhysGrabberStartPostfix(PhysGrabber __instance) { if (IsStaticModEnabled()) { AddTrackedUnique(trackedGrabbers, trackedGrabberSet, __instance); } } private static void LevelGeneratorStartRoomGenerationPrefix() { if (IsStaticModEnabled()) { ClearTrackedCollection(trackedValuables, trackedValuableSet); ClearTrackedCollection(trackedItems, trackedItemSet); ClearTrackedCollection(trackedEnemies, trackedEnemySet); ClearTrackedCollection(trackedCarts, trackedCartSet); ClearTrackedCollection(trackedDiscoverCustoms, trackedDiscoverCustomSet); ClearTrackedCollection(trackedGrabbers, trackedGrabberSet); nextEnemyDirectorSyncTime = 0f; if ((Object)(object)Instance != (Object)null) { Instance.objectRendererCache.Clear(); Instance.objectDisplayNameCache.Clear(); Instance.objectPhysGrabCache.Clear(); Instance.itemHasValuableCache.Clear(); Instance.itemShopItemCache.Clear(); Instance.itemCartInfoCache.Clear(); Instance.itemShouldScanCache.Clear(); Instance.customDiscoverColorCache.Clear(); Instance.valuableValueCache.Clear(); Instance.valuableValueCacheExpiry.Clear(); Instance.proximityUnlockedScanTargetIds.Clear(); Instance.physGrabHiddenOrDeadFrameCache.Clear(); Instance.sharedValuableIds.Clear(); Instance.sharedCustomDiscoverIds.Clear(); Instance.localHeldPhysGrabObjects.Clear(); Instance.localHeldStateCache.Clear(); Instance.playerAvatarFieldCache.Clear(); Instance.grabberObjectsCache.Clear(); Instance.cachedPhysGrabStateFrame = -1; Instance.cachedLocalPlayer = null; Instance.cachedLocalPlayerIsLocal = false; Instance.cachedScanLocalPlayerFrame = -1; Instance.cachedScanLocalPlayerReady = false; Instance.cachedScanLocalPlayer = null; Instance.cachedLocalPositionFrame = -1; Instance.cachedCamera = null; Instance.cachedGuiScaleCamera = null; Instance.cachedGuiScaleFrame = -1; Instance.nextLocalHeldRefreshTime = 0f; Instance.nextGrabberRefreshTime = 0f; Instance.nextLocalPlayerRefreshTime = 0f; Instance.ClearEnemyRuntimeCaches(); } } } private static void LevelGeneratorGenerateDonePostfix() { if (IsStaticModEnabled()) { SyncTrackedObjectsFromScene(); } } private static void SyncTrackedObjectsFromScene() { ClearTrackedCollection(trackedValuables, trackedValuableSet); ValuableObject[] array = Object.FindObjectsOfType(); if (array != null) { ValuableObject[] array2 = array; foreach (ValuableObject item in array2) { AddTrackedUnique(trackedValuables, trackedValuableSet, item); } } ClearTrackedCollection(trackedEnemies, trackedEnemySet); Enemy[] array3 = Object.FindObjectsOfType(true); if (array3 != null) { Enemy[] array4 = array3; for (int i = 0; i < array4.Length; i++) { TrackEnemy(array4[i]); } } SyncTrackedEnemiesFromDirector(force: true); ClearTrackedCollection(trackedItems, trackedItemSet); ItemAttributes[] array5 = Object.FindObjectsOfType(); if (array5 != null) { ItemAttributes[] array6 = array5; foreach (ItemAttributes item2 in array6) { AddTrackedUnique(trackedItems, trackedItemSet, item2); Instance?.PrimeTrackedItemCaches(item2); } } ClearTrackedCollection(trackedCarts, trackedCartSet); PhysGrabCart[] array7 = Object.FindObjectsOfType(); if (array7 != null) { PhysGrabCart[] array8 = array7; foreach (PhysGrabCart item3 in array8) { AddTrackedUnique(trackedCarts, trackedCartSet, item3); } } ClearTrackedCollection(trackedDiscoverCustoms, trackedDiscoverCustomSet); ValuableDiscoverCustom[] array9 = Object.FindObjectsOfType(); if (array9 != null) { ValuableDiscoverCustom[] array10 = array9; foreach (ValuableDiscoverCustom item4 in array10) { AddTrackedUnique(trackedDiscoverCustoms, trackedDiscoverCustomSet, item4); } } ClearTrackedCollection(trackedGrabbers, trackedGrabberSet); PhysGrabber[] array11 = Object.FindObjectsOfType(true); if (array11 != null) { PhysGrabber[] array12 = array11; foreach (PhysGrabber item5 in array12) { AddTrackedUnique(trackedGrabbers, trackedGrabberSet, item5); } } } private static void SyncTrackedEnemiesFromDirector(bool force = false) { if (!force && Time.unscaledTime < nextEnemyDirectorSyncTime) { return; } nextEnemyDirectorSyncTime = Time.unscaledTime + 0.25f; if ((Object)(object)EnemyDirector.instance == (Object)null || EnemyDirector.instance.enemiesSpawned == null) { return; } foreach (EnemyParent item in EnemyDirector.instance.enemiesSpawned) { TrackEnemyFromParent(item); } } private static void TrackEnemyFromParent(EnemyParent parent) { if (!((Object)(object)parent == (Object)null)) { object? obj = EnemyParentEnemyField?.GetValue(parent); Enemy val = (Enemy)((obj is Enemy) ? obj : null); if ((Object)(object)val == (Object)null) { val = ((Component)parent).GetComponentInChildren(true); } TrackEnemy(val); } } private static void TrackEnemy(Enemy enemy) { AddTrackedUnique(trackedEnemies, trackedEnemySet, enemy); } private static void AddTrackedUnique(List list, HashSet set, T item) where T : Object { if ((Object)(object)item != (Object)null && set.Add(item)) { list.Add(item); } } private void StartResourceNameDump() { if (!resourceNameDumpStarted) { resourceNameDumpStarted = true; ((MonoBehaviour)this).StartCoroutine(ResourceNameDumpCoroutine()); } } [IteratorStateMachine(typeof(d__384))] private IEnumerator ResourceNameDumpCoroutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__384(0) { <>4__this = this }; } private static bool AreResourceDumpSourcesReady() { if ((Object)(object)StatsManager.instance != (Object)null && StatsManager.instance.itemDictionary != null && StatsManager.instance.itemDictionary.Count > 0 && (Object)(object)RunManager.instance != (Object)null && RunManager.instance.levels != null) { return RunManager.instance.levels.Count > 0; } return false; } private void DumpItemResources() { Dictionary itemDictionary = StatsManager.instance.itemDictionary; if (itemDictionary == null || itemDictionary.Count == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[NameDump][Items] Skip. itemDictionary is empty."); return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[NameDump][Items] Begin. Count={itemDictionary.Count}"); foreach (KeyValuePair item in itemDictionary.OrderBy, string>((KeyValuePair x) => x.Key, StringComparer.OrdinalIgnoreCase)) { Item value = item.Value; if (!((Object)(object)value == (Object)null)) { string text = SafeString(((Object)value).name); string text2 = SafeString(value.itemName); string localizedStringSafe = GetLocalizedStringSafe(value.itemNameLocalized); string text3 = TranslateItemName(text2); string text4 = SafeString((value.prefab == null) ? null : value.prefab.PrefabName); string text5 = SafeString((value.prefab == null) ? null : value.prefab.ResourcePath); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[NameDump][Items] assetName=" + text + " | itemName=" + text2 + " | localized=" + localizedStringSafe + " | translatedZh=" + text3 + " | prefabName=" + text4 + " | prefabPath=" + text5)); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)"[NameDump][Items] End."); } private void DumpValuableResources() { List levels = RunManager.instance.levels; if (levels == null || levels.Count == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[NameDump][Valuables] Skip. levels is empty."); return; } Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); int loggedEntries = 0; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[NameDump][Valuables] Begin."); foreach (Level item in levels) { if ((Object)(object)item == (Object)null || item.ValuablePresets == null) { continue; } foreach (LevelValuables valuablePreset in item.ValuablePresets) { if (!((Object)(object)valuablePreset == (Object)null)) { DumpValuableBucket(item, "tiny", valuablePreset.tiny, dictionary, ref loggedEntries); DumpValuableBucket(item, "small", valuablePreset.small, dictionary, ref loggedEntries); DumpValuableBucket(item, "medium", valuablePreset.medium, dictionary, ref loggedEntries); DumpValuableBucket(item, "big", valuablePreset.big, dictionary, ref loggedEntries); DumpValuableBucket(item, "wide", valuablePreset.wide, dictionary, ref loggedEntries); DumpValuableBucket(item, "tall", valuablePreset.tall, dictionary, ref loggedEntries); DumpValuableBucket(item, "veryTall", valuablePreset.veryTall, dictionary, ref loggedEntries); } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[NameDump][Valuables] End. UniqueEntries={dictionary.Count} LoggedEntries={loggedEntries}"); } private void DumpValuableBucket(Level level, string bucketName, List bucket, Dictionary seenEntries, ref int loggedEntries) { //IL_0181: Unknown result type (might be due to invalid IL or missing references) if (bucket == null) { return; } foreach (PrefabRef item in bucket) { if (item != null) { string text = SafeString(((Object)level).name); string text2 = SafeString(item.PrefabName); string text3 = SafeString(item.ResourcePath); GameObject prefab = item.Prefab; string text4 = SafeString(((Object)(object)prefab == (Object)null) ? null : ((Object)prefab).name); ItemAttributes val = (((Object)(object)prefab == (Object)null) ? null : prefab.GetComponent()); ValuableObject val2 = (((Object)(object)prefab == (Object)null) ? null : prefab.GetComponent()); string text5 = (((Object)(object)val != (Object)null) ? GetFieldString(val, ItemNameField) : string.Empty); string text6 = (((Object)(object)val != (Object)null) ? GetFieldString(val, ItemPromptNameField) : string.Empty); string text7 = (((Object)(object)val != (Object)null) ? GetFieldString(val, ItemAssetNameField) : string.Empty); string text8 = (((Object)(object)val != (Object)null) ? GetFieldString(val, ItemInstanceNameField) : string.Empty); string text9 = (((Object)(object)val != (Object)null && (Object)(object)val.item != (Object)null) ? GetLocalizedStringSafe(val.item.itemNameLocalized) : string.Empty); string text10 = (((Object)(object)val != (Object)null) ? GetItemDisplayName(val) : TranslateItemName(text4)); string text11 = (((Object)(object)val2 != (Object)null) ? $"ValuableObject(volume={val2.volumeType})" : string.Join(",", GetComponentTypeNames(prefab))); string key = text2 + "|" + text3; if (!seenEntries.ContainsKey(key)) { seenEntries[key] = text; loggedEntries++; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[NameDump][Valuables] level=" + text + " | bucket=" + bucketName + " | prefabName=" + text2 + " | prefabPath=" + text3 + " | prefabGoName=" + text4 + " | itemAssetName=" + text7 + " | itemName=" + text5 + " | promptName=" + text6 + " | instanceName=" + text8 + " | localized=" + text9 + " | resolvedDisplayName=" + text10 + " | components=" + text11)); } } } } private static string GetLocalizedStringSafe(LocalizedAsset localizedAsset) { try { if ((Object)(object)localizedAsset == (Object)null || LocalizedAssetGetStringMethod == null) { return string.Empty; } return SafeString(LocalizedAssetGetStringMethod.Invoke(localizedAsset, null) as string); } catch { return string.Empty; } } private static string GetFieldString(object instance, FieldInfo field) { if (instance == null || field == null) { return string.Empty; } try { return SafeString(field.GetValue(instance) as string); } catch { return string.Empty; } } private static string SafeString(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } return value.Replace("\r", " ").Replace("\n", " ").Trim(); } [IteratorStateMachine(typeof(d__392))] private static IEnumerable GetComponentTypeNames(GameObject gameObject) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__392(-2) { <>3__gameObject = gameObject }; } } internal sealed class ReferenceObjectComparer : IEqualityComparer { public static readonly ReferenceObjectComparer Instance = new ReferenceObjectComparer(); public new bool Equals(object x, object y) { return x == y; } public int GetHashCode(object obj) { if (obj != null) { return RuntimeHelpers.GetHashCode(obj); } return 0; } } internal sealed class ConfigurationManagerAttributes { public bool? ShowRangeAsPercent; public Action CustomDrawer; public bool? Browsable; public string Category; public object DefaultValue; public bool? HideDefaultButton; public bool? HideSettingName; public int? Order; public bool? ReadOnly; } internal static class EnemyNameLocalizer { private static readonly Regex GroupCountRegex = new Regex("^(?\\d+)\\s+(?.+)$", RegexOptions.Compiled); private static readonly Regex CamelCaseBoundaryRegex = new Regex("(?<=[a-z])(?=[A-Z])", RegexOptions.Compiled); private static readonly Regex LeadingEnemyRegex = new Regex("^Enemy\\s+", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex WhitespaceRegex = new Regex("\\s+", RegexOptions.Compiled); private static readonly Regex ComponentSuffixRegex = new Regex("\\b(Anim|Animation System|Always Active|Attaching|Bot Tilt|Bomb|Camera Visuals|Catch Cutscene|Chase Offset|Controller|Cute Face|Director|Explosion|Eye|Eye Idle|Eye Target|Eye Tilt|Eye Tremble|Float|Fuse|Gas Checker|Gas Guider|Hair|Hair Lean|Hair Target|Hair Tilt|Heal Aura|Hive Attack|Lean|Local Camera|Loop|Old|Particle|Particle Puke Collision|Player Avatar Attached|Pupil|Screen Vein Effect|Sphere Effect|Stun Fly|Tentacle|Tilt|Up|Visual|Visuals)\\b.*$", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Dictionary NameMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["Animal"] = "蟑螂", ["Enemy Animal"] = "蟑螂", ["Apex Predator"] = "邪恶鸭子", ["Bang"] = "炸弹骷髅", ["Banger"] = "炸弹骷髅", ["Enemy Bang"] = "炸弹骷髅", ["Baby"] = "扔东西小孩", ["Beamer"] = "激光小丑", ["Enemy Beamer"] = "激光小丑", ["Bella"] = "三轮车", ["Birthday Boy"] = "生日男孩", ["Enemy Birthday Boy"] = "生日男孩", ["Bomb Thrower"] = "疯狂厨师青蛙", ["Enemy Bomb Thrower"] = "疯狂厨师青蛙", ["Bowtie"] = "尖叫大白", ["Enemy Bowtie"] = "尖叫大白", ["Ceiling Eye"] = "邪恶大眼", ["Enemy Ceiling Eye"] = "邪恶大眼", ["Chef"] = "疯狂厨师青蛙", ["Cleanup Crew"] = "清洁工", ["Clown"] = "激光小丑", ["Dog"] = "小狗", ["Elsa"] = "小狗", ["Enemy Elsa"] = "小狗", ["Duck"] = "邪恶鸭子", ["Enemy Duck"] = "邪恶鸭子", ["Floater"] = "外星人", ["Enemy Floater"] = "外星人", ["Frog"] = "疯狂厨师青蛙", ["Gambit"] = "赌盘怪", ["Gnome"] = "红帽子侏儒", ["Gnomes"] = "红帽子侏儒", ["Enemy Gnome"] = "红帽子侏儒", ["Head"] = "咬人骷髅头", ["Enemy Head"] = "咬人骷髅头", ["Head Grabber"] = "抢头怪", ["Enemy Head Grabber"] = "抢头怪", ["Headgrab"] = "抢头怪", ["Headman"] = "咬人骷髅头", ["Heart Hugger"] = "爱心花", ["Enemy Heart Hugger"] = "爱心花", ["Hidden"] = "隐身怪", ["Enemy Hidden"] = "隐身怪", ["Hunter"] = "猎人", ["Huntsman"] = "猎人", ["Enemy Hunter"] = "猎人", ["Loom"] = "拍手女", ["Mentalist"] = "外星人", ["Oogly"] = "绿灯怪", ["Enemy Oogly"] = "绿灯怪", ["Peeper"] = "邪恶大眼", ["Peeper Ceiling Eye"] = "邪恶大眼", ["Reaper"] = "电锯小丑", ["Robe"] = "长袍无脸男", ["Enemy Robe"] = "长袍无脸男", ["Rugrat"] = "熊孩子", ["Runner"] = "电锯小丑", ["Enemy Runner"] = "电锯小丑", ["Shadow"] = "拍手女", ["Enemy Shadow"] = "拍手女", ["Shadow Child"] = "娃娃脸小孩", ["Slow Mouth"] = "呕吐怪", ["Enemy Slow Mouth"] = "呕吐怪", ["Slow Walker"] = "大锤版钟馗", ["Enemy Slow Walker"] = "大锤版钟馗", ["Spewer"] = "呕吐怪", ["Spinny"] = "赌盘怪", ["Enemy Spinny"] = "赌盘怪", ["Thin Man"] = "娃娃脸小孩", ["Enemy Thin Man"] = "娃娃脸小孩", ["Tick"] = "吸血虫", ["Enemy Tick"] = "吸血虫", ["Tricycle"] = "三轮车", ["Enemy Tricycle"] = "三轮车", ["Trudge"] = "大锤版钟馗", ["Tumbler"] = "疯狂厨师青蛙", ["Enemy Tumbler"] = "疯狂厨师青蛙", ["Upscream"] = "尖叫", ["Enemy Upscream"] = "尖叫", ["Valuable Thrower"] = "熊孩子", ["Enemy Valuable Thrower"] = "熊孩子" }; private static readonly Dictionary NicknameMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["Animal"] = "小六子", ["Enemy Animal"] = "小六子", ["Dog"] = "摸摸小狗", ["Elsa"] = "摸摸小狗", ["Enemy Elsa"] = "摸摸小狗" }; private static readonly Dictionary ChineseNicknameMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["蟑螂"] = "小六子", ["邪恶鸭子"] = "暴走鸭", ["炸弹骷髅"] = "东方快递", ["扔东西小孩"] = "败家小子", ["激光小丑"] = "激光哥", ["三轮车"] = "鬼火少年", ["生日男孩"] = "气球哥", ["疯狂厨师青蛙"] = "青蛙厨神", ["尖叫大白"] = "白色电风扇", ["邪恶大眼"] = "大眼哥", ["清洁工"] = "丢头哥", ["小狗"] = "摸摸小狗", ["外星人"] = "外星人", ["赌盘怪"] = "转转乐", ["红帽子侏儒"] = "地精矿工", ["咬人骷髅头"] = "大头鬼", ["抢头怪"] = "抢头哥", ["爱心花"] = "心动花花", ["隐身怪"] = "隐身老六", ["猎人"] = "男枪", ["拍手女"] = "老奶奶", ["绿灯怪"] = "夜店绿苍蝇", ["电锯小丑"] = "双刀妹", ["长袍无脸男"] = "无脸鬼手男", ["熊孩子"] = "败家小子", ["娃娃脸小孩"] = "末影人", ["呕吐怪"] = "口水哥", ["大锤版钟馗"] = "大锤哥", ["吸血虫"] = "面包虫", ["尖叫"] = "尖叫鸡" }; public static string Translate(string rawName, DisplayLanguage language, bool useNicknames) { if (string.IsNullOrWhiteSpace(rawName)) { return string.Empty; } string text = rawName.Trim(); if (language == DisplayLanguage.English) { return NormalizeEnglishName(text); } Dictionary activeMap = (useNicknames ? NicknameMap : NameMap); if (TryGetName(activeMap, text, out var translated)) { return translated; } string text2 = NormalizeKey(text); if (TryGetName(activeMap, text2, out translated)) { return translated; } string text3 = SimplifyEnemyComponentName(text2); if (!string.Equals(text3, text2, StringComparison.OrdinalIgnoreCase) && TryGetName(activeMap, text3, out translated)) { return translated; } Match match = GroupCountRegex.Match(text2); if (match.Success) { string value = match.Groups["count"].Value; string text4 = match.Groups["name"].Value.Trim(); string text5 = (text4.EndsWith("s", StringComparison.OrdinalIgnoreCase) ? text4.Substring(0, text4.Length - 1) : text4); if (TryGetName(activeMap, text4, out translated)) { return value + " " + translated; } if (TryGetName(activeMap, text5, out translated)) { return value + " " + translated; } string key = SimplifyEnemyComponentName(text4); if (TryGetName(activeMap, key, out translated)) { return value + " " + translated; } string key2 = SimplifyEnemyComponentName(text5); if (TryGetName(activeMap, key2, out translated)) { return value + " " + translated; } } return text; } private static bool TryGetName(Dictionary activeMap, string key, out string translated) { if (activeMap.TryGetValue(key, out translated)) { return true; } if (activeMap != NameMap && NameMap.TryGetValue(key, out translated)) { if (ChineseNicknameMap.TryGetValue(translated, out var value)) { translated = value; } return true; } translated = null; return false; } private static string NormalizeEnglishName(string rawName) { string text = NormalizeKey(rawName); string text2 = SimplifyEnemyComponentName(text); if (!string.IsNullOrWhiteSpace(text2)) { return text2; } return text; } private static string NormalizeKey(string rawName) { string input = rawName.Replace("(Clone)", string.Empty).Replace("Enemy Group - ", string.Empty).Replace("Enemy - ", string.Empty) .Replace("_", " ") .Replace("-", " ") .Trim(); input = CamelCaseBoundaryRegex.Replace(input, " "); input = LeadingEnemyRegex.Replace(input, string.Empty); return WhitespaceRegex.Replace(input, " ").Trim(); } private static string SimplifyEnemyComponentName(string cleaned) { if (string.IsNullOrWhiteSpace(cleaned)) { return string.Empty; } string text = ComponentSuffixRegex.Replace(cleaned, string.Empty).Trim(); if (!string.IsNullOrWhiteSpace(text)) { return text; } return cleaned; } } internal static class ItemNameLocalizer { private static readonly Regex WhitespaceRegex = new Regex("\\s+", RegexOptions.Compiled); private static readonly Regex PrefixValueRegex = new Regex("^(Arctic|Manor|Museum|Wizard)\\s+(.+)$", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex LeadingTypePrefixRegex = new Regex("^(valuable\\s*object|valuable|item)\\s+", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex TrailingTypePrefixRegex = new Regex("\\s+(valuable\\s*object|valuable|item)$", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex SeparatorRegex = new Regex("[_\\-]+", RegexOptions.Compiled); private static readonly Regex LeadingValuablePrefixRegex = new Regex("^Valuable(?=[A-Z0-9_\\-\\s])", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex LowerUpperBoundaryRegex = new Regex("([a-z])([A-Z])", RegexOptions.Compiled); private static readonly Regex LetterDigitBoundaryRegex = new Regex("([A-Za-z])(\\d)", RegexOptions.Compiled); private static readonly Regex DigitLetterBoundaryRegex = new Regex("(\\d)([A-Za-z])", RegexOptions.Compiled); private static readonly Dictionary ExactNameMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "C.A.R.T. Cannon", "C.A.R.T. 加农炮" }, { "C.A.R.T. Laser", "C.A.R.T. 激光炮" }, { "C.A.R.T.", "C.A.R.T.运输车" }, { "POCKET C.A.R.T.", "C.A.R.T.小车" }, { "Recharge Drone", "充能无人机" }, { "Feather Drone", "羽毛无人机" }, { "Indestructible Drone", "无敌无人机" }, { "Roll Drone", "滚动无人机" }, { "Zero Gravity Drone", "零重力无人机" }, { "Duck Bucket", "鸭子桶" }, { "Extraction Tracker", "提取追踪器" }, { "Duct Taped Grenades", "胶带捆绑手榴弹" }, { "Grenade", "手榴弹" }, { "Human Grenade", "人类手榴弹" }, { "Shockwave Grenade", "冲击波手榴弹" }, { "Stun Grenade", "眩晕手榴弹" }, { "AK-47", "AK-47" }, { "Gun", "枪" }, { "Photon Blaster", "光子冲击炮" }, { "Pulse Pistol", "脉冲手枪" }, { "Shotgun", "霰弹枪" }, { "Boltzap", "电击枪" }, { "Tranq Gun", "麻醉枪" }, { "Large Health Pack (100)", "大医疗包 (100)" }, { "Medium Health Pack (50)", "中医疗包 (50)" }, { "Small Health Pack (25)", "小医疗包 (25)" }, { "Leaf Blower", "吹风机" }, { "Baseball Bat", "棒球棍" }, { "Frying Pan", "铁锅" }, { "Inflatable Hammer", "充气锤" }, { "Sledge Hammer", "大锤" }, { "Prodzap", "电击棒" }, { "Sword", "剑" }, { "Explosive Mine", "爆炸地雷" }, { "Shockwave Mine", "冲击波地雷" }, { "Trapzap", "陷阱" }, { "Zero Gravity Orb", "零重力球" }, { "Phase Bridge", "相位桥" }, { "Energy Crystal", "能量水晶" }, { "Defibro", "除颤仪" }, { "Rubber Duck", "橡胶鸭" }, { "Roll Staff", "滚动法杖" }, { "Void Staff", "虚空法杖" }, { "Zero Gravity Staff", "零重力法杖" }, { "Death Head Battery Upgrade", "死亡头部电池升级" }, { "Map Player Count Upgrade", "地图玩家剩余数量升级" }, { "Crouch Rest Upgrade", "下蹲回体升级" }, { "Stamina Upgrade", "体力升级" }, { "Extra Jump Upgrade", "额外跳跃升级" }, { "Range Upgrade", "抓取范围升级" }, { "Strength Upgrade", "力量升级" }, { "Health Upgrade", "生命升级" }, { "Sprint Speed Upgrade", "冲刺速度升级" }, { "Tumble Climb Upgrade", "翻滚抓墙升级" }, { "Tumble Launch Upgrade", "翻滚速度升级" }, { "Tumble Wings Upgrade", "翻滚滑翔升级" }, { "Valuable Tracker", "贵重物品追踪器" }, { "Hauler", "运输车" }, { "Scout", "斥候" }, { "Semibot Walkies", "半机械对讲机套件" }, { "Cart", "大购物车" }, { "Small Cart", "小购物车" }, { "Decor Box", "装饰箱" } }; private static readonly Dictionary BodyMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { { "3D Printer", "3D打印机" }, { "3 D Printer", "3D打印机" }, { "Alchemy Station", "炼金台" }, { "Animal Crate", "动物箱" }, { "Baby Head", "婴儿头" }, { "Banana Bow", "香蕉蝴蝶结" }, { "Barrel", "桶" }, { "Big Sample", "大型样本" }, { "Bird Skull", "鸟头骨" }, { "Blender", "搅拌机" }, { "Bonsai", "盆景" }, { "Boombox", "音响" }, { "Bottle", "瓶子" }, { "Broom", "扫帚" }, { "Bug", "虫子" }, { "Calculator", "计算器" }, { "Camera", "相机" }, { "Car", "汽车" }, { "Cauldron Box", "坩埚箱" }, { "Centrifuge", "离心机" }, { "Chomp Book", "咬咬书" }, { "Clown", "小丑" }, { "Cocktail", "鸡尾酒" }, { "Coffee Cup", "咖啡杯" }, { "Coffin", "棺材" }, { "Computer", "电脑" }, { "Cool brain", "酷脑" }, { "Creature Leg", "生物腿" }, { "Crown", "王冠" }, { "Cryo Pod", "冷冻舱" }, { "Crystal", "水晶" }, { "Crystal Ball", "水晶球" }, { "Cube ball", "方块球" }, { "Cube of Knowledge", "知识方块" }, { "Cubic Sculpture", "立方雕塑" }, { "Cubic Tower", "立方塔" }, { "Diamond", "钻石" }, { "Diamond Display", "钻石展示架" }, { "Dinosaur", "恐龙" }, { "Doll", "玩偶" }, { "Dragon Skull", "龙头骨" }, { "duck man", "鸭人" }, { "Dumgolfs Staff", "杜姆高夫法杖" }, { "Egg", "蛋" }, { "Emerald Bracelet", "翡翠手镯" }, { "Eraser", "橡皮" }, { "Eye Ball", "眼球" }, { "Eye of Orpigox", "奥匹戈克斯之眼" }, { "Fan", "风扇" }, { "Fire Extinguisher", "灭火器" }, { "Fish", "鱼" }, { "Flamethrower", "火焰喷射器" }, { "Flashlight", "手电筒" }, { "Flesh Blob", "肉团" }, { "Forever Candle", "永燃蜡烛" }, { "Fortune Card", "命运卡" }, { "Frog", "青蛙" }, { "Gem Box", "宝石箱" }, { "Gem Burger", "宝石汉堡" }, { "Globe", "地球仪" }, { "Glowing Jar", "发光罐" }, { "Goblet", "高脚杯" }, { "Goblin Arm", "哥布林手臂" }, { "Goblin Head", "哥布林头" }, { "Golden Statue", "黄金雕像" }, { "Golden Swirl", "金色旋纹" }, { "GoldFish", "金鱼" }, { "Gold Fish", "金鱼" }, { "GoldTooth", "金牙" }, { "Gold Tooth", "金牙" }, { "Gramophone", "留声机" }, { "Grandfather Clock", "落地钟" }, { "Griffin Statue", "狮鹫雕像" }, { "Guitar", "吉他" }, { "Gumball", "口香糖球" }, { "Handface", "手脸" }, { "Hand Face", "手脸" }, { "Harp", "竖琴" }, { "HDD", "硬盘" }, { "Heavy Water", "重水" }, { "Horse", "马" }, { "Ice Block", "冰块" }, { "Ice Saw", "冰锯" }, { "Icepick", "冰镐" }, { "Instrument", "乐器" }, { "Jackhammer", "风镐" }, { "Kettle", "水壶" }, { "Keycard", "钥匙卡" }, { "ladybug", "瓢虫" }, { "Laptop", "笔记本电脑" }, { "Levitation Potion", "漂浮药水" }, { "Love Potion", "爱情药水" }, { "Magnifying Glass", "放大镜" }, { "Map", "地图" }, { "Master Potion", "大师药水" }, { "Milk", "牛奶" }, { "Money", "钱" }, { "MonkeyBox", "猴子盒" }, { "Monkey Box", "猴子盒" }, { "Music Box", "音乐盒" }, { "Ocarina", "陶笛" }, { "Old Camera", "老式相机" }, { "Pacifier", "奶嘴" }, { "Painting", "画作" }, { "Pendant", "吊坠" }, { "Phone", "电话" }, { "Piano", "钢琴" }, { "Pills", "药丸" }, { "PimpleGuy", "痘痘人" }, { "Pimple Guy", "痘痘人" }, { "Plane", "飞机" }, { "Pocket Watch", "怀表" }, { "Poison Chalice", "毒酒杯" }, { "Power Crystal", "能量水晶" }, { "Propane Tank", "丙烷罐" }, { "Radio", "收音机" }, { "Red Mushroom", "红蘑菇" }, { "RubenDoll", "鲁本玩偶" }, { "Ruben Doll", "鲁本玩偶" }, { "Sample", "样本" }, { "Sample Cooler", "样本冷藏箱" }, { "Sample Cooler Wide", "宽样本冷藏箱" }, { "Sample Six Pack", "六联样本" }, { "Scale", "天平" }, { "Science Station", "科研站" }, { "Scream Doll", "尖叫玩偶" }, { "Server Rack", "服务器机柜" }, { "Ship in a bottle", "瓶中船" }, { "SilverFish", "银鱼" }, { "Silver Fish", "银鱼" }, { "Small Gem", "小宝石" }, { "Small Potion", "小药水" }, { "Smartwatch", "智能手表" }, { "Snow Bike", "雪地摩托" }, { "Spider Potion", "蜘蛛药水" }, { "Stapler", "订书机" }, { "Star Wand", "星星魔杖" }, { "Sword", "剑" }, { "Tall Guy", "高个子" }, { "Teeth Bot", "牙齿机器人" }, { "Telescope", "望远镜" }, { "Television", "电视" }, { "Tentacle", "触手" }, { "Time Glass", "时之沙漏" }, { "Toast", "吐司" }, { "Tooth", "牙齿" }, { "Toy Monkey", "玩具猴" }, { "Traffic Light", "红绿灯" }, { "Tray", "托盘" }, { "Troll Finger", "巨魔手指" }, { "Trophy", "奖杯" }, { "Unicorn Horn", "独角兽角" }, { "Uranium Mug", "铀杯" }, { "Uranium Mug Deluxe", "豪华铀杯" }, { "Uranium Petri Dish", "铀培养皿" }, { "Uranium Plate", "铀盘" }, { "Usb stick", "U盘" }, { "Vase", "花瓶" }, { "Vase Big", "大花瓶" }, { "Vase Chunky", "厚花瓶" }, { "Vase Small", "小花瓶" }, { "VHS", "录像带" }, { "Vinyl", "黑胶唱片" }, { "Wire Figure", "铁丝人偶" }, { "Worm", "蠕虫" } }; public static string Translate(string rawName) { string text = CleanDisplayName(rawName); if (string.IsNullOrWhiteSpace(text)) { return CleanName(rawName); } if (ExactNameMap.TryGetValue(text, out var value)) { return value; } string text2 = SplitWords(text); if (ExactNameMap.TryGetValue(text2, out value)) { return value; } if (TryTranslatePrefixedValuable(text, out value) || TryTranslatePrefixedValuable(text2, out value)) { return value; } if (TryGetBodyTranslation(text, out value) || TryGetBodyTranslation(text2, out value)) { return value; } return text2; } public static string CleanDisplayName(string rawName) { string text = NormalizeLeadingValuablePrefix(CleanName(rawName)); string text2 = StripTypePrefix(text); if (!string.IsNullOrWhiteSpace(text2)) { return text2; } return text; } private static bool TryTranslatePrefixedValuable(string value, out string translated) { translated = null; if (string.IsNullOrWhiteSpace(value)) { return false; } if (!TrySplitPrefixAndBody(value, out var _, out var body)) { return false; } if (TryGetBodyTranslation(body, out var translated2)) { translated = translated2; return true; } string text = SplitWords(body); translated = text; return true; } private static bool TryGetBodyTranslation(string value, out string translated) { translated = null; if (string.IsNullOrWhiteSpace(value)) { return false; } if (BodyMap.TryGetValue(value, out translated)) { return true; } string text = SplitWords(value); if (!string.Equals(text, value, StringComparison.OrdinalIgnoreCase) && BodyMap.TryGetValue(text, out translated)) { return true; } string text2 = WhitespaceRegex.Replace(value, string.Empty); if (!string.Equals(text2, value, StringComparison.OrdinalIgnoreCase) && BodyMap.TryGetValue(text2, out translated)) { return true; } return false; } private static bool TrySplitPrefixAndBody(string value, out string prefix, out string body) { prefix = null; body = null; Match match = PrefixValueRegex.Match(value); if (!match.Success) { return false; } prefix = match.Groups[1].Value.Trim(); body = match.Groups[2].Value.Trim(); return !string.IsNullOrWhiteSpace(body); } private static string StripTypePrefix(string name) { if (string.IsNullOrWhiteSpace(name)) { return string.Empty; } string input = SplitWords(name); input = LeadingTypePrefixRegex.Replace(input, string.Empty); input = TrailingTypePrefixRegex.Replace(input, string.Empty); input = WhitespaceRegex.Replace(input, " "); return input.Trim(); } private static string CleanName(string rawName) { if (string.IsNullOrWhiteSpace(rawName)) { return string.Empty; } string input = rawName.Replace("(Clone)", string.Empty).Trim(); input = SeparatorRegex.Replace(input, " "); input = WhitespaceRegex.Replace(input, " "); return input.Trim(); } private static string NormalizeLeadingValuablePrefix(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } return LeadingValuablePrefixRegex.Replace(value, string.Empty).Trim(); } private static string SplitWords(string value) { string input = LowerUpperBoundaryRegex.Replace(value, "$1 $2"); input = LetterDigitBoundaryRegex.Replace(input, "$1 $2"); input = DigitLetterBoundaryRegex.Replace(input, "$1 $2"); input = SeparatorRegex.Replace(input, " "); input = WhitespaceRegex.Replace(input, " "); return input.Trim(); } }