using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [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-MoreUI-1.3.4")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+85a78bb8de5017ffff90b08f70b8ac4c36537b87")] [assembly: AssemblyProduct("Zichen-MoreUI-1.3.4")] [assembly: AssemblyTitle("Zichen-MoreUI-1.3.4")] [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 DisplayMode { 文字显示, 原生UI显示 } public enum DisplayLanguage { 中文, English } [BepInPlugin("zichen.moreui", "MoreUI", "1.3.4")] public class Plugin : BaseUnityPlugin { internal sealed class CfgI18N { public string SectionCN; public string SectionEN; public string KeyCN; public string KeyEN; public string DisplayEN; public string DescCN; public string DescEN; public ConfigurationManagerAttributes Attrs; public string ValueEN; public string ValueCN; public ConfigEntry ReadOnlyEntry; public ConfigEntryBase Entry; public bool ChineseOnly; } internal sealed class LiveLabel { public WeakReference Tmp; public CfgI18N I18N; public bool IsSection; } internal sealed class LiveValue { public WeakReference InputField; public CfgI18N I18N; } internal sealed class LiveSliderOptions { public WeakReference Slider; public CfgI18N I18N; public string[] OptionsCN; public string[] OptionsEN; } internal sealed class LiveToggleButtons { public WeakReference LeftTmp; public WeakReference RightTmp; } public const string PluginGuid = "zichen.moreui"; public const string PluginVersion = "1.3.4"; public const string PluginName = "MoreUI"; private static Plugin Instance; private const float MinimumRefreshIntervalSeconds = 0.1f; private const float RunLevelInactiveGraceSeconds = 4f; private const int PlayerHeadTopColorSlot = 5; private const float PlayerColorCacheRefreshSeconds = 0.2f; private const float PlayerPositionCacheSeconds = 0.15f; private const string TeammateIcon = "\ud83e\udd16"; private const string CartIcon = ""; private const float CartCacheInterval = 0.15f; private const float CartFarFontShrinkPercent = 30f; private const float TrackedObjectCleanupIntervalSeconds = 0.5f; private static readonly GUIContent ReusableGuiContent = new GUIContent(); private static readonly CultureInfo MoneyCulture = CultureInfo.GetCultureInfo("en-US"); private static readonly HashSet BoundsVisitedBuffer = new HashSet(); private static readonly List BoundsRendererBuffer = new List(); private static readonly List BoundsColliderBuffer = new List(); private static readonly Dictionary CachedChildRenderers = new Dictionary(); private static readonly Dictionary CachedChildColliders = new Dictionary(); private static readonly Dictionary PlayerAliveFrameCache = new Dictionary(); private static readonly HashSet TrackedEnemyKeyBuffer = new HashSet(); private static int playerAliveFrameCacheFrame = -1; private static readonly Dictionary EnemyBreakdownRankTable = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["Apex Predator"] = 10, ["Bang"] = 11, ["Gnome"] = 12, ["Peeper"] = 13, ["Shadow Child"] = 14, ["Spewer"] = 15, ["Tick"] = 16, ["Bella"] = 17, ["Birthday Boy"] = 18, ["Elsa"] = 19, ["Animal"] = 20, ["Bowtie"] = 21, ["Head Grabber"] = 22, ["Heart Hugger"] = 23, ["Mentalist"] = 24, ["Oogly"] = 25, ["Rugrat"] = 26, ["Upscream"] = 27, ["Head"] = 30, ["Hidden"] = 31, ["Hunter"] = 32, ["Loom"] = 33, ["Reaper"] = 34, ["Robe"] = 35, ["Slow Mouth"] = 36, ["Slow Walker"] = 37, ["Trudge"] = 38, ["Cleanup Crew"] = 39, ["Beamer"] = 40, ["Gambit"] = 41 }; private static int cachedWorldLabelCameraFrame = -1; private static Camera cachedWorldLabelCamera; private static int cachedRunLevelActiveFrame = -1; private static bool cachedRunLevelActive; private static int cachedLocalPlayerFrame = -1; private static PlayerAvatar cachedLocalPlayer; private static readonly HashSet valuablesCurrentlyInDollarHaul = new HashSet(); private static readonly List trackedValuables = new List(); private static readonly HashSet trackedValuableSet = new HashSet(ReferenceObjectComparer.Instance); private static readonly List trackedCarts = new List(); private static readonly HashSet trackedCartSet = new HashSet(ReferenceObjectComparer.Instance); private static readonly List trackedVehicles = new List(); private static readonly HashSet trackedVehicleSet = new HashSet(ReferenceObjectComparer.Instance); private static readonly List preservedTrackedVehiclesBuffer = new List(); private static readonly List trackedEnemies = new List(); private static readonly HashSet trackedEnemySet = new HashSet(ReferenceObjectComparer.Instance); private static readonly List trackedGrabbers = new List(); private static readonly HashSet trackedGrabberSet = new HashSet(ReferenceObjectComparer.Instance); private static readonly List trackedItems = new List(); private static readonly List trackedTokenBoxItems = new List(); private static readonly List trackedCustomDiscoverables = new List(); private static readonly List trackedCosmeticShopMachines = new List(); private static readonly Dictionary trackedTokenBoxObjectRefCounts = new Dictionary(); private static readonly HashSet EmptyReferenceSet = new HashSet(ReferenceObjectComparer.Instance); private static readonly List preservedTrackedCartsBuffer = new List(); private static readonly List preservedTrackedItemsBuffer = new List(); private static readonly List preservedTrackedCustomDiscoverablesBuffer = new List(); private static readonly List preservedTrackedCosmeticShopMachinesBuffer = new List(); private static int trackedTokenBoxObjectCount; private static float nextTrackedValuableCleanupAt; private static float nextTrackedCartCleanupAt; private static float nextTrackedVehicleCleanupAt; private static float nextTrackedEnemyCleanupAt; private static float nextTrackedGrabberCleanupAt; private static float nextTrackedTokenItemCleanupAt; private static float nextTrackedCustomDiscoverableCleanupAt; private static float nextTrackedCosmeticShopMachineCleanupAt; private ConfigEntry modEnabled; private ConfigEntry overlayEnabled; private ConfigEntry sectionSpacing; private ConfigEntry displayLanguage; private ConfigEntry enemyNicknameEnabled; private ConfigEntry displayMode; private ConfigEntry fontSize; private ConfigEntry overlayTextOpacityPercent; private ConfigEntry updateInterval; private ConfigEntry overlayOffsetX; private ConfigEntry overlayOffsetY; private ConfigEntry showEnemySection; private ConfigEntry showBreakdown; private ConfigEntry showTotalEnemyCount; private ConfigEntry showTokenBoxCount; private ConfigEntry showValueSection; private ConfigEntry showMapLostValue; private ConfigEntry showExplorationProgress; private ConfigEntry showMapTotalValue; private ConfigEntry showCurrentRunSubmittedFunds; private ConfigEntry showShopRemainingFunds; private ConfigEntry showLevelInfo; private ConfigEntry showTeammateInfoSection; private ConfigEntry showDeadTeammates; private ConfigEntry showAliveTeammates; private ConfigEntry showPlayerCounts; private ConfigEntry teammateOverlayEnabled; private ConfigEntry teammateAliveOverlayEnabled; private ConfigEntry teammateDeadOverlayEnabled; private ConfigEntry teammateAliveEdgeOverlayEnabled; private ConfigEntry teammateDeadEdgeOverlayEnabled; private ConfigEntry teammateDistanceEnabled; private ConfigEntry teammateFontSize; private ConfigEntry cartSectionEnabled; private ConfigEntry cartOverlayEnabled; private ConfigEntry smallCartOverlayEnabled; private ConfigEntry cartDistanceEnabled; private ConfigEntry cartFontSize; private ConfigEntry showLargeCartCount; private ConfigEntry showSmallCartCount; private ConfigEntry showKartCount; private ConfigEntry showCargoCount; private ConfigEntry vehicleSectionEnabled; private ConfigEntry vehicleOverlayEnabled; private ConfigEntry racingVehicleOverlayEnabled; private ConfigEntry vehicleDistanceEnabled; private ConfigEntry vehicleFontSize; private GameObject overlayObject; private RectTransform overlayRect; private TextMeshProUGUI overlayLabel; private readonly List nativeOverlayLineLabels = new List(); private readonly List nativeOverlayLineRects = new List(); private readonly List nativeOverlayLineStates = new List(); private readonly List nativeOverlayLineTextBuffer = new List(); private TMP_FontAsset nativeOverlayStableFont; private Material nativeOverlayStableMaterial; private bool nativeOverlayStableFontResolved; private Harmony valuableHaulHarmony; private Harmony nativeNameHarmony; private string overlayText = string.Empty; private string lastNativeOverlayText; private int lastNativeOverlayFontSize = -1; private int lastNativeOverlayOffsetX = int.MinValue; private int lastNativeOverlayOffsetY = int.MinValue; private bool lastNativeOverlayShowBreakdown; private float lastNativeOverlayOpacity = -1f; private Transform lastNativeOverlayParent; private string lastPlainOverlaySource; private string lastPlainOverlayText = string.Empty; private string lastTextOverlaySource; private int lastTextOverlayFontSize = -1; private bool lastTextOverlayShowBreakdown; private int lastTextOverlayOffsetX = int.MinValue; private int lastTextOverlayOffsetY = int.MinValue; private int lastTextOverlayScreenWidth = -1; private int lastTextOverlayScreenHeight = -1; private Rect cachedTextOverlayRect; private Rect cachedTextOverlayShadowRect; private float cachedTextOverlayWidth; private string cachedTextOverlayPlainText = string.Empty; private readonly List cartDistanceCache = new List(); private readonly List cartDistancePool = new List(); private readonly List vehicleDistanceCache = new List(); private readonly List vehicleDistancePool = new List(); private readonly List reusableSnapshotKeys = new List(); private readonly Dictionary largeCartLabelIndices = new Dictionary(); private readonly Dictionary smallCartLabelIndices = new Dictionary(); private readonly Dictionary smallCartTypeCache = new Dictionary(); private readonly Dictionary centeredRichLabelStyleCache = new Dictionary(); private readonly Dictionary centeredShadowLabelStyleCache = new Dictionary(); private readonly Dictionary overlayRichStyleCache = new Dictionary(); private readonly Dictionary overlayShadowStyleCache = new Dictionary(); private readonly Dictionary centeredLabelSizeCache = new Dictionary(); private readonly StringBuilder reusableOverlayTextBuilder = new StringBuilder(512); private readonly StringBuilder reusableItemSearchTextBuilder = new StringBuilder(256); private readonly StringBuilder reusableNativeOverlayTagStripBuilder = new StringBuilder(256); private readonly List activeEnemyBuffer = new List(); private readonly Dictionary enemyBreakdownBuffer = new Dictionary(); private readonly Dictionary enemyBreakdownRankBuffer = new Dictionary(); private readonly Dictionary enemyBreakdownRankCache = new Dictionary(); private readonly Dictionary enemyBreakdownRawNameRankCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly List> orderedEnemyBreakdownBuffer = new List>(); private readonly List currentDollarHaulObjectsBuffer = new List(); private readonly List currentCartObjectsBuffer = new List(); private readonly HashSet haulReferenceSetBuffer = new HashSet(ReferenceObjectComparer.Instance); private readonly HashSet cartReferenceSetBuffer = new HashSet(ReferenceObjectComparer.Instance); private readonly List activeCartBuffer = new List(); private readonly List cartLabelCandidateBuffer = new List(); private readonly List teammateDistanceBuffer = new List(); private readonly List teammateDistancePool = new List(); private readonly List leftEdgeTeammateLabelBuffer = new List(); private readonly List rightEdgeTeammateLabelBuffer = new List(); private readonly List leftEdgeTeammateRectBuffer = new List(); private readonly List rightEdgeTeammateRectBuffer = new List(); private readonly Component[] cartBoundsRootBuffer = (Component[])(object)new Component[2]; private readonly Dictionary cartComponentCache = new Dictionary(); private readonly Dictionary itemSearchTextCache = new Dictionary(); private readonly Dictionary itemTokenBoxCandidateCache = new Dictionary(); private List playerObjectsFrameCache; private readonly Dictionary enemyDisplayNameCache = new Dictionary(); private readonly Dictionary playerNameCache = new Dictionary(); private readonly Dictionary playerColorCache = new Dictionary(); private readonly Dictionary cartLabelYOffsetCache = new Dictionary(); private readonly Dictionary playerPositionCache = new Dictionary(); private DisplayLanguage cachedEnemyDisplayNameLanguage; private bool cachedEnemyNicknameEnabled; private bool hasCachedEnemyDisplayNameLanguage; private float refreshTimer; private float cartRefreshTimer; private int enemyObjectsFrameCacheFrame = -1; private int cartObjectsFrameCacheFrame = -1; private int grabberObjectsFrameCacheFrame = -1; private int valuableObjectsFrameCacheFrame = -1; private int playerObjectsFrameCacheFrame = -1; private int playerNameCacheFrame = -1; private int teammateDistanceCacheFrame = -1; private int playerCountsFrame = -1; private int cachedTotalPlayers; private int cachedAlivePlayers; private int cachedDeadPlayers; private bool cartDistanceCacheValid; private bool vehicleDistanceCacheValid; private float vehicleRefreshTimer; private int cartLabelIndexLevelNumber = -1; private int nextLargeCartLabelIndex = 1; private int nextSmallCartLabelIndex = 1; private int trackedLevelNumber = -1; private int valuableSnapshotGeneration; private float previousExtractedValue = -1f; private float accumulatedLostValue; private bool hasLoggedUpdateError; private bool runtimeWasActive; private bool levelTransitionLogIndicatesRun; private float lastConfirmedRunLevelTime = -999f; private int submittedFundsSnapshotLevelNumber = -1; private float submittedFundsBaselineTotalHaul = -1f; private float submittedFundsSnapshot; private int shopRemainingSnapshotLevelNumber = -1; private float shopRemainingFundsSnapshot = -1f; private readonly Dictionary valuableSnapshots = new Dictionary(); private static readonly FieldRef PlayerDeadSetRef = CreateFieldRef("deadSet"); private static readonly FieldRef PlayerIsDisabledRef = CreateFieldRef("isDisabled"); private static readonly FieldRef PlayerNameRef = CreateFieldRef("playerName"); private static readonly FieldRef PlayerIsLocalRef = CreateFieldRef("isLocal"); private static readonly FieldRef PlayerCosmeticsColorsEquippedRef = CreateFieldRef("colorsEquipped"); private static readonly FieldRef PlayerDeathHeadRef = CreateFieldRef("playerDeathHead"); private static readonly FieldRef PlayerLastNavmeshPositionRef = CreateFieldRef("LastNavmeshPosition"); private static readonly FieldRef DeathHeadPhysGrabObjectRef = CreateFieldRef("physGrabObject"); private static readonly FieldRef DeathHeadTriggeredPositionRef = CreateFieldRef("triggeredPosition"); private static readonly FieldRef DeathHeadOverridePositionTransformRef = CreateFieldRef("overridePositionTransform"); private static readonly FieldRef SpectateCameraPlayerRef = CreateFieldRef("player"); private static readonly FieldRef SpectateCameraPlayerOverrideRef = CreateFieldRef("playerOverride"); private static readonly FieldRef SpectateCameraMainCameraRef = CreateFieldRef("MainCamera"); private static readonly FieldRef EnemyParentRef = CreateFieldRef("EnemyParent"); private static readonly FieldRef EnemyHealthRef = CreateFieldRef("Health"); private static readonly FieldRef EnemyHealthDeadRef = CreateFieldRef("dead"); private static readonly FieldRef EnemyParentSpawnedRef = CreateFieldRef("Spawned"); private static readonly FieldRef EnemyParentEnemyRef = CreateFieldRef("Enemy"); private static readonly FieldRef ValuableOriginalValueRef = CreateFieldRef("dollarValueOriginal"); private static readonly FieldRef ValuableCurrentValueRef = CreateFieldRef("dollarValueCurrent"); private static readonly FieldRef ValuableValueSetRef = CreateFieldRef("dollarValueSet"); private static readonly FieldRef ValuablePhotonViewRef = CreateFieldRef("photonView"); private static readonly FieldRef ValuablePhysGrabObjectRef = CreateFieldRef("physGrabObject"); private static readonly FieldRef> PhysGrabCartItemsInCartRef = CreateFieldRef>("itemsInCart"); private static readonly FieldRef PhysGrabCartPhysGrabObjectRef = CreateFieldRef("physGrabObject"); private static readonly FieldRef PhysGrabCartBeingPulledRef = CreateFieldRef("cartBeingPulled"); private static readonly FieldRef PhysGrabCartCurrentStateRef = CreateFieldRef("currentState"); private static readonly FieldRef PhysGrabCartItemEquippableRef = CreateFieldRef("itemEquippable"); private static readonly FieldRef> PhysGrabInCartObjectsRef = CreateFieldRef>("inCartObjects"); private static readonly FieldRef ItemEquippableCurrentStateRef = CreateFieldRef("currentState"); private static readonly FieldRef PhysGrabberGrabbedPhysGrabObjectRef = CreateFieldRef("grabbedPhysGrabObject"); private static readonly FieldRef PhysGrabberIsPushingRef = CreateFieldRef("isPushing"); private static readonly FieldRef PhysGrabberIsPullingRef = CreateFieldRef("isPulling"); private static readonly FieldRef PlayerWorldSpaceUIPlayerNameRef = CreateFieldRef("worldSpaceUIPlayerName"); private static readonly FieldRef WsUiPlayerAvatarRef = CreateFieldRef("playerAvatar"); private static readonly FieldRef WsUiShowTimerRef = CreateFieldRef("showTimer"); private static readonly FieldRef ItemAttribNameRef = CreateFieldRef("itemName"); private static readonly FieldRef ItemAttribPromptNameRef = CreateFieldRef("promptName"); private static readonly FieldRef ItemAttribAssetNameRef = CreateFieldRef("itemAssetName"); private static readonly FieldRef ItemAttribInstanceNameRef = CreateFieldRef("instanceName"); private static readonly FieldRef ItemAttribTagRef = CreateFieldRef("itemTag"); private static readonly FieldRef ItemAttribTypeRef = CreateFieldRef("itemType"); private static readonly FieldRef ItemVehicleSeatsRef = CreateFieldRef("seats"); private static readonly FieldRef ItemVehicleIsRacingRef = CreateFieldRef("isRacingVehicle"); internal static readonly Dictionary _cfgByEnSection = new Dictionary(StringComparer.Ordinal); internal static readonly Dictionary _cfgByEnKey = new Dictionary(StringComparer.Ordinal); internal static readonly Dictionary> _cfgByKeyOnly = new Dictionary>(StringComparer.Ordinal); private static readonly List _cfgI18Ns = new List(64); private static readonly string[] _chineseModKeywords = new string[6] { "chinese", "简体", "繁體", "繁体", "汉化", "中文" }; private static readonly string[] _chineseEnvironmentPluginGuids = new string[1] { "gravydevsupreme.xunity.autotranslator" }; private static readonly List _liveLabels = new List(64); private static readonly List _liveValues = new List(8); private static readonly List _liveSliderOptions = new List(4); private static readonly List _liveToggleButtons = new List(16); private static readonly Dictionary _labelTmpFieldCache = new Dictionary(8); private static readonly Dictionary _sliderStringOptionsPropCache = new Dictionary(4); private static readonly Dictionary _toggleLeftTmpCache = new Dictionary(4); private static readonly Dictionary _toggleRightTmpCache = new Dictionary(4); private static readonly Dictionary _pendingKeyMatchIndex = new Dictionary(StringComparer.Ordinal); internal static string _currentRenderingConfigFilePath; internal static bool _createModEntriesPatchInstalled; private static readonly Dictionary _inputStringSystemFieldCache = new Dictionary(4); private static readonly Dictionary _inputStringSystemSetValueCache = new Dictionary(4); private static readonly Dictionary _enumNameCNtoEN = new Dictionary(StringComparer.Ordinal) { ["中文"] = "Chinese", ["文字显示"] = "Text Mode", ["原生UI显示"] = "Native UI" }; private static readonly Dictionary _enumNameENtoCN = new Dictionary(StringComparer.Ordinal) { ["English"] = "英语", ["Chinese"] = "中文" }; private const float NativeOverlayRightMargin = -2f; private const float NativeOverlayBottomMargin = -2f; private const float NativeOverlayCompactLineSpacing = -4f; private const float NativeOverlayCompactParagraphSpacing = -1f; private const float NativeOverlayBreakdownWidth = 430f; private const float NativeOverlaySummaryWidth = 320f; private float tokenBoxCountLastUpdate = -1f; private const float TokenBoxCountCacheSeconds = 1f; private static readonly Dictionary vehicleLabelIndices = new Dictionary(); private static int nextVehicleLabelIndex = 1; private static int vehicleLabelIndexLevelNumber = -1; private static readonly List activeVehicleBuffer = new List(); private DisplayLanguage CurrentLanguage { get { if (displayLanguage != null) { return displayLanguage.Value; } return DisplayLanguage.English; } } private bool UseEnemyNicknameNames { get { if (CurrentLanguage == DisplayLanguage.中文 && enemyNicknameEnabled != null) { return enemyNicknameEnabled.Value; } return false; } } private void Awake() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown DetachFromManager(); Instance = this; MakePluginHostPersistent(); Application.logMessageReceived += new LogCallback(OnUnityLogMessageReceived); ResetConfigIfVersionChanged(); BindConfig(); Harmony val = new Harmony("zichen.moreui"); ApplyValuableHaulPatch(); ApplyNativeNamePatch(); TryHookREPOConfig(val); if (displayLanguage != null) { displayLanguage.SettingChanged += delegate { RefreshAllI18N(); }; } ((BaseUnityPlugin)this).Logger.LogInfo((object)"moreui loaded."); } private void BindConfig() { DisplayLanguage defaultVal = DetectDefaultLanguage(); displayLanguage = BindI18N("A.Mod Info", "A.模组信息", "More UI Language", "语言", "Switch display language.", "切换显示语言。", defaultVal, null, 980, null, "Language"); BindReadOnlyI18N("A.Mod Info", "A.模组信息", "More UI Mod Name", "模组名称", "More UI", "更多的UI显示", 1000, null, "Mod Name"); BindReadOnlyI18N("A.Mod Info", "A.模组信息", "More UI Mod Version", "模组版本号", "1.3.4", "1.3.4", 990, null, "Mod Version"); modEnabled = BindI18N("B.Global", "B.全局设置", "Mod Enabled", "模组启用", "Disable to turn off all features (HUD, teammate/cart distance, monster stats, value tracking, all Harmony patches).", "关闭后整个模组所有UI显示功能都不生效,包括右下角显示、队友/敌人距离、购物车距离、怪物统计和价值统计。", defaultVal: true, null, 990); enemyNicknameEnabled = BindI18N("B.Global", "B.全局设置", "Enemy Nicknames", "敌人名字优化", "Default on. Only affects Chinese mode: replaces literal translations with friendlier nicknames. English mode always uses English.", "默认开启。仅在语言为中文时生效,会把直接翻译的敌人名称优化成更顺口、更好辨认的中文名字;语言为 English 时始终显示英文。", defaultVal: true, null, 970); teammateOverlayEnabled = BindI18N("C.Teammate Display", "C.好友局内显示", "Enabled", "启用", "Always show teammate names, distance and death status. Disable to fall back to the game's proximity-based name display.", "开启后始终显示好友名字、距离和死亡状态。关闭后使用游戏自带的靠近检测显示逻辑。", defaultVal: true, null, 600); teammateDeadOverlayEnabled = BindI18N("C.Teammate Display", "C.好友局内显示", "Show Dead Teammates", "死亡好友显示", "Show name and distance for dead teammates in the world.", "开启后,局内显示死亡好友的名字和距离。", defaultVal: true, null, 599); teammateDeadEdgeOverlayEnabled = BindI18N("C.Teammate Display", "C.好友局内显示", "Dead Teammate Edge Hint", "死亡好友离屏边缘提示", "Show name and distance on left/right screen edges when a dead teammate is off-screen.", "开启后,死亡好友离开屏幕时会在左/右边缘显示名字和距离。", defaultVal: true, null, 598); teammateAliveOverlayEnabled = BindI18N("C.Teammate Display", "C.好友局内显示", "Show Alive Teammates", "存活好友显示", "Show name and distance for alive teammates in the world.", "开启后,局内显示存活好友的名字和距离。", defaultVal: true, null, 597); teammateAliveEdgeOverlayEnabled = BindI18N("C.Teammate Display", "C.好友局内显示", "Alive Teammate Edge Hint", "存活好友离屏边缘提示", "Show name and distance on left/right screen edges when an alive teammate is off-screen.", "开启后,存活好友离开屏幕时会在左/右边缘显示名字和距离。", defaultVal: false, null, 596); teammateDistanceEnabled = BindI18N("C.Teammate Display", "C.好友局内显示", "Show Distance Meters", "显示米数", "Append distance in meters after teammate world labels and edge hints. Off by default.", "开启后,好友局内标签和离屏边缘提示会显示距离米数。默认关闭。", defaultVal: false, null, 595); teammateFontSize = BindI18N("C.Teammate Display", "C.好友局内显示", "Font Size", "字体大小", "Font size of teammate names. The game's native default is around 20; this value overrides it.", "好友名字的字体大小。游戏原生默认约20,此值会覆盖原生大小。", 22, (AcceptableValueBase)(object)new AcceptableValueRange(10, 60), 590); cartSectionEnabled = BindI18N("D1.Cart Display", "D1.购物车局内显示", "Enabled", "启用", "Disable to hide all cart world labels.", "关闭后购物车局内显示全部不显示。", defaultVal: true, null, 530); smallCartOverlayEnabled = BindI18N("D1.Cart Display", "D1.购物车局内显示", "Show Small Cart", "显示小购物车", "Show index and distance on small carts.", "在小购物车上显示编号和距离。", defaultVal: true, null, 520); cartOverlayEnabled = BindI18N("D1.Cart Display", "D1.购物车局内显示", "Show Large Cart", "显示大购物车", "Show index and distance on large carts.", "在大购物车上显示编号和距离。", defaultVal: true, null, 518); cartDistanceEnabled = BindI18N("D1.Cart Display", "D1.购物车局内显示", "Show Distance Meters", "显示米数", "Append distance in meters after cart labels. Off by default.", "开启后,在购物车局内标签后面追加距离米数。默认关闭。", defaultVal: false, null, 517); cartFontSize = BindI18N("D1.Cart Display", "D1.购物车局内显示", "Font Size", "字体大小", "Font size of cart labels. Used as the near-distance maximum; far-distance labels shrink by a percentage.", "购物车局内文字的字体大小。近距离显示不超过这个大小,远距离会按变小百分比缩小。", 20, (AcceptableValueBase)(object)new AcceptableValueRange(10, 36), 515); vehicleSectionEnabled = BindI18N("D2.Vehicle Display", "D2.载具局内显示", "Enabled", "启用", "Disable to hide all vehicle world labels.", "关闭后载具局内显示全部不显示。", defaultVal: true, null, 510); racingVehicleOverlayEnabled = BindI18N("D2.Vehicle Display", "D2.载具局内显示", "Show Racing Vehicle", "显示赛车", "Show label and distance on racing vehicles.", "在赛车上显示标签和距离。", defaultVal: true, null, 508); vehicleOverlayEnabled = BindI18N("D2.Vehicle Display", "D2.载具局内显示", "Show Cargo Vehicle", "显示载货车", "Show label and distance on cargo vehicles.", "在载货车上显示标签和距离。", defaultVal: true, null, 506); vehicleDistanceEnabled = BindI18N("D2.Vehicle Display", "D2.载具局内显示", "Show Distance Meters", "显示米数", "Append distance in meters after vehicle labels. Off by default.", "开启后,在载具局内标签后面追加距离米数。默认关闭。", defaultVal: false, null, 504); vehicleFontSize = BindI18N("D2.Vehicle Display", "D2.载具局内显示", "Font Size", "字体大小", "Font size of vehicle labels.", "载具局内文字的字体大小。", 20, (AcceptableValueBase)(object)new AcceptableValueRange(10, 36), 502); overlayEnabled = BindI18N("E1.Panel Basics", "E1.右下角基础设置", "Enabled", "启用", "Show extra info in the bottom-right corner.", "是否在右下角显示额外信息。", defaultVal: true, null, 960); sectionSpacing = BindI18N("E1.Panel Basics", "E1.右下角基础设置", "Section Spacing", "不同分区空行", "Default on. Inserts a blank line between different info sections.", "默认开启。开启后不同信息分区之间会插入一行空白。", defaultVal: true, null, 955); displayMode = BindI18N("E1.Panel Basics", "E1.右下角基础设置", "Display Mode", "显示模式", "Bottom-right uses text mode by default with 70% opacity. Can switch to native UI style.", "右下角默认使用文字显示,默认透明度为 70%,也可切换为更贴近游戏的原生UI显示。", DisplayMode.文字显示, null, 952, DrawDisplayMode); fontSize = BindI18N("E1.Panel Basics", "E1.右下角基础设置", "Font Size", "字体大小", "Display font size.", "显示文字的字体大小。", 22, (AcceptableValueBase)(object)new AcceptableValueRange(10, 28), 950); overlayTextOpacityPercent = BindI18N("E1.Panel Basics", "E1.右下角基础设置", "Text Opacity %", "文字透明度/%", "Controls overall opacity of both text mode and native UI mode. Default 70.", "右下角默认以文字显示为主时,这里控制文字显示和原生UI显示的整体透明度,默认 70%。", 70, (AcceptableValueBase)(object)new AcceptableValueRange(1, 100), 949); updateInterval = BindI18N("E1.Panel Basics", "E1.右下角基础设置", "Refresh Interval (s)", "刷新间隔/秒", "How many seconds between display refreshes.", "每隔多少秒刷新一次显示。", 3f, (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 10f), 940); overlayOffsetX = BindI18N("E1.Panel Basics", "E1.右下角基础设置", "Offset X (px)", "右下角X偏移/像素", "Horizontal offset of the bottom-right info. Positive moves left, negative moves right.", "右下角信息的水平偏移。正数向左移动,负数向右移动。", 0, (AcceptableValueBase)(object)new AcceptableValueRange(-600, 600), 930); overlayOffsetY = BindI18N("E1.Panel Basics", "E1.右下角基础设置", "Offset Y (px)", "右下角Y偏移/像素", "Vertical offset of the bottom-right info. Positive moves up, negative moves down.", "右下角信息的垂直偏移。正数向上移动,负数向下移动。", 0, (AcceptableValueBase)(object)new AcceptableValueRange(-600, 600), 920); showEnemySection = BindI18N("E2.Monster Stats", "E2.右下角怪物统计", "Enabled", "启用", "Disable to hide the monster stats section.", "关闭后右下角怪物统计分区全部不显示。", defaultVal: true, null, 800); showBreakdown = BindI18N("E2.Monster Stats", "E2.右下角怪物统计", "Show Breakdown", "显示怪物明细", "Show count per monster type.", "显示每种怪物当前数量。", defaultVal: true, null, 790); showTotalEnemyCount = BindI18N("E2.Monster Stats", "E2.右下角怪物统计", "Show Total", "显示怪物总数", "Show total alive monster count.", "显示当前存活怪物总数。", defaultVal: true, null, 780); showValueSection = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Enabled", "启用", "Disable to hide the value stats section.", "关闭后右下角价值统计分区全部不显示。", defaultVal: true, null, 770); showTokenBoxCount = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Show Lottery Boxes", "显示装饰箱", "Show the number of lottery / decor boxes (token machines, coin chests, etc.) in the current level.", "显示当前关卡中装饰箱的数量(包括投币机、硬币宝箱、代币箱等)。", defaultVal: true, null, 769); showKartCount = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Show Kart Count", "显示赛车数量", "Show kart (racing vehicle) count for the current level in the bottom-right.", "在右下角显示当前关卡的赛车数量。", defaultVal: false, null, 768); showCargoCount = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Show Cargo Count", "显示载货车数量", "Show cargo vehicle count for the current level in the bottom-right.", "在右下角显示当前关卡的载货车数量。", defaultVal: false, null, 767); showSmallCartCount = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Show Small Cart Count", "显示小购物车数量", "Show small cart count for the current level in the bottom-right.", "在右下角显示当前关卡的小购物车数量。", defaultVal: false, null, 766); showLargeCartCount = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Show Large Cart Count", "显示大购物车数量", "Show large cart count for the current level in the bottom-right.", "在右下角显示当前关卡的大购物车数量。", defaultVal: false, null, 765); showExplorationProgress = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Show Extraction Progress", "显示收集进度", "Shows extraction progress as a percent of the map's initial total value. Items in extraction points or carts count as collected.", "单独显示收集进度。进度按地图初始总价值计算,已放到提取点或购物车的物资也算作已收集。", defaultVal: true, null, 760); showMapLostValue = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Show Run Lost Funds", "显示损坏宝物", "Show value lost from broken or destroyed valuables in this run.", "显示本局中已摔坏或丢失造成的宝物损失。", defaultVal: true, null, 750); showMapTotalValue = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Show Map Remaining", "显示地图库存", "Shows remaining map value. Items already in extraction points are excluded; carts and uncollected items still count.", "显示当前地图库存。已放到提取点的物品会被排除,购物车里和地图上未收集的物品仍会计入。", defaultVal: true, null, 740); showCurrentRunSubmittedFunds = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Show Submitted Funds", "显示提交资金", "Show funds successfully extracted and settled this run. Items only placed at the extraction point but not yet finalized do not count.", "显示本局已经成功带走并结算的提交资金。仅放进提取点但未提取成功时不会计入。", defaultVal: true, null, 730); showShopRemainingFunds = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Show Shop Stock", "显示商店库存", "Shows shop remaining funds. Snapshot taken once per run start; submissions in the current level do not increase this.", "显示商店库存。此值只在每局开始读取一次快照,当前关卡提交物品不会让它上涨。", defaultVal: true, null, 720); showLevelInfo = BindI18N("E3.Value Stats", "E3.右下角价值统计", "Show Level", "显示关卡", "Show current level number and name, below shop stock.", "显示当前关卡编号和名称,位于商店库存下面。", defaultVal: true, null, 710); showTeammateInfoSection = BindI18N("E4.Teammate Info", "E4.右下角好友信息", "Enabled", "启用", "Disable to hide the bottom-right teammate info section.", "关闭后右下角好友信息分区全部不显示。", defaultVal: true, null, 670); showDeadTeammates = BindI18N("E4.Teammate Info", "E4.右下角好友信息", "Show Dead Teammates Info", "显示死亡好友信息", "Show dead teammate icon, name and distance at the top of the section. Closer teammates appear higher.", "在右下角好友信息分区顶部显示死亡好友图标、名字和距离,距离越近越靠上。", defaultVal: true, null, 660); showAliveTeammates = BindI18N("E4.Teammate Info", "E4.右下角好友信息", "Show Alive Teammates Info", "显示存活好友信息", "Show name and distance of each alive teammate. Closer teammates appear higher.", "在右下角好友信息分区显示每个存活好友的名字和距离,距离越近越靠上。", defaultVal: true, null, 650); showPlayerCounts = BindI18N("E4.Teammate Info", "E4.右下角好友信息", "Show Player Counts", "显示玩家", "Show dead / alive / total player counts at the bottom of the teammate section.", "在右下角好友信息分区最底部显示死亡、存活和总玩家。", defaultVal: true, null, 640); } private void ResetConfigIfVersionChanged() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; if (File.Exists(configFilePath)) { string text = ReadConfigPluginVersion(configFilePath); if (!(text == "1.3.4")) { ResetConfigFileToDefaults(configFilePath); ((BaseUnityPlugin)this).Logger.LogWarning((object)(string.IsNullOrWhiteSpace(text) ? "Old config without Mod Version, reset to defaults." : ("Config version " + text + " -> 1.3.4, 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)^More UI Mod Version\\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 void Update() { try { UpdateCore(); } catch (Exception ex) { ResetRuntimeDisplayState(); if (!hasLoggedUpdateError) { hasLoggedUpdateError = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)("moreui update skipped after an error: " + ex.GetType().Name + ": " + ex.Message)); } } } private void UpdateCore() { bool flag = IsRuntimeSessionActive(); if (!IsModEnabled() || !flag) { if (runtimeWasActive) { runtimeWasActive = false; ResetLossTracking(); ResetRuntimeDisplayState(); } return; } runtimeWasActive = true; refreshTimer += Time.deltaTime; UpdateCartDistanceCache(); UpdateVehicleDistanceCache(); bool flag2 = overlayEnabled.Value && displayMode.Value == DisplayMode.原生UI显示; if (refreshTimer >= ClampRefreshInterval((updateInterval == null) ? 1.5f : updateInterval.Value)) { refreshTimer = 0f; overlayText = (overlayEnabled.Value ? BuildOverlayText() : string.Empty); if (flag2) { UpdateNativeOverlay(); } } if (flag2 && !string.IsNullOrWhiteSpace(overlayText)) { SetNativeOverlayVisible(visible: true); } else { SetNativeOverlayVisible(visible: false); } } private static float ClampRefreshInterval(float value) { if (float.IsNaN(value) || float.IsInfinity(value)) { return 0.1f; } return Mathf.Max(0.1f, value); } private void MakePluginHostPersistent() { 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 void OnUnityLogMessageReceived(string condition, string stackTrace, LogType type) { if (!string.IsNullOrEmpty(condition)) { int num = condition.IndexOf("Changed level to:", StringComparison.OrdinalIgnoreCase); int length = "Changed level to:".Length; if (num < 0) { num = condition.IndexOf("updated level to:", StringComparison.OrdinalIgnoreCase); length = "updated level to:".Length; } if (num >= 0) { string name = condition.Substring(num + length).Trim(); levelTransitionLogIndicatesRun = LooksLikePlayableSessionName(name); } } } private void DetachFromManager() { ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } private void OnDestroy() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown Application.logMessageReceived -= new LogCallback(OnUnityLogMessageReceived); if (Instance == this) { Instance = null; } ZichenMapValueService.Reset(); if (valuableHaulHarmony != null) { valuableHaulHarmony.UnpatchSelf(); valuableHaulHarmony = null; } if (nativeNameHarmony != null) { nativeNameHarmony.UnpatchSelf(); nativeNameHarmony = null; } valuablesCurrentlyInDollarHaul.Clear(); if ((Object)(object)overlayObject != (Object)null) { Object.Destroy((Object)(object)overlayObject); overlayObject = null; overlayRect = null; overlayLabel = null; lastNativeOverlayParent = null; } } private static void DrawDisplayMode(ConfigEntryBase entry) { if (entry is ConfigEntry val) { GUILayout.BeginHorizontal(Array.Empty()); GUILayout.Label(entry.Definition.Key, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); DisplayMode value = val.Value; if (GUILayout.Button((!UseChinese()) ? ((value == DisplayMode.原生UI显示) ? "Native UI" : "Text") : ((value == DisplayMode.原生UI显示) ? "原生UI显示" : "文字显示"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) })) { val.Value = ((value == DisplayMode.文字显示) ? DisplayMode.原生UI显示 : DisplayMode.文字显示); } GUILayout.EndHorizontal(); } } private bool IsModEnabled() { if (modEnabled != null) { return modEnabled.Value; } return true; } private bool IsRuntimeSessionActive() { if (IsRunLevelActive()) { lastConfirmedRunLevelTime = Time.unscaledTime; return true; } if (runtimeWasActive && Time.unscaledTime - lastConfirmedRunLevelTime <= 4f) { return true; } return false; } private void ResetRuntimeDisplayState() { overlayText = string.Empty; lastTextOverlaySource = null; lastTextOverlayFontSize = -1; lastTextOverlayScreenWidth = -1; lastTextOverlayScreenHeight = -1; cachedTextOverlayPlainText = string.Empty; enemyDisplayNameCache.Clear(); enemyBreakdownRankCache.Clear(); enemyBreakdownRawNameRankCache.Clear(); playerNameCache.Clear(); playerColorCache.Clear(); cartLabelYOffsetCache.Clear(); cartComponentCache.Clear(); itemSearchTextCache.Clear(); itemTokenBoxCandidateCache.Clear(); playerPositionCache.Clear(); playerObjectsFrameCache = null; cachedLocalPlayer = null; cachedLocalPlayerFrame = -1; playerCountsFrame = -1; cachedTotalPlayers = 0; cachedAlivePlayers = 0; cachedDeadPlayers = 0; ResetTrackedObjectCleanupSchedule(); enemyObjectsFrameCacheFrame = -1; cartObjectsFrameCacheFrame = -1; grabberObjectsFrameCacheFrame = -1; valuableObjectsFrameCacheFrame = -1; playerObjectsFrameCacheFrame = -1; ClearCartLabelIndices(); ClearCartDistanceCache(); ClearVehicleDistanceCache(); SetNativeOverlayVisible(visible: false); } private static bool IsRunLevelSafe() { try { return IsRunLevelActive(); } catch { return false; } } private static int GetCurrentMapValueLevelNumber() { try { return SemiFunc.RunGetLevelsCompleted() + 1; } catch { return 0; } } private static bool IsRunLevelActive() { int frameCount = Time.frameCount; if (cachedRunLevelActiveFrame == frameCount) { return cachedRunLevelActive; } cachedRunLevelActiveFrame = frameCount; cachedRunLevelActive = IsRunLevelActiveUncached(); return cachedRunLevelActive; } private static bool IsRunLevelActiveUncached() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) try { if (SemiFunc.RunIsShop()) { return true; } } catch { } try { if ((Object)(object)RunManager.instance != (Object)null && (Object)(object)RunManager.instance.levelCurrent != (Object)null) { string name = ((Object)RunManager.instance.levelCurrent).name; string narrativeName = RunManager.instance.levelCurrent.NarrativeName; if (IsNonPlayableLevelName(name) || IsNonPlayableLevelName(narrativeName)) { return false; } } } catch { } try { Scene activeScene = SceneManager.GetActiveScene(); if (IsNonPlayableLevelName(((Scene)(ref activeScene)).name)) { return false; } } catch { } try { if (IsGameDirectorSessionStateActive()) { return true; } } catch { } try { if (SemiFunc.RunIsLevel()) { return true; } } catch { } Plugin instance = Instance; if ((Object)(object)instance != (Object)null && instance.levelTransitionLogIndicatesRun) { return true; } try { if ((Object)(object)RunManager.instance != (Object)null && (Object)(object)RunManager.instance.levelCurrent != (Object)null) { string name2 = ((Object)RunManager.instance.levelCurrent).name; string narrativeName2 = RunManager.instance.levelCurrent.NarrativeName; return LooksLikePlayableSessionName(name2) || LooksLikePlayableSessionName(narrativeName2); } } catch { } return false; } private static bool IsGameDirectorSessionStateActive() { if ((Object)(object)GameDirector.instance == (Object)null) { return false; } switch (((object)(gameState)(ref GameDirector.instance.currentState)).ToString()) { case "Main": case "Outro": case "End": case "EndWait": case "Death": return true; default: return false; } } private static bool LooksLikePlayableSessionName(string name) { if (string.IsNullOrWhiteSpace(name) || IsNonPlayableLevelName(name)) { return false; } if (name.IndexOf("Level", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Shop", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Lobby", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Rest", StringComparison.OrdinalIgnoreCase) < 0) { return name.IndexOf("Truck", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static bool IsNonPlayableLevelName(string name) { if (string.IsNullOrWhiteSpace(name)) { return false; } if (name.IndexOf("Menu", StringComparison.OrdinalIgnoreCase) < 0) { return name.IndexOf("Splash", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static bool IsStaticModEnabled() { Plugin instance = Instance; if (!((Object)(object)instance == (Object)null)) { return instance.IsModEnabled(); } return true; } private bool IsCartFeatureEnabled() { if (cartSectionEnabled != null && cartSectionEnabled.Value) { if (cartOverlayEnabled == null || !cartOverlayEnabled.Value) { if (smallCartOverlayEnabled != null) { return smallCartOverlayEnabled.Value; } return false; } return true; } return false; } private bool IsVehicleFeatureEnabled() { if (vehicleSectionEnabled != null && vehicleSectionEnabled.Value) { if (vehicleOverlayEnabled == null || !vehicleOverlayEnabled.Value) { if (racingVehicleOverlayEnabled != null) { return racingVehicleOverlayEnabled.Value; } return false; } return true; } return false; } internal static void NotifyTrackedObjectDestroyed(ValuableObject valuable, PhysGrabCart cart, Enemy enemy, ValuableDiscoverCustom customDiscoverable, CosmeticShopMachine machine, ItemVehicle vehicle = null) { UnregisterTrackedValuable(valuable); UnregisterTrackedCart(cart); UnregisterTrackedEnemy(enemy); UnregisterTrackedCustomDiscoverable(customDiscoverable); UnregisterTrackedCosmeticShopMachine(machine); if ((Object)(object)vehicle != (Object)null) { UnregisterTrackedVehicle(vehicle); } } private static FieldRef CreateFieldRef(string fieldName) where TInstance : class { try { return AccessTools.FieldRefAccess(fieldName); } catch { return null; } } internal static bool GetPlayerDeadSetFast(PlayerAvatar player) { if ((Object)(object)player != (Object)null && PlayerDeadSetRef != null) { return PlayerDeadSetRef.Invoke(player); } return false; } internal static bool GetPlayerIsDisabledFast(PlayerAvatar player) { if ((Object)(object)player != (Object)null && PlayerIsDisabledRef != null) { return PlayerIsDisabledRef.Invoke(player); } return false; } internal static bool GetPlayerIsLocalFast(PlayerAvatar player) { if ((Object)(object)player != (Object)null && PlayerIsLocalRef != null) { return PlayerIsLocalRef.Invoke(player); } return false; } internal static string GetPlayerInternalNameFast(PlayerAvatar player) { if (!((Object)(object)player == (Object)null) && PlayerNameRef != null) { return PlayerNameRef.Invoke(player); } return null; } internal static int[] GetPlayerCosmeticsColorsFast(PlayerCosmetics cosmetics) { if (!((Object)(object)cosmetics == (Object)null) && PlayerCosmeticsColorsEquippedRef != null) { return PlayerCosmeticsColorsEquippedRef.Invoke(cosmetics); } return null; } internal static PlayerDeathHead GetPlayerDeathHeadFast(PlayerAvatar player) { if (!((Object)(object)player == (Object)null) && PlayerDeathHeadRef != null) { return PlayerDeathHeadRef.Invoke(player); } return null; } internal static bool TryGetPlayerLastNavmeshPositionFast(PlayerAvatar player, 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; if ((Object)(object)player == (Object)null || PlayerLastNavmeshPositionRef == null) { return false; } position = PlayerLastNavmeshPositionRef.Invoke(player); return ((Vector3)(ref position)).sqrMagnitude > 0.001f; } internal static PhysGrabObject GetDeathHeadPhysGrabObjectFast(PlayerDeathHead deathHead) { if (!((Object)(object)deathHead == (Object)null) && DeathHeadPhysGrabObjectRef != null) { return DeathHeadPhysGrabObjectRef.Invoke(deathHead); } return null; } internal static Transform GetDeathHeadOverridePositionTransformFast(PlayerDeathHead deathHead) { if (!((Object)(object)deathHead == (Object)null) && DeathHeadOverridePositionTransformRef != null) { return DeathHeadOverridePositionTransformRef.Invoke(deathHead); } return null; } internal static bool TryGetDeathHeadTriggeredPositionFast(PlayerDeathHead deathHead, 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; if ((Object)(object)deathHead == (Object)null || DeathHeadTriggeredPositionRef == null) { return false; } position = DeathHeadTriggeredPositionRef.Invoke(deathHead); return ((Vector3)(ref position)).sqrMagnitude > 0.001f; } internal static PlayerAvatar GetSpectateCameraPlayerFast(SpectateCamera spectateCamera) { if (!((Object)(object)spectateCamera == (Object)null) && SpectateCameraPlayerRef != null) { return SpectateCameraPlayerRef.Invoke(spectateCamera); } return null; } internal static PlayerAvatar GetSpectateCameraPlayerOverrideFast(SpectateCamera spectateCamera) { if (!((Object)(object)spectateCamera == (Object)null) && SpectateCameraPlayerOverrideRef != null) { return SpectateCameraPlayerOverrideRef.Invoke(spectateCamera); } return null; } internal static Camera GetSpectateCameraMainCameraFast(SpectateCamera spectateCamera) { if (!((Object)(object)spectateCamera == (Object)null) && SpectateCameraMainCameraRef != null) { return SpectateCameraMainCameraRef.Invoke(spectateCamera); } return null; } internal static EnemyParent GetEnemyParentFast(Enemy enemy) { if (!((Object)(object)enemy == (Object)null) && EnemyParentRef != null) { return EnemyParentRef.Invoke(enemy); } return null; } internal static EnemyHealth GetEnemyHealthFast(Enemy enemy) { if (!((Object)(object)enemy == (Object)null) && EnemyHealthRef != null) { return EnemyHealthRef.Invoke(enemy); } return null; } internal static bool GetEnemyHealthDeadFast(EnemyHealth health) { if ((Object)(object)health != (Object)null && EnemyHealthDeadRef != null) { return EnemyHealthDeadRef.Invoke(health); } return false; } internal static bool GetEnemyParentSpawnedFast(EnemyParent parent) { if (!((Object)(object)parent == (Object)null) && EnemyParentSpawnedRef != null) { return EnemyParentSpawnedRef.Invoke(parent); } return true; } internal static Enemy GetEnemyParentEnemyFast(EnemyParent parent) { if (!((Object)(object)parent == (Object)null) && EnemyParentEnemyRef != null) { return EnemyParentEnemyRef.Invoke(parent); } return null; } internal static float GetValuableOriginalValueFast(ValuableObject valuable) { if (!((Object)(object)valuable == (Object)null) && ValuableOriginalValueRef != null) { return Mathf.Max(0f, ValuableOriginalValueRef.Invoke(valuable)); } return 0f; } internal static float GetValuableCurrentValueFast(ValuableObject valuable) { if (!((Object)(object)valuable == (Object)null) && ValuableCurrentValueRef != null) { return Mathf.Max(0f, ValuableCurrentValueRef.Invoke(valuable)); } return 0f; } internal static bool IsValuableValueSetFast(ValuableObject valuable) { if ((Object)(object)valuable != (Object)null) { if (ValuableValueSetRef != null) { return ValuableValueSetRef.Invoke(valuable); } return true; } return false; } internal static PhotonView GetValuablePhotonViewFast(ValuableObject valuable) { if (!((Object)(object)valuable == (Object)null) && ValuablePhotonViewRef != null) { return ValuablePhotonViewRef.Invoke(valuable); } return null; } internal static PhysGrabObject GetValuablePhysGrabObjectFast(ValuableObject valuable) { if (!((Object)(object)valuable == (Object)null) && ValuablePhysGrabObjectRef != null) { return ValuablePhysGrabObjectRef.Invoke(valuable); } return null; } internal static List GetCartItemsInCartFast(PhysGrabCart cart) { if (!((Object)(object)cart == (Object)null) && PhysGrabCartItemsInCartRef != null) { return PhysGrabCartItemsInCartRef.Invoke(cart); } return null; } internal static PhysGrabObject GetCartPhysGrabObjectFast(PhysGrabCart cart) { if (!((Object)(object)cart == (Object)null) && PhysGrabCartPhysGrabObjectRef != null) { return PhysGrabCartPhysGrabObjectRef.Invoke(cart); } return null; } internal static bool GetCartBeingPulledFast(PhysGrabCart cart) { if ((Object)(object)cart != (Object)null && PhysGrabCartBeingPulledRef != null) { return PhysGrabCartBeingPulledRef.Invoke(cart); } return false; } internal static State? GetCartStateFast(PhysGrabCart cart) { if ((Object)(object)cart == (Object)null || PhysGrabCartCurrentStateRef == null) { return null; } return PhysGrabCartCurrentStateRef.Invoke(cart); } internal static ItemEquippable GetCartItemEquippableFast(PhysGrabCart cart) { if (!((Object)(object)cart == (Object)null) && PhysGrabCartItemEquippableRef != null) { return PhysGrabCartItemEquippableRef.Invoke(cart); } return null; } internal static List GetPhysGrabInCartObjectsFast(PhysGrabInCart inCart) { if (!((Object)(object)inCart == (Object)null) && PhysGrabInCartObjectsRef != null) { return PhysGrabInCartObjectsRef.Invoke(inCart); } return null; } internal static ItemState? GetItemEquippableStateFast(ItemEquippable itemEquippable) { if ((Object)(object)itemEquippable == (Object)null || ItemEquippableCurrentStateRef == null) { return null; } return ItemEquippableCurrentStateRef.Invoke(itemEquippable); } internal static PhysGrabObject GetGrabberHeldObjectFast(PhysGrabber grabber) { if (!((Object)(object)grabber == (Object)null) && PhysGrabberGrabbedPhysGrabObjectRef != null) { return PhysGrabberGrabbedPhysGrabObjectRef.Invoke(grabber); } return null; } internal static bool GetGrabberIsPushingFast(PhysGrabber grabber) { if ((Object)(object)grabber != (Object)null && PhysGrabberIsPushingRef != null) { return PhysGrabberIsPushingRef.Invoke(grabber); } return false; } internal static bool GetGrabberIsPullingFast(PhysGrabber grabber) { if ((Object)(object)grabber != (Object)null && PhysGrabberIsPullingRef != null) { return PhysGrabberIsPullingRef.Invoke(grabber); } return false; } internal static WorldSpaceUIPlayerName GetPlayerWorldSpaceUiFast(PlayerAvatar player) { if (!((Object)(object)player == (Object)null) && PlayerWorldSpaceUIPlayerNameRef != null) { return PlayerWorldSpaceUIPlayerNameRef.Invoke(player); } return null; } internal static PlayerAvatar GetWorldSpaceUiPlayerAvatarFast(WorldSpaceUIPlayerName nameUi) { if (!((Object)(object)nameUi == (Object)null) && WsUiPlayerAvatarRef != null) { return WsUiPlayerAvatarRef.Invoke(nameUi); } return null; } internal static void SetWorldSpaceUiShowTimerFast(WorldSpaceUIPlayerName nameUi, float value) { if (!((Object)(object)nameUi == (Object)null) && WsUiShowTimerRef != null) { WsUiShowTimerRef.Invoke(nameUi) = value; } } internal static string GetItemAttribNameFast(ItemAttributes item) { if (!((Object)(object)item == (Object)null) && ItemAttribNameRef != null) { return ItemAttribNameRef.Invoke(item); } return null; } internal static string GetItemAttribPromptNameFast(ItemAttributes item) { if (!((Object)(object)item == (Object)null) && ItemAttribPromptNameRef != null) { return ItemAttribPromptNameRef.Invoke(item); } return null; } internal static string GetItemAttribAssetNameFast(ItemAttributes item) { if (!((Object)(object)item == (Object)null) && ItemAttribAssetNameRef != null) { return ItemAttribAssetNameRef.Invoke(item); } return null; } internal static string GetItemAttribInstanceNameFast(ItemAttributes item) { if (!((Object)(object)item == (Object)null) && ItemAttribInstanceNameRef != null) { return ItemAttribInstanceNameRef.Invoke(item); } return null; } internal static string GetItemAttribTagFast(ItemAttributes item) { if (!((Object)(object)item == (Object)null) && ItemAttribTagRef != null) { return ItemAttribTagRef.Invoke(item); } return null; } internal static string GetItemAttribTypeNameFast(ItemAttributes item) { if ((Object)(object)item == (Object)null || ItemAttribTypeRef == null) { return null; } return ((object)(itemType)(ref ItemAttribTypeRef.Invoke(item))).ToString(); } internal static VehicleSeat[] GetVehicleSeatsFast(ItemVehicle vehicle) { if (!((Object)(object)vehicle == (Object)null) && ItemVehicleSeatsRef != null) { return ItemVehicleSeatsRef.Invoke(vehicle); } return null; } internal static bool GetVehicleIsRacingFast(ItemVehicle vehicle) { if ((Object)(object)vehicle == (Object)null || ItemVehicleIsRacingRef == null) { return false; } return ItemVehicleIsRacingRef.Invoke(vehicle); } internal static bool GetVehicleHasRider(ItemVehicle vehicle) { if ((Object)(object)vehicle == (Object)null) { return false; } VehicleSeat[] vehicleSeatsFast = GetVehicleSeatsFast(vehicle); if (vehicleSeatsFast == null) { return false; } for (int i = 0; i < vehicleSeatsFast.Length; i++) { if (vehicleSeatsFast[i] != null && (Object)(object)vehicleSeatsFast[i].seatedPlayer != (Object)null) { return true; } } return false; } private void ApplyValuableHaulPatch() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown try { valuableHaulHarmony = new Harmony("zichen.moreui.valuablehaul"); PatchValuableHaulMethod("AddToDollarHaulList", "ValuableDollarHaulAddPostfix"); PatchValuableHaulMethod("AddToDollarHaulListRPC", "ValuableDollarHaulAddPostfix"); PatchValuableHaulMethod("RemoveFromDollarHaulList", "ValuableDollarHaulRemovePostfix"); PatchValuableHaulMethod("RemoveFromDollarHaulListRPC", "ValuableDollarHaulRemovePostfix"); PatchValuableTrackingMethod(typeof(ValuableObject), "DollarValueSetLogic", "ValuableDollarValueSetLogicPostfix"); PatchValuableTrackingMethod(typeof(ValuableObject), "DollarValueSetRPC", "ValuableDollarValueSetRpcPostfix"); PatchValuableTrackingMethod(typeof(PhysGrabObjectImpactDetector), "BreakRPC", "ValuableBreakPostfix"); PatchValuableTrackingMethod(typeof(PhysGrabObject), "DestroyPhysGrabObjectRPC", "ValuableDestroyPhysGrabObjectPostfix"); PatchValuableTrackingMethod(typeof(RoundDirector), "ExtractionCompleted", "RoundDirectorExtractionCompletedPostfix"); PatchValuableTrackingMethod(typeof(LevelGenerator), "StartRoomGeneration", "LevelGeneratorStartRoomGenerationPrefix", prefix: true); PatchValuableTrackingMethod(typeof(LevelGenerator), "GenerateDone", "LevelGeneratorGenerateDonePostfix"); PatchValuableTrackingMethod(typeof(ValuableObject), "Start", "ValuableObjectStartPostfix"); PatchValuableTrackingMethod(typeof(PhysGrabCart), "Start", "PhysGrabCartStartPostfix"); PatchValuableTrackingMethod(typeof(ItemVehicle), "Start", "ItemVehicleStartPostfix"); PatchValuableTrackingMethod(typeof(PhysGrabber), "Start", "PhysGrabberStartPostfix"); PatchValuableTrackingMethod(typeof(PhysGrabber), "OnDestroy", "PhysGrabberOnDestroyPrefix", prefix: true); PatchValuableTrackingMethod(typeof(EnemyParent), "Awake", "EnemyParentAwakePostfix"); PatchValuableTrackingMethod(typeof(ItemAttributes), "Start", "ItemAttributesStartPostfix"); PatchValuableTrackingMethod(typeof(ItemAttributes), "OnDestroy", "ItemAttributesOnDestroyPrefix", prefix: true); PatchValuableTrackingMethod(typeof(ValuableDiscoverCustom), "Awake", "ValuableDiscoverCustomAwakePostfix"); PatchValuableTrackingMethod(typeof(CosmeticShopMachine), "Awake", "CosmeticShopMachineAwakePostfix"); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Valuable haul tracking patched."); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Failed to patch valuable haul tracking: {arg}"); } } private void PatchValuableHaulMethod(string originalName, string postfixName) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(ValuableObject), originalName, (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), postfixName, (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to find valuable haul method patch target: " + originalName)); } else { valuableHaulHarmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private void PatchValuableTrackingMethod(Type originalType, string originalName, string patchName, bool prefix = false) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(originalType, originalName, (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), patchName, (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to find valuable tracking patch target: " + originalType?.Name + "." + originalName)); return; } HarmonyMethod val = new HarmonyMethod(methodInfo2); if (prefix) { valuableHaulHarmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { valuableHaulHarmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static void ValuableDollarHaulAddPostfix(ValuableObject __instance) { if (!((Object)(object)__instance == (Object)null) && IsStaticModEnabled()) { valuablesCurrentlyInDollarHaul.Add(GetValuableKey(__instance)); } } private static void ValuableDollarHaulRemovePostfix(ValuableObject __instance) { if (!((Object)(object)__instance == (Object)null) && IsStaticModEnabled()) { valuablesCurrentlyInDollarHaul.Remove(GetValuableKey(__instance)); } } private static void ValuableDollarValueSetLogicPostfix(ValuableObject __instance) { if (IsStaticModEnabled() && IsRunLevelSafe()) { ZichenMapValueService.RegisterValueSet(__instance, GetCurrentMapValueLevelNumber()); } } private static void ValuableDollarValueSetRpcPostfix(ValuableObject __instance, float value) { if (IsStaticModEnabled() && IsRunLevelSafe()) { ZichenMapValueService.RegisterValueSet(__instance, value, GetCurrentMapValueLevelNumber()); } } private static void ValuableBreakPostfix(float valueLost, PhysGrabObjectImpactDetector __instance, bool _loseValue) { if (_loseValue && IsStaticModEnabled() && IsRunLevelSafe()) { ZichenMapValueService.RegisterBreak(((Object)(object)__instance == (Object)null) ? null : ((Component)__instance).GetComponent(), valueLost, GetCurrentMapValueLevelNumber()); } } private static void ValuableDestroyPhysGrabObjectPostfix(PhysGrabObject __instance) { if (!((Object)(object)__instance == (Object)null) && IsStaticModEnabled() && IsRunLevelSafe()) { ValuableObject component = ((Component)__instance).GetComponent(); ZichenMapValueService.RegisterDestroy(component, GetCurrentMapValueLevelNumber()); UnregisterTrackedValuable(component); } } private static void RoundDirectorExtractionCompletedPostfix() { if (IsStaticModEnabled() && IsRunLevelSafe()) { ZichenMapValueService.SyncFromLiveValuables(GetValuableObjectsCachedForFrameStatic(), GetCurrentMapValueLevelNumber()); } } private static void LevelGeneratorStartRoomGenerationPrefix() { if (IsStaticModEnabled()) { if ((Object)(object)Instance != (Object)null) { Instance.ResetLossTracking(); Instance.ClearCartLabelIndices(); Instance.ClearCartDistanceCache(); Instance.ClearVehicleDistanceCache(); Instance.enemyDisplayNameCache.Clear(); Instance.enemyBreakdownRankCache.Clear(); Instance.enemyBreakdownRawNameRankCache.Clear(); Instance.playerNameCache.Clear(); Instance.playerColorCache.Clear(); ResetTrackedObjectCleanupSchedule(); cachedLocalPlayer = null; cachedLocalPlayerFrame = -1; trackedValuables.Clear(); trackedValuableSet.Clear(); trackedCarts.Clear(); trackedCartSet.Clear(); trackedVehicles.Clear(); trackedVehicleSet.Clear(); trackedEnemies.Clear(); trackedEnemySet.Clear(); trackedGrabbers.Clear(); trackedGrabberSet.Clear(); ClearTrackedTokenSources(); } else { valuablesCurrentlyInDollarHaul.Clear(); ZichenMapValueService.Reset(); ResetTrackedObjectCleanupSchedule(); cachedLocalPlayer = null; cachedLocalPlayerFrame = -1; trackedValuables.Clear(); trackedValuableSet.Clear(); trackedCarts.Clear(); trackedCartSet.Clear(); trackedVehicles.Clear(); trackedVehicleSet.Clear(); trackedEnemies.Clear(); trackedEnemySet.Clear(); trackedGrabbers.Clear(); trackedGrabberSet.Clear(); ClearTrackedTokenSources(); } } } private static void LevelGeneratorGenerateDonePostfix() { if (IsStaticModEnabled()) { SyncTrackedObjectsFromScene(); ZichenMapValueService.SyncFromLiveValuables(GetValuableObjectsCachedForFrameStatic(), GetCurrentMapValueLevelNumber()); } } private static void SyncTrackedObjectsFromScene() { CaptureTrackedObjects(trackedCarts, preservedTrackedCartsBuffer); CaptureTrackedObjects(trackedVehicles, preservedTrackedVehiclesBuffer); CaptureTrackedObjects(trackedItems, preservedTrackedItemsBuffer); CaptureTrackedObjects(trackedCustomDiscoverables, preservedTrackedCustomDiscoverablesBuffer); CaptureTrackedObjects(trackedCosmeticShopMachines, preservedTrackedCosmeticShopMachinesBuffer); try { trackedValuables.Clear(); trackedValuableSet.Clear(); List list = (((Object)(object)ValuableDirector.instance == (Object)null) ? null : ValuableDirector.instance.valuableList); if (list != null) { foreach (ValuableObject item in list) { RegisterTrackedValuable(item); } } trackedCarts.Clear(); trackedCartSet.Clear(); trackedVehicles.Clear(); trackedVehicleSet.Clear(); trackedEnemies.Clear(); trackedEnemySet.Clear(); List list2 = (((Object)(object)EnemyDirector.instance == (Object)null) ? null : EnemyDirector.instance.enemiesSpawned); if (list2 != null) { foreach (EnemyParent item2 in list2) { RegisterTrackedEnemyFromParent(item2); } } trackedGrabbers.Clear(); trackedGrabberSet.Clear(); List list3 = (((Object)(object)GameDirector.instance == (Object)null) ? null : GameDirector.instance.PlayerList); if (list3 != null) { foreach (PlayerAvatar item3 in list3) { RegisterTrackedGrabber(((Object)(object)item3 == (Object)null) ? null : item3.physGrabber); } } ClearTrackedTokenSources(); List list4 = (((Object)(object)ItemManager.instance == (Object)null) ? null : ItemManager.instance.spawnedItems); if (list4 != null) { foreach (ItemAttributes item4 in list4) { RegisterTrackedItem(item4); RegisterTrackedCart(((Object)(object)item4 == (Object)null) ? null : ((Component)item4).GetComponent()); RegisterTrackedCustomDiscoverable(((Object)(object)item4 == (Object)null) ? null : ((Component)item4).GetComponent()); } } foreach (ItemAttributes item5 in preservedTrackedItemsBuffer) { RegisterTrackedItem(item5); RegisterTrackedCart(((Object)(object)item5 == (Object)null) ? null : ((Component)item5).GetComponent()); RegisterTrackedCustomDiscoverable(((Object)(object)item5 == (Object)null) ? null : ((Component)item5).GetComponent()); } foreach (PhysGrabCart item6 in preservedTrackedCartsBuffer) { RegisterTrackedCart(item6); } foreach (ItemVehicle item7 in preservedTrackedVehiclesBuffer) { RegisterTrackedVehicle(item7); } List list5 = (((Object)(object)RoundDirector.instance == (Object)null) ? null : RoundDirector.instance.cosmeticWorldObjects); if (list5 != null) { foreach (CosmeticWorldObject item8 in list5) { RegisterTrackedCustomDiscoverable(((Object)(object)item8 == (Object)null) ? null : ((Component)item8).GetComponent()); } } foreach (ValuableDiscoverCustom item9 in preservedTrackedCustomDiscoverablesBuffer) { RegisterTrackedCustomDiscoverable(item9); } RegisterTrackedCosmeticShopMachine(CosmeticShopMachine.instance); foreach (CosmeticShopMachine item10 in preservedTrackedCosmeticShopMachinesBuffer) { RegisterTrackedCosmeticShopMachine(item10); } } finally { ClearPreservedTrackedObjectBuffers(); } } private static void CaptureTrackedObjects(List source, List destination) { destination.Clear(); if (source != null && source.Count != 0) { destination.AddRange(source); } } private static void ClearPreservedTrackedObjectBuffers() { preservedTrackedCartsBuffer.Clear(); preservedTrackedVehiclesBuffer.Clear(); preservedTrackedItemsBuffer.Clear(); preservedTrackedCustomDiscoverablesBuffer.Clear(); preservedTrackedCosmeticShopMachinesBuffer.Clear(); } private static void ValuableObjectStartPostfix(ValuableObject __instance) { if (!((Object)(object)__instance == (Object)null) && IsStaticModEnabled()) { RegisterTrackedValuable(__instance); } } private static void PhysGrabCartStartPostfix(PhysGrabCart __instance) { if (!((Object)(object)__instance == (Object)null) && IsStaticModEnabled()) { RegisterTrackedCart(__instance); } } private static void ItemVehicleStartPostfix(ItemVehicle __instance) { if (!((Object)(object)__instance == (Object)null) && IsStaticModEnabled()) { RegisterTrackedVehicle(__instance); } } private static void EnemyParentAwakePostfix(EnemyParent __instance) { if (!((Object)(object)__instance == (Object)null) && IsStaticModEnabled()) { RegisterTrackedEnemyFromParent(__instance); } } private static void PhysGrabberStartPostfix(PhysGrabber __instance) { if (!((Object)(object)__instance == (Object)null) && IsStaticModEnabled()) { RegisterTrackedGrabber(__instance); } } private static void PhysGrabberOnDestroyPrefix(PhysGrabber __instance) { UnregisterTrackedGrabber(__instance); } private static void ItemAttributesStartPostfix(ItemAttributes __instance) { if (!((Object)(object)__instance == (Object)null) && IsStaticModEnabled()) { RegisterTrackedItem(__instance); } } private static void ItemAttributesOnDestroyPrefix(ItemAttributes __instance) { UnregisterTrackedItem(__instance); } private static void ValuableDiscoverCustomAwakePostfix(ValuableDiscoverCustom __instance) { if (!((Object)(object)__instance == (Object)null) && IsStaticModEnabled()) { RegisterTrackedCustomDiscoverable(__instance); } } private static void CosmeticShopMachineAwakePostfix(CosmeticShopMachine __instance) { if (!((Object)(object)__instance == (Object)null) && IsStaticModEnabled()) { RegisterTrackedCosmeticShopMachine(__instance); } } private static void RegisterTrackedValuable(ValuableObject valuable) { if ((Object)(object)valuable != (Object)null && trackedValuableSet.Add(valuable)) { trackedValuables.Add(valuable); TrackNotifierForValuable(valuable); } } private static void UnregisterTrackedValuable(ValuableObject valuable) { if (!((Object)(object)valuable == (Object)null)) { trackedValuableSet.Remove(valuable); trackedValuables.Remove(valuable); valuablesCurrentlyInDollarHaul.Remove(GetValuableKey(valuable)); } } private static void RegisterTrackedCart(PhysGrabCart cart) { if ((Object)(object)cart != (Object)null && trackedCartSet.Add(cart)) { trackedCarts.Add(cart); TrackNotifierForCart(cart); Instance?.ClearCartDistanceCache(); } } private static void UnregisterTrackedCart(PhysGrabCart cart) { if (!((Object)(object)cart == (Object)null)) { trackedCartSet.Remove(cart); if (trackedCarts.Remove(cart)) { Instance?.ClearCartDistanceCache(); } } } private static void RegisterTrackedVehicle(ItemVehicle vehicle) { if ((Object)(object)vehicle != (Object)null && trackedVehicleSet.Add(vehicle)) { trackedVehicles.Add(vehicle); TrackNotifierForVehicle(vehicle); Instance?.ClearVehicleDistanceCache(); } } private static void UnregisterTrackedVehicle(ItemVehicle vehicle) { if (!((Object)(object)vehicle == (Object)null)) { trackedVehicleSet.Remove(vehicle); if (trackedVehicles.Remove(vehicle)) { Instance?.ClearVehicleDistanceCache(); } } } private static void RegisterTrackedEnemy(Enemy enemy) { if ((Object)(object)enemy != (Object)null && trackedEnemySet.Add(enemy)) { trackedEnemies.Add(enemy); TrackNotifierForEnemy(enemy); } } private static void RegisterTrackedEnemyFromParent(EnemyParent enemyParent) { if (!((Object)(object)enemyParent == (Object)null)) { Enemy val = GetEnemyParentEnemyFast(enemyParent); if ((Object)(object)val == (Object)null) { val = ((Component)enemyParent).GetComponentInChildren(true); } RegisterTrackedEnemy(val); } } private static void UnregisterTrackedEnemy(Enemy enemy) { if (!((Object)(object)enemy == (Object)null) && (trackedEnemySet.Remove(enemy) || trackedEnemies.Contains(enemy)) && trackedEnemies.Remove(enemy)) { Plugin instance = Instance; if (!((Object)(object)instance == (Object)null)) { int instanceID = ((Object)enemy).GetInstanceID(); instance.enemyDisplayNameCache.Remove(instanceID); instance.enemyBreakdownRankCache.Remove(instanceID); } } } private static void RegisterTrackedGrabber(PhysGrabber grabber) { if ((Object)(object)grabber != (Object)null && trackedGrabberSet.Add(grabber)) { trackedGrabbers.Add(grabber); } } private static void UnregisterTrackedGrabber(PhysGrabber grabber) { if (!((Object)(object)grabber == (Object)null)) { trackedGrabberSet.Remove(grabber); trackedGrabbers.Remove(grabber); } } private static void RegisterTrackedItem(ItemAttributes item) { if ((Object)(object)item != (Object)null && !trackedItems.Contains(item)) { trackedItems.Add(item); if ((Object)(object)Instance != (Object)null && Instance.IsTokenBoxItemCached(item) && !trackedTokenBoxItems.Contains(item)) { trackedTokenBoxItems.Add(item); RegisterTrackedTokenBoxSource((Component)(object)item); } InvalidateTokenBoxCache(); } } private static void UnregisterTrackedItem(ItemAttributes item) { if (!((Object)(object)item == (Object)null)) { trackedItems.Remove(item); if (trackedTokenBoxItems.Remove(item)) { UnregisterTrackedTokenBoxSource((Component)(object)item); } UnregisterTrackedValuable(((Component)item).GetComponent()); UnregisterTrackedCart(((Component)item).GetComponent()); UnregisterTrackedCustomDiscoverable(((Component)item).GetComponent()); Plugin instance = Instance; if ((Object)(object)instance != (Object)null) { instance.itemSearchTextCache.Remove(((Object)item).GetInstanceID()); instance.itemTokenBoxCandidateCache.Remove(((Object)item).GetInstanceID()); } InvalidateTokenBoxCache(); } } private static void RegisterTrackedCustomDiscoverable(ValuableDiscoverCustom customDiscoverable) { if ((Object)(object)customDiscoverable != (Object)null && !trackedCustomDiscoverables.Contains(customDiscoverable)) { trackedCustomDiscoverables.Add(customDiscoverable); TrackNotifierForCustomDiscoverable(customDiscoverable); RegisterTrackedTokenBoxSource((Component)(object)customDiscoverable); InvalidateTokenBoxCache(); } } private static void UnregisterTrackedCustomDiscoverable(ValuableDiscoverCustom customDiscoverable) { if ((Object)(object)customDiscoverable != (Object)null && trackedCustomDiscoverables.Remove(customDiscoverable)) { UnregisterTrackedTokenBoxSource((Component)(object)customDiscoverable); InvalidateTokenBoxCache(); } } private static void RegisterTrackedCosmeticShopMachine(CosmeticShopMachine machine) { if ((Object)(object)machine != (Object)null && !trackedCosmeticShopMachines.Contains(machine)) { trackedCosmeticShopMachines.Add(machine); TrackNotifierForCosmeticShopMachine(machine); RegisterTrackedTokenBoxSource((Component)(object)machine); InvalidateTokenBoxCache(); } } private static void UnregisterTrackedCosmeticShopMachine(CosmeticShopMachine machine) { if ((Object)(object)machine != (Object)null && trackedCosmeticShopMachines.Remove(machine)) { UnregisterTrackedTokenBoxSource((Component)(object)machine); InvalidateTokenBoxCache(); } } private static void ClearTrackedTokenSources() { trackedItems.Clear(); trackedTokenBoxItems.Clear(); trackedCustomDiscoverables.Clear(); trackedCosmeticShopMachines.Clear(); trackedTokenBoxObjectRefCounts.Clear(); trackedTokenBoxObjectCount = 0; Plugin instance = Instance; if ((Object)(object)instance != (Object)null) { instance.itemSearchTextCache.Clear(); instance.itemTokenBoxCandidateCache.Clear(); instance.tokenBoxCountLastUpdate = -1f; } InvalidateTokenBoxCache(); } private static void InvalidateTokenBoxCache() { } private static void RegisterTrackedTokenBoxSource(Component component) { if (TryGetTrackedTokenBoxObjectId(component, requireLiveScene: true, out var objectId)) { trackedTokenBoxObjectRefCounts.TryGetValue(objectId, out var value); trackedTokenBoxObjectRefCounts[objectId] = value + 1; if (value == 0) { trackedTokenBoxObjectCount++; } } } private static void UnregisterTrackedTokenBoxSource(Component component) { if (TryGetTrackedTokenBoxObjectId(component, requireLiveScene: false, out var objectId) && trackedTokenBoxObjectRefCounts.TryGetValue(objectId, out var value)) { if (value <= 1) { trackedTokenBoxObjectRefCounts.Remove(objectId); trackedTokenBoxObjectCount = Math.Max(0, trackedTokenBoxObjectCount - 1); } else { trackedTokenBoxObjectRefCounts[objectId] = value - 1; } } } private static bool TryGetTrackedTokenBoxObjectId(Component component, bool requireLiveScene, out int objectId) { //IL_0041: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) objectId = 0; if ((Object)(object)component == (Object)null || (Object)(object)component.gameObject == (Object)null) { return false; } GameObject gameObject = component.gameObject; Scene scene; if (requireLiveScene) { scene = gameObject.scene; if (!((Scene)(ref scene)).IsValid() || !gameObject.activeInHierarchy) { return false; } } else { scene = gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { return false; } } objectId = ((Object)gameObject).GetInstanceID(); return objectId != 0; } private static void RebuildTrackedTokenBoxCount() { trackedTokenBoxObjectRefCounts.Clear(); trackedTokenBoxObjectCount = 0; foreach (CosmeticShopMachine trackedCosmeticShopMachine in trackedCosmeticShopMachines) { TryRegisterTrackedTokenBoxSourceForRebuild((Component)(object)trackedCosmeticShopMachine); } foreach (ValuableDiscoverCustom trackedCustomDiscoverable in trackedCustomDiscoverables) { TryRegisterTrackedTokenBoxSourceForRebuild((Component)(object)trackedCustomDiscoverable); } foreach (ItemAttributes trackedTokenBoxItem in trackedTokenBoxItems) { TryRegisterTrackedTokenBoxSourceForRebuild((Component)(object)trackedTokenBoxItem); } } private static void TryRegisterTrackedTokenBoxSourceForRebuild(Component component) { if (TryGetTrackedTokenBoxObjectId(component, requireLiveScene: true, out var objectId)) { trackedTokenBoxObjectRefCounts.TryGetValue(objectId, out var value); trackedTokenBoxObjectRefCounts[objectId] = value + 1; if (value == 0) { trackedTokenBoxObjectCount++; } } } private static void TrackNotifierForValuable(ValuableObject valuable) { GetOrAddTrackedObjectNotifier((Component)(object)valuable)?.TrackValuable(valuable); } private static void TrackNotifierForCart(PhysGrabCart cart) { GetOrAddTrackedObjectNotifier((Component)(object)cart)?.TrackCart(cart); } private static void TrackNotifierForVehicle(ItemVehicle vehicle) { GetOrAddTrackedObjectNotifier((Component)(object)vehicle)?.TrackVehicle(vehicle); } private static void TrackNotifierForEnemy(Enemy enemy) { GetOrAddTrackedObjectNotifier((Component)(object)enemy)?.TrackEnemy(enemy); } private static void TrackNotifierForCustomDiscoverable(ValuableDiscoverCustom customDiscoverable) { GetOrAddTrackedObjectNotifier((Component)(object)customDiscoverable)?.TrackCustomDiscoverable(customDiscoverable); } private static void TrackNotifierForCosmeticShopMachine(CosmeticShopMachine machine) { GetOrAddTrackedObjectNotifier((Component)(object)machine)?.TrackCosmeticShopMachine(machine); } private static MoreUiTrackedObjectNotifier GetOrAddTrackedObjectNotifier(Component component) { if ((Object)(object)component == (Object)null || (Object)(object)component.gameObject == (Object)null) { return null; } MoreUiTrackedObjectNotifier component2 = component.GetComponent(); if ((Object)(object)component2 != (Object)null) { return component2; } try { return component.gameObject.AddComponent(); } catch { return null; } } private void ApplyNativeNamePatch() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown try { nativeNameHarmony = new Harmony("zichen.moreui.nativename"); PatchNativeNameMethod(typeof(PlayerNameChecker), "Update", "PlayerNameCheckerUpdatePrefix", prefix: true); PatchNativeNameMethod(typeof(WorldSpaceUIPlayerName), "Update", "WorldSpaceUIPlayerNameUpdatePrefix", prefix: true); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Native teammate name display suppression patched."); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Failed to patch native name display: {arg}"); } } private void PatchNativeNameMethod(Type originalType, string originalName, string patchName, bool prefix) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(originalType, originalName, (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), patchName, (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to find native name patch target: " + originalType?.Name + "." + originalName)); } else if (prefix) { nativeNameHarmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { nativeNameHarmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static bool PlayerNameCheckerUpdatePrefix() { return !ShouldSuppressOfficialTeammateNames(); } private static bool WorldSpaceUIPlayerNameUpdatePrefix(WorldSpaceUIPlayerName __instance) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (!ShouldSuppressOfficialTeammateNames()) { return true; } TextMeshProUGUI text = __instance.text; if ((Object)(object)text == (Object)null) { return false; } Color color = ((Graphic)text).color; color.a = 0f; ((Graphic)text).color = color; ((TMP_Text)text).richText = false; SetWorldSpaceUiShowTimerFast(__instance, 0f); return false; } private static bool ShouldSuppressOfficialTeammateNames() { if (!IsStaticModEnabled() || !IsRunLevelSafe()) { return false; } Plugin instance = Instance; if ((Object)(object)instance != (Object)null && instance.teammateOverlayEnabled != null) { return instance.teammateOverlayEnabled.Value; } return false; } public static bool UseChinese() { Plugin instance = Instance; if ((Object)(object)instance == (Object)null || instance.displayLanguage == null) { return false; } return instance.displayLanguage.Value == DisplayLanguage.中文; } private static DisplayLanguage DetectDefaultLanguage() { try { foreach (KeyValuePair pluginInfo in Chainloader.PluginInfos) { string text = pluginInfo.Key ?? string.Empty; string text2 = ((pluginInfo.Value == null || pluginInfo.Value.Metadata == null) ? string.Empty : (pluginInfo.Value.Metadata.Name ?? string.Empty)); for (int i = 0; i < _chineseModKeywords.Length; i++) { string value = _chineseModKeywords[i]; if ((!string.IsNullOrEmpty(text) && text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) || (!string.IsNullOrEmpty(text2) && text2.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)) { return DisplayLanguage.中文; } } for (int j = 0; j < _chineseEnvironmentPluginGuids.Length; j++) { if (string.Equals(text, _chineseEnvironmentPluginGuids[j], StringComparison.OrdinalIgnoreCase)) { return DisplayLanguage.中文; } } } } catch { } return DisplayLanguage.English; } private ConfigEntry BindI18N(string sectEN, string sectCN, string keyEN, string keyCN, string descEN, string descCN, T defaultVal, AcceptableValueBase acceptableValues = null, int? order = null, Action customDrawer = null, string displayEN = null) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes(); if (order.HasValue) { configurationManagerAttributes.Order = order.Value; } if (customDrawer != null) { configurationManagerAttributes.CustomDrawer = customDrawer; } CfgI18N cfgI18N = NewI18N(sectEN, sectCN, keyEN, keyCN, descEN, descCN, configurationManagerAttributes, readOnly: false); cfgI18N.DisplayEN = displayEN; ApplyI18N(cfgI18N); return (ConfigEntry)(object)(cfgI18N.Entry = (ConfigEntryBase)(object)((BaseUnityPlugin)this).Config.Bind(sectEN, keyEN, defaultVal, new ConfigDescription(descEN, acceptableValues, new object[1] { configurationManagerAttributes }))); } private void BindReadOnlyI18N(string sectEN, string sectCN, string keyEN, string keyCN, string valueEN, string valueCN, int? order = null, Action customDrawer = null, string displayEN = null) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes { ReadOnly = true }; if (order.HasValue) { configurationManagerAttributes.Order = order.Value; } if (customDrawer != null) { configurationManagerAttributes.CustomDrawer = customDrawer; } CfgI18N cfgI18N = NewI18N(sectEN, sectCN, keyEN, keyCN, string.Empty, string.Empty, configurationManagerAttributes, readOnly: true); cfgI18N.ValueEN = valueEN; cfgI18N.ValueCN = valueCN; cfgI18N.DisplayEN = displayEN; ApplyI18N(cfgI18N); cfgI18N.ReadOnlyEntry = ((BaseUnityPlugin)this).Config.Bind(sectEN, keyEN, UseChinese() ? valueCN : valueEN, new ConfigDescription(string.Empty, (AcceptableValueBase)null, new object[1] { configurationManagerAttributes })); cfgI18N.Entry = (ConfigEntryBase)(object)cfgI18N.ReadOnlyEntry; string text = (UseChinese() ? valueCN : valueEN); if (cfgI18N.ReadOnlyEntry.Value != text) { cfgI18N.ReadOnlyEntry.Value = text; } } private static CfgI18N NewI18N(string sectEN, string sectCN, string keyEN, string keyCN, string descEN, string descCN, ConfigurationManagerAttributes attrs, bool readOnly) { CfgI18N cfgI18N = new CfgI18N { SectionEN = sectEN, SectionCN = sectCN, KeyEN = keyEN, KeyCN = keyCN, DescEN = descEN, DescCN = descCN, Attrs = attrs }; ApplyI18N(cfgI18N); _cfgI18Ns.Add(cfgI18N); _cfgByEnSection[sectEN] = cfgI18N; _cfgByEnKey[sectEN + "\0" + keyEN] = cfgI18N; if (!_cfgByKeyOnly.TryGetValue(keyEN, out var value)) { value = new List(2); _cfgByKeyOnly[keyEN] = value; } value.Add(cfgI18N); string text = FixNamingForLookup(keyEN); if (!string.Equals(text, keyEN, StringComparison.Ordinal)) { if (!_cfgByKeyOnly.TryGetValue(text, out var value2)) { value2 = new List(2); _cfgByKeyOnly[text] = value2; } if (!value2.Contains(cfgI18N)) { value2.Add(cfgI18N); } } return cfgI18N; } private static void ApplyI18N(CfgI18N i18n) { if (i18n == null || i18n.Attrs == null) { return; } bool flag = UseChinese(); i18n.Attrs.Category = (flag ? i18n.SectionCN : i18n.SectionEN); i18n.Attrs.DispName = (flag ? i18n.KeyCN : (i18n.DisplayEN ?? i18n.KeyEN)); i18n.Attrs.Description = (flag ? i18n.DescCN : i18n.DescEN); if (i18n.ReadOnlyEntry != null) { string text = (flag ? i18n.ValueCN : i18n.ValueEN); if (i18n.ReadOnlyEntry.Value != text) { i18n.ReadOnlyEntry.Value = text; } } } private static void RefreshAllI18N() { for (int i = 0; i < _cfgI18Ns.Count; i++) { ApplyI18N(_cfgI18Ns[i]); } RefreshLiveLabels(); } private static string FixNamingForLookup(string input) { if (string.IsNullOrEmpty(input)) { return input; } input = Regex.Replace(input, "([a-z])([A-Z])", "$1 $2"); input = Regex.Replace(input, "([A-Z])([A-Z][a-z])", "$1 $2"); input = Regex.Replace(input, "\\s+", " "); input = Regex.Replace(input, "([A-Z]\\.)\\s([A-Z]\\.)", "$1$2"); return input.Trim(); } internal static void TryHookREPOConfig(Harmony h) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_018a: Expected O, but got Unknown try { Type type = AccessTools.TypeByName("MenuLib.MenuAPI"); if (type == null) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogInfo((object)"MenuLib not detected, skip REPOConfig bilingual hook."); } return; } HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(REPOConfigCreateHook), "Postfix", (Type[])null, (Type[])null)); HashSet hashSet = new HashSet(StringComparer.Ordinal) { "CreateREPOLabel", "CreateREPOToggle", "CreateREPOSlider", "CreateREPOInputField", "CreateREPOButton" }; int num = 0; foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type)) { if (!hashSet.Contains(declaredMethod.Name)) { continue; } ParameterInfo[] parameters = declaredMethod.GetParameters(); if (parameters.Length != 0 && !(parameters[0].ParameterType != typeof(string))) { try { h.Patch((MethodBase)declaredMethod, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } catch { } } } try { Type type2 = AccessTools.TypeByName("REPOConfig.ConfigMenu"); if (type2 != null) { MethodInfo methodInfo = AccessTools.Method(type2, "CreateModEntries", (Type[])null, (Type[])null); if (methodInfo != null) { h.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(REPOConfigCreateHook), "CreateModEntriesPrefix", (Type[])null, (Type[])null)), new HarmonyMethod(AccessTools.Method(typeof(REPOConfigCreateHook), "CreateModEntriesPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _createModEntriesPatchInstalled = true; } } } catch { } if (num > 0) { Plugin instance2 = Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogInfo((object)$"REPOConfig bilingual hook attached ({num} UI creation methods)."); } } else { Plugin instance3 = Instance; if (instance3 != null) { ((BaseUnityPlugin)instance3).Logger.LogInfo((object)"REPOConfig: no patchable UI creation methods found."); } } } catch (Exception ex) { Plugin instance4 = Instance; if (instance4 != null) { ((BaseUnityPlugin)instance4).Logger.LogInfo((object)("REPOConfig hook failed: " + ex.Message)); } } } internal static void RegisterLiveLabelIfMatched(string label, object uiElement) { if (string.IsNullOrEmpty(label) || uiElement == null) { return; } if (_cfgByEnSection.TryGetValue(label, out var value)) { RegisterOneLiveLabel(uiElement, value, isSection: true); } else { if (!_cfgByKeyOnly.TryGetValue(label, out var value2) || value2 == null || value2.Count == 0) { return; } if (value2.Count == 1) { RegisterOneLiveLabel(uiElement, value2[0], isSection: false); return; } if (!_pendingKeyMatchIndex.TryGetValue(label, out var value3)) { value3 = 0; } if (value3 >= value2.Count) { value3 = 0; } RegisterOneLiveLabel(uiElement, value2[value3], isSection: false); _pendingKeyMatchIndex[label] = value3 + 1; } } private static void RegisterOneLiveLabel(object uiElement, CfgI18N i18n, bool isSection) { if (!IsOwnEntry(i18n) || !IsRenderingOurMod()) { return; } TextMeshProUGUI labelTmp = GetLabelTmp(uiElement); if ((Object)(object)labelTmp == (Object)null) { return; } bool flag = UseChinese(); string text = ((!isSection) ? (flag ? i18n.KeyCN : (i18n.DisplayEN ?? i18n.KeyEN)) : (flag ? i18n.SectionCN : i18n.SectionEN)); if (!string.IsNullOrEmpty(text)) { try { ((TMP_Text)labelTmp).text = text; } catch { } } _liveLabels.Add(new LiveLabel { Tmp = new WeakReference(labelTmp), I18N = i18n, IsSection = isSection }); if (!isSection && i18n.ReadOnlyEntry != null) { Object val = (Object)((uiElement is Object) ? uiElement : null); if (val != null && AccessTools.Field(uiElement.GetType(), "inputStringSystem") != null) { _liveValues.Add(new LiveValue { InputField = new WeakReference(val), I18N = i18n }); TrySetInputFieldValue(val, flag ? i18n.ValueCN : i18n.ValueEN); } } if (!isSection) { Type type = uiElement.GetType(); if (!_toggleLeftTmpCache.TryGetValue(type, out var value)) { value = AccessTools.Field(type, "leftButtonTMP"); _toggleLeftTmpCache[type] = value; } if (!_toggleRightTmpCache.TryGetValue(type, out var value2)) { value2 = AccessTools.Field(type, "rightButtonTMP"); _toggleRightTmpCache[type] = value2; } if (value != null && value2 != null) { object? value3 = value.GetValue(uiElement); TextMeshProUGUI val2 = (TextMeshProUGUI)((value3 is TextMeshProUGUI) ? value3 : null); object? value4 = value2.GetValue(uiElement); TextMeshProUGUI val3 = (TextMeshProUGUI)((value4 is TextMeshProUGUI) ? value4 : null); if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null) { _liveToggleButtons.Add(new LiveToggleButtons { LeftTmp = new WeakReference(val2), RightTmp = new WeakReference(val3) }); ApplyToggleButtonText(val2, val3, flag); } } } if (isSection || i18n.Entry == null || !i18n.Entry.SettingType.IsSubclassOf(typeof(Enum))) { return; } Object val4 = (Object)((uiElement is Object) ? uiElement : null); if (val4 != null) { Type type2 = uiElement.GetType(); if (!_sliderStringOptionsPropCache.TryGetValue(type2, out var value5)) { value5 = AccessTools.Property(type2, "stringOptions"); _sliderStringOptionsPropCache[type2] = value5; } if (value5 != null) { string[] names = Enum.GetNames(i18n.Entry.SettingType); string[] array = BuildEnumOptionsCN(names); string[] array2 = BuildEnumOptionsEN(names); LiveSliderOptions item = new LiveSliderOptions { Slider = new WeakReference(val4), I18N = i18n, OptionsCN = array, OptionsEN = array2 }; _liveSliderOptions.Add(item); TrySetSliderOptions(val4, value5, flag ? array : array2); } } } private static bool IsOwnEntry(CfgI18N i18n) { if (i18n == null) { return false; } if (i18n.Entry == null) { return false; } Plugin instance = Instance; if ((Object)(object)instance == (Object)null) { return false; } return i18n.Entry.ConfigFile == ((BaseUnityPlugin)instance).Config; } private static bool IsRenderingOurMod() { if (!_createModEntriesPatchInstalled) { return true; } if (_currentRenderingConfigFilePath == null) { return false; } Plugin instance = Instance; if ((Object)(object)instance == (Object)null) { return false; } return string.Equals(_currentRenderingConfigFilePath, ((BaseUnityPlugin)instance).Config.ConfigFilePath, StringComparison.OrdinalIgnoreCase); } private static TextMeshProUGUI GetLabelTmp(object uiElement) { try { Type type = uiElement.GetType(); if (!_labelTmpFieldCache.TryGetValue(type, out var value)) { value = AccessTools.Field(type, "labelTMP"); _labelTmpFieldCache[type] = value; } return (TextMeshProUGUI)((value == null) ? null : /*isinst with value type is only supported in some contexts*/); } catch { return null; } } internal static void RefreshLiveLabels() { bool flag = UseChinese(); for (int num = _liveLabels.Count - 1; num >= 0; num--) { LiveLabel liveLabel = _liveLabels[num]; if (!liveLabel.Tmp.TryGetTarget(out var target) || (Object)(object)target == (Object)null || (Object)(object)((Component)target).gameObject == (Object)null) { _liveLabels.RemoveAt(num); } else { string text = ((!liveLabel.IsSection) ? (flag ? liveLabel.I18N.KeyCN : (liveLabel.I18N.DisplayEN ?? liveLabel.I18N.KeyEN)) : (flag ? liveLabel.I18N.SectionCN : liveLabel.I18N.SectionEN)); try { ((TMP_Text)target).text = text; } catch { _liveLabels.RemoveAt(num); } } } for (int num2 = _liveValues.Count - 1; num2 >= 0; num2--) { LiveValue liveValue = _liveValues[num2]; if (!liveValue.InputField.TryGetTarget(out var target2) || target2 == (Object)null) { _liveValues.RemoveAt(num2); } else { string newVal = (flag ? liveValue.I18N.ValueCN : liveValue.I18N.ValueEN); if (!TrySetInputFieldValue(target2, newVal)) { _liveValues.RemoveAt(num2); } } } for (int num3 = _liveSliderOptions.Count - 1; num3 >= 0; num3--) { LiveSliderOptions liveSliderOptions = _liveSliderOptions[num3]; if (!liveSliderOptions.Slider.TryGetTarget(out var target3) || target3 == (Object)null) { _liveSliderOptions.RemoveAt(num3); } else { Type type = ((object)target3).GetType(); if (!_sliderStringOptionsPropCache.TryGetValue(type, out var value) || value == null) { _liveSliderOptions.RemoveAt(num3); } else { TrySetSliderOptions(target3, value, flag ? liveSliderOptions.OptionsCN : liveSliderOptions.OptionsEN); } } } for (int num4 = _liveToggleButtons.Count - 1; num4 >= 0; num4--) { LiveToggleButtons liveToggleButtons = _liveToggleButtons[num4]; if (!liveToggleButtons.LeftTmp.TryGetTarget(out var target4) || (Object)(object)target4 == (Object)null || !liveToggleButtons.RightTmp.TryGetTarget(out var target5) || (Object)(object)target5 == (Object)null) { _liveToggleButtons.RemoveAt(num4); } else { ApplyToggleButtonText(target4, target5, flag); } } _pendingKeyMatchIndex.Clear(); } private static string[] BuildEnumOptionsCN(string[] enumNames) { string[] array = new string[enumNames.Length]; for (int i = 0; i < enumNames.Length; i++) { array[i] = (_enumNameENtoCN.TryGetValue(enumNames[i], out var value) ? value : enumNames[i]); } return array; } private static string[] BuildEnumOptionsEN(string[] enumNames) { string[] array = new string[enumNames.Length]; for (int i = 0; i < enumNames.Length; i++) { array[i] = (_enumNameCNtoEN.TryGetValue(enumNames[i], out var value) ? value : enumNames[i]); } return array; } private static void TrySetSliderOptions(Object sliderObj, PropertyInfo prop, string[] options) { try { prop.SetValue(sliderObj, options); } catch { } } private static void ApplyToggleButtonText(TextMeshProUGUI leftTmp, TextMeshProUGUI rightTmp, bool cn) { try { ((TMP_Text)leftTmp).text = (cn ? "开" : "ON"); ((TMP_Text)rightTmp).text = (cn ? "关" : "OFF"); } catch { } } private static bool TrySetInputFieldValue(Object ifObj, string newVal) { try { Type type = ((object)ifObj).GetType(); if (!_inputStringSystemFieldCache.TryGetValue(type, out var value)) { value = AccessTools.Field(type, "inputStringSystem"); _inputStringSystemFieldCache[type] = value; } if (value == null) { return false; } object value2 = value.GetValue(ifObj); if (value2 == null) { return false; } Type type2 = value2.GetType(); if (!_inputStringSystemSetValueCache.TryGetValue(type2, out var value3)) { value3 = AccessTools.Method(type2, "SetValue", new Type[2] { typeof(string), typeof(bool) }, (Type[])null); _inputStringSystemSetValueCache[type2] = value3; } if (value3 == null) { return false; } value3.Invoke(value2, new object[2] { newVal ?? string.Empty, false }); return true; } catch { return false; } } private string BuildOverlayText() { DisplayLanguage currentLanguage = CurrentLanguage; bool flag = showEnemySection == null || showEnemySection.Value; bool flag2 = showValueSection == null || showValueSection.Value; bool num = showTeammateInfoSection == null || showTeammateInfoSection.Value; bool flag3 = flag && showBreakdown.Value; bool flag4 = flag && showTotalEnemyCount.Value; bool flag5 = flag3 || flag4; bool flag6 = num && ((showDeadTeammates != null && showDeadTeammates.Value) || (showAliveTeammates != null && showAliveTeammates.Value)); bool flag7 = num && showPlayerCounts.Value; bool flag8 = flag2 && ((showSmallCartCount != null && showSmallCartCount.Value) || (showLargeCartCount != null && showLargeCartCount.Value)); bool flag9 = flag2 && ((showKartCount != null && showKartCount.Value) || (showCargoCount != null && showCargoCount.Value)); bool flag10 = flag2 && showCurrentRunSubmittedFunds.Value; bool flag11 = flag2 && showShopRemainingFunds.Value; activeEnemyBuffer.Clear(); if (flag5) { List enemyObjectsCachedForFrame = GetEnemyObjectsCachedForFrame(); if (enemyObjectsCachedForFrame != null) { foreach (Enemy item in enemyObjectsCachedForFrame) { if (IsEnemyCountable(item)) { activeEnemyBuffer.Add(item); } } } } List teammateInfos = (flag6 ? CreateTeammateDistanceInfos() : teammateDistanceBuffer); enemyBreakdownBuffer.Clear(); enemyBreakdownRankBuffer.Clear(); orderedEnemyBreakdownBuffer.Clear(); if (flag3) { foreach (Enemy item2 in activeEnemyBuffer) { string cachedEnemyDisplayName = GetCachedEnemyDisplayName(item2); if (!string.IsNullOrWhiteSpace(cachedEnemyDisplayName)) { enemyBreakdownBuffer.TryGetValue(cachedEnemyDisplayName, out var value); enemyBreakdownBuffer[cachedEnemyDisplayName] = value + 1; int enemyBreakdownRank = GetEnemyBreakdownRank(item2); if (!enemyBreakdownRankBuffer.TryGetValue(cachedEnemyDisplayName, out var value2) || enemyBreakdownRank < value2) { enemyBreakdownRankBuffer[cachedEnemyDisplayName] = enemyBreakdownRank; } } } foreach (KeyValuePair item3 in enemyBreakdownBuffer) { orderedEnemyBreakdownBuffer.Add(item3); } orderedEnemyBreakdownBuffer.Sort(CompareEnemyBreakdownEntry); } int num2 = 0; string text = string.Empty; if (flag2 && showTokenBoxCount != null && showTokenBoxCount.Value) { num2 = GetTokenBoxCountCachedForFrame(); text = $"{HudText.TokenBoxCount(currentLanguage)}: {num2}"; } string text2 = string.Empty; string text3 = string.Empty; if (flag8) { CountCarts(out var largeCount, out var smallCount); if (showSmallCartCount != null && showSmallCartCount.Value) { text2 = ((currentLanguage == DisplayLanguage.English) ? $"Small Cart: {smallCount}" : $"小购物车: {smallCount}"); } if (showLargeCartCount != null && showLargeCartCount.Value) { text3 = ((currentLanguage == DisplayLanguage.English) ? $"Cart: {largeCount}" : $"大购物车: {largeCount}"); } } string text4 = string.Empty; string text5 = string.Empty; if (flag9) { CountVehicles(out var kartCount, out var cargoCount); if (showKartCount != null && showKartCount.Value) { text4 = ((currentLanguage == DisplayLanguage.English) ? $"Kart: {kartCount}" : $"赛车: {kartCount}"); } if (showCargoCount != null && showCargoCount.Value) { text5 = ((currentLanguage == DisplayLanguage.English) ? $"Cargo: {cargoCount}" : $"载货车: {cargoCount}"); } } string line = (flag4 ? $"{HudText.EnemyTotal(currentLanguage)}: {activeEnemyBuffer.Count}" : string.Empty); string text6 = string.Empty; string text7 = string.Empty; string text8 = string.Empty; string text9 = string.Empty; float mapValue = 0f; float initialMapValue = 0f; List valuables = null; int num3; if (flag2) { if (!showMapLostValue.Value && !showExplorationProgress.Value) { num3 = (showMapTotalValue.Value ? 1 : 0); if (num3 == 0) { goto IL_04e3; } } else { num3 = 1; } valuables = GetValuableObjectsCachedForFrame(); } else { num3 = 0; } goto IL_04e3; IL_04e3: int levelNumber = SemiFunc.RunGetLevelsCompleted() + 1; bool flag12 = num3 != 0 && ZichenMapValueService.TryGetValues(valuables, levelNumber, out mapValue, out initialMapValue); float value3 = 0f; int num4 = 0; float unexploredValue = 0f; bool hasLiveValuableData = false; if (flag2 && flag12) { bool value4 = showMapLostValue.Value; bool value5 = showExplorationProgress.Value; bool value6 = showMapTotalValue.Value; float num5 = mapValue; if (value4 || value5 || value6) { FillCurrentDollarHaulObjects(currentDollarHaulObjectsBuffer); FillReferenceSet(currentDollarHaulObjectsBuffer, haulReferenceSetBuffer); if (value6) { num5 = CalculateRemainingMapValue(mapValue, valuables, haulReferenceSetBuffer); } if (value4) { value3 = UpdateAndGetLostMapValue(valuables, haulReferenceSetBuffer); } if (value5) { FillCurrentCartObjects(currentCartObjectsBuffer); FillReferenceSet(currentCartObjectsBuffer, cartReferenceSetBuffer); num4 = CalculateExplorationProgress(mapValue, initialMapValue, valuables, haulReferenceSetBuffer, cartReferenceSetBuffer, out unexploredValue, out hasLiveValuableData); } } text6 = (showMapLostValue.Value ? (HudText.MapLostValue(currentLanguage) + ": " + FormatMoney(value3)) : string.Empty); text7 = (showExplorationProgress.Value ? BuildExplorationProgressLine(currentLanguage, num4) : string.Empty); text8 = (showExplorationProgress.Value ? BuildUnextractedFundsLine(currentLanguage, CalculateUnextractedFunds(initialMapValue, num4, unexploredValue, hasLiveValuableData)) : string.Empty); mapValue = num5; text9 = (showMapTotalValue.Value ? BuildMapValueLine(currentLanguage, mapValue) : string.Empty); } else if (flag2 && (showMapLostValue.Value || showExplorationProgress.Value || showMapTotalValue.Value)) { text7 = (showExplorationProgress.Value ? BuildExplorationProgressLine(currentLanguage, 0) : string.Empty); text8 = (showExplorationProgress.Value ? BuildUnextractedFundsLine(currentLanguage, 0f) : string.Empty); text6 = (showMapLostValue.Value ? (HudText.MapLostValue(currentLanguage) + ": " + FormatMoney(0f)) : string.Empty); text9 = (showMapTotalValue.Value ? BuildMapValueLine(currentLanguage, 0f) : string.Empty); } float value7 = (flag11 ? GetShopRemainingFundsSnapshot() : 0f); float value8 = (flag10 ? GetCurrentLevelSubmittedValue() : 0f); string text10 = ((flag2 && showLevelInfo.Value) ? BuildLevelLine() : string.Empty); StringBuilder stringBuilder = reusableOverlayTextBuilder; stringBuilder.Clear(); bool hasWrittenAnySection = false; bool sectionStarted = false; if (flag3) { foreach (KeyValuePair item4 in orderedEnemyBreakdownBuffer) { BeginOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted); stringBuilder.Append(item4.Key); stringBuilder.Append(": "); stringBuilder.Append(item4.Value); } } if (flag4) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted, line); } bool sectionStarted2 = false; if (!string.IsNullOrWhiteSpace(text2)) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, text2); } if (!string.IsNullOrWhiteSpace(text3)) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, text3); } if (!string.IsNullOrWhiteSpace(text4)) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, text4); } if (!string.IsNullOrWhiteSpace(text5)) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, text5); } if (!string.IsNullOrWhiteSpace(text)) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, text); } if (!string.IsNullOrWhiteSpace(text7)) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, text7); } if (!string.IsNullOrWhiteSpace(text8)) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, text8); } if (!string.IsNullOrWhiteSpace(text9)) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, text9); } if (!string.IsNullOrWhiteSpace(text6)) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, text6); } if (flag10) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, HudText.CurrentRunEvacuatedFunds(currentLanguage) + ": " + FormatMoney(value8)); } if (flag11) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, HudText.WarehouseFunds(currentLanguage) + ": " + FormatMoney(value7)); } if (!string.IsNullOrWhiteSpace(text10)) { AppendOverlaySectionLine(stringBuilder, ref hasWrittenAnySection, ref sectionStarted2, text10); } if (flag6 || flag7) { bool sectionStarted3 = false; BuildRightBottomTeammateInfoSection(stringBuilder, teammateInfos, ref hasWrittenAnySection, ref sectionStarted3); } return stringBuilder.ToString(); } private int CompareEnemyBreakdownEntry(KeyValuePair left, KeyValuePair right) { int value; int num = (enemyBreakdownRankBuffer.TryGetValue(left.Key, out value) ? value : int.MaxValue); int value2; int value3 = (enemyBreakdownRankBuffer.TryGetValue(right.Key, out value2) ? value2 : int.MaxValue); int num2 = num.CompareTo(value3); if (num2 != 0) { return num2; } return string.Compare(left.Key, right.Key, StringComparison.Ordinal); } private void BuildRightBottomTeammateInfoSection(StringBuilder builder, List teammateInfos, ref bool hasWrittenAnySection, ref bool sectionStarted) { if (showDeadTeammates.Value) { AppendTeammateDistanceLines(teammateInfos, deadOnly: true, builder, ref hasWrittenAnySection, ref sectionStarted); } if (showAliveTeammates.Value) { AppendTeammateDistanceLines(teammateInfos, deadOnly: false, builder, ref hasWrittenAnySection, ref sectionStarted); } if (showPlayerCounts.Value) { AppendOverlaySectionLine(builder, ref hasWrittenAnySection, ref sectionStarted, BuildPlayerCountLine()); } } private void UpdateCartDistanceCache() { if (!ShouldDrawCartWorldLabels()) { if (cartDistanceCacheValid || cartDistanceCache.Count > 0 || cartRefreshTimer > 0f) { ClearCartDistanceCache(); } return; } cartRefreshTimer += Time.deltaTime; if (!cartDistanceCacheValid || !(cartRefreshTimer < 0.15f)) { cartRefreshTimer = 0f; cartDistanceCache.Clear(); FillCartDistanceInfos(cartDistanceCache); cartDistanceCacheValid = true; } } private void ClearCartDistanceCache() { cartRefreshTimer = 0f; cartDistanceCacheValid = false; cartDistanceCache.Clear(); } private void UpdateVehicleDistanceCache() { if (!ShouldDrawVehicleWorldLabels()) { if (vehicleDistanceCacheValid || vehicleDistanceCache.Count > 0 || vehicleRefreshTimer > 0f) { ClearVehicleDistanceCache(); } return; } if (CleanupDestroyedObjectsIfNeeded(trackedVehicles, ref nextTrackedVehicleCleanupAt, force: false)) { vehicleLabelIndices.Clear(); nextVehicleLabelIndex = 1; vehicleDistanceCacheValid = false; } vehicleRefreshTimer += Time.deltaTime; if (!vehicleDistanceCacheValid || !(vehicleRefreshTimer < 0.15f)) { vehicleRefreshTimer = 0f; vehicleDistanceCache.Clear(); FillVehicleDistanceInfos(vehicleDistanceCache); vehicleDistanceCacheValid = true; } } private void ClearVehicleDistanceCache() { vehicleRefreshTimer = 0f; vehicleDistanceCacheValid = false; vehicleDistanceCache.Clear(); } private List GetEnemyObjectsCachedForFrame() { int frameCount = Time.frameCount; if (enemyObjectsFrameCacheFrame == frameCount) { return trackedEnemies; } enemyObjectsFrameCacheFrame = frameCount; if (CleanupDestroyedObjectsIfNeeded(trackedEnemies, ref nextTrackedEnemyCleanupAt, force: false)) { RebuildTrackedEnemySet(); TrimTrackedEnemyCaches(); } return trackedEnemies; } private int GetTokenBoxCountCachedForFrame() { float time = Time.time; if (tokenBoxCountLastUpdate >= 0f && time - tokenBoxCountLastUpdate < 1f) { return trackedTokenBoxObjectCount; } tokenBoxCountLastUpdate = time; if (CleanupDestroyedObjectsIfNeeded(trackedCosmeticShopMachines, ref nextTrackedCosmeticShopMachineCleanupAt, force: false) | CleanupDestroyedObjectsIfNeeded(trackedCustomDiscoverables, ref nextTrackedCustomDiscoverableCleanupAt, force: false) | CleanupDestroyedObjectsIfNeeded(trackedTokenBoxItems, ref nextTrackedTokenItemCleanupAt, force: false)) { RebuildTrackedTokenBoxCount(); } return trackedTokenBoxObjectCount; } private bool IsTokenBoxItemCached(ItemAttributes item) { if ((Object)(object)item == (Object)null) { return false; } int instanceID = ((Object)item).GetInstanceID(); if (itemTokenBoxCandidateCache.TryGetValue(instanceID, out var value)) { return value; } bool flag = (Object)(object)((Component)item).GetComponent() == (Object)null && MatchesTokenBoxKeywords(GetCachedItemAttribSearchText(item)); itemTokenBoxCandidateCache[instanceID] = flag; return flag; } private string GetCachedItemAttribSearchText(ItemAttributes item) { if ((Object)(object)item == (Object)null) { return string.Empty; } int instanceID = ((Object)item).GetInstanceID(); if (itemSearchTextCache.TryGetValue(instanceID, out var value)) { return value; } string text = BuildItemAttribSearchText(item); itemSearchTextCache[instanceID] = text; return text; } private string BuildItemAttribSearchText(ItemAttributes item) { if ((Object)(object)item == (Object)null) { return string.Empty; } reusableItemSearchTextBuilder.Clear(); AppendSearchTextPart(reusableItemSearchTextBuilder, GetItemAttribTypeNameFast(item)); AppendSearchTextPart(reusableItemSearchTextBuilder, GetItemAttribTagFast(item)); AppendSearchTextPart(reusableItemSearchTextBuilder, GetItemAttribAssetNameFast(item)); AppendSearchTextPart(reusableItemSearchTextBuilder, GetItemAttribPromptNameFast(item)); AppendSearchTextPart(reusableItemSearchTextBuilder, GetItemAttribNameFast(item)); AppendSearchTextPart(reusableItemSearchTextBuilder, GetItemAttribInstanceNameFast(item)); AppendSearchTextPart(reusableItemSearchTextBuilder, ((Object)(object)((Component)item).gameObject == (Object)null) ? null : ((Object)((Component)item).gameObject).name); return reusableItemSearchTextBuilder.ToString(); } private static void AppendSearchTextPart(StringBuilder builder, object value) { if (builder == null || value == null) { return; } string text = (value as string) ?? value.ToString(); if (string.IsNullOrWhiteSpace(text)) { return; } string text2 = text.Trim(); if (text2.Length != 0) { if (builder.Length > 0) { builder.Append(' '); } for (int i = 0; i < text2.Length; i++) { builder.Append(char.ToLowerInvariant(text2[i])); } } } private static bool MatchesTokenBoxKeywords(string combined) { if (string.IsNullOrWhiteSpace(combined)) { return false; } bool num = combined.Contains("token") || combined.Contains("coin") || combined.Contains("prize") || combined.Contains("reward") || combined.Contains("lottery") || combined.Contains("gacha") || combined.Contains("capsule") || combined.Contains("loot"); bool flag = combined.Contains("chest") || combined.Contains("crate") || combined.Contains("box") || combined.Contains("case") || combined.Contains("cache") || combined.Contains("machine") || combined.Contains("dispenser") || combined.Contains("vendor") || combined.Contains("shop"); return num && flag; } private void CountCarts(out int largeCount, out int smallCount) { largeCount = 0; smallCount = 0; List cartObjectsCachedForFrame = GetCartObjectsCachedForFrame(); if (cartObjectsCachedForFrame == null || cartObjectsCachedForFrame.Count == 0) { return; } foreach (PhysGrabCart item in cartObjectsCachedForFrame) { if (!((Object)(object)item == (Object)null) && IsCartCountable(item)) { if (IsSmallCartObject(item)) { smallCount++; } else { largeCount++; } } } } private void CountVehicles(out int kartCount, out int cargoCount) { kartCount = 0; cargoCount = 0; foreach (ItemVehicle trackedVehicle in trackedVehicles) { if (!((Object)(object)trackedVehicle == (Object)null) && !((Object)(object)((Component)trackedVehicle).gameObject == (Object)null) && ((Component)trackedVehicle).gameObject.activeInHierarchy) { if (GetVehicleIsRacingFast(trackedVehicle)) { kartCount++; } else { cargoCount++; } } } } private List GetCartObjectsCachedForFrame() { int frameCount = Time.frameCount; if (cartObjectsFrameCacheFrame == frameCount) { return trackedCarts; } cartObjectsFrameCacheFrame = frameCount; if (CleanupDestroyedObjectsIfNeeded(trackedCarts, ref nextTrackedCartCleanupAt, force: false)) { RebuildTrackedCartSet(); } return trackedCarts; } private List GetGrabberObjectsCachedForFrame() { int frameCount = Time.frameCount; if (grabberObjectsFrameCacheFrame == frameCount) { return trackedGrabbers; } grabberObjectsFrameCacheFrame = frameCount; CleanupDestroyedObjectsIfNeeded(trackedGrabbers, ref nextTrackedGrabberCleanupAt, force: false); return trackedGrabbers; } private List GetValuableObjectsCachedForFrame() { int frameCount = Time.frameCount; if (valuableObjectsFrameCacheFrame == frameCount) { return trackedValuables; } valuableObjectsFrameCacheFrame = frameCount; if (CleanupDestroyedObjectsIfNeeded(trackedValuables, ref nextTrackedValuableCleanupAt, force: false)) { RebuildTrackedValuableSet(); } return trackedValuables; } private static List GetValuableObjectsCachedForFrameStatic() { CleanupDestroyedObjectsIfNeeded(trackedValuables, ref nextTrackedValuableCleanupAt, force: true); return trackedValuables; } private static void ResetTrackedObjectCleanupSchedule() { nextTrackedValuableCleanupAt = 0f; nextTrackedCartCleanupAt = 0f; nextTrackedEnemyCleanupAt = 0f; nextTrackedGrabberCleanupAt = 0f; nextTrackedTokenItemCleanupAt = 0f; nextTrackedCustomDiscoverableCleanupAt = 0f; nextTrackedCosmeticShopMachineCleanupAt = 0f; } private static bool CleanupDestroyedObjectsIfNeeded(List objects, ref float nextCleanupAt, bool force = false) where T : Object { if (objects == null) { return false; } float unscaledTime = Time.unscaledTime; if (!force && unscaledTime < nextCleanupAt) { return false; } nextCleanupAt = unscaledTime + 0.5f; return RemoveDestroyedObjects(objects); } private static bool RemoveDestroyedObjects(List objects) where T : Object { if (objects == null) { return false; } bool result = false; for (int num = objects.Count - 1; num >= 0; num--) { if ((Object)(object)objects[num] == (Object)null) { objects.RemoveAt(num); result = true; } } return result; } private static void RebuildTrackedEnemySet() { trackedEnemySet.Clear(); foreach (Enemy trackedEnemy in trackedEnemies) { if ((Object)(object)trackedEnemy != (Object)null) { trackedEnemySet.Add(trackedEnemy); } } } private static void TrimTrackedEnemyCaches() { Plugin instance = Instance; if ((Object)(object)instance == (Object)null) { return; } TrackedEnemyKeyBuffer.Clear(); foreach (Enemy trackedEnemy in trackedEnemies) { if ((Object)(object)trackedEnemy != (Object)null) { TrackedEnemyKeyBuffer.Add(((Object)trackedEnemy).GetInstanceID()); } } RemoveMissingEnemyCacheEntries(instance.enemyDisplayNameCache); RemoveMissingEnemyCacheEntries(instance.enemyBreakdownRankCache); TrackedEnemyKeyBuffer.Clear(); } private static void RemoveMissingEnemyCacheEntries(Dictionary cache) { if (cache == null || cache.Count == 0) { return; } List list = null; foreach (KeyValuePair item in cache) { if (!TrackedEnemyKeyBuffer.Contains(item.Key)) { if (list == null) { list = new List(); } list.Add(item.Key); } } if (list == null) { return; } foreach (int item2 in list) { cache.Remove(item2); } } private static void RebuildTrackedValuableSet() { trackedValuableSet.Clear(); foreach (ValuableObject trackedValuable in trackedValuables) { if ((Object)(object)trackedValuable != (Object)null) { trackedValuableSet.Add(trackedValuable); } } } private static void RebuildTrackedCartSet() { trackedCartSet.Clear(); foreach (PhysGrabCart trackedCart in trackedCarts) { if ((Object)(object)trackedCart != (Object)null) { trackedCartSet.Add(trackedCart); } } } private static bool IsLiveSceneComponent(Component component) { //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)component != (Object)null && (Object)(object)component.gameObject != (Object)null && component.gameObject.activeInHierarchy) { Scene scene = component.gameObject.scene; return ((Scene)(ref scene)).IsValid(); } return false; } private List GetPlayerObjectsCachedForFrame() { int frameCount = Time.frameCount; if (playerObjectsFrameCacheFrame == frameCount) { return playerObjectsFrameCache; } playerObjectsFrameCacheFrame = frameCount; playerObjectsFrameCache = (((Object)(object)GameDirector.instance == (Object)null) ? null : GameDirector.instance.PlayerList); return playerObjectsFrameCache; } private static int GetEnemyKey(Enemy enemy) { if (!((Object)(object)enemy == (Object)null)) { return ((Object)enemy).GetInstanceID(); } return 0; } private bool TryGetEnemyDistanceOrigin(out Vector3 origin) { //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) //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_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) try { PlayerAvatar localPlayer = GetLocalPlayer(GetPlayerObjectsCachedForFrame()); if ((Object)(object)localPlayer != (Object)null) { origin = GetPlayerDistanceOrigin(localPlayer, IsPlayerAlive(localPlayer)); return true; } } catch { } Camera worldLabelCamera = GetWorldLabelCamera(); if ((Object)(object)worldLabelCamera != (Object)null) { origin = ((Component)worldLabelCamera).transform.position; return true; } origin = Vector3.zero; return false; } private int GetEnemyBreakdownRank(Enemy enemy) { int enemyKey = GetEnemyKey(enemy); if (enemyKey != 0 && enemyBreakdownRankCache.TryGetValue(enemyKey, out var value)) { return value; } string enemyRawSortName = GetEnemyRawSortName(enemy); if (string.IsNullOrWhiteSpace(enemyRawSortName)) { return 999; } if (!enemyBreakdownRawNameRankCache.TryGetValue(enemyRawSortName, out var value2)) { string key = NormalizeEnemyBreakdownKey(enemyRawSortName); value2 = (EnemyBreakdownRankTable.TryGetValue(key, out var value3) ? value3 : 999); enemyBreakdownRawNameRankCache[enemyRawSortName] = value2; } if (enemyKey != 0) { enemyBreakdownRankCache[enemyKey] = value2; } return value2; } private static string GetEnemyRawSortName(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return string.Empty; } try { if (TryGetEnemyParentDisplayName(GetEnemyParentFast(enemy), out var name)) { return name; } } catch { } try { Type type = ((object)enemy).GetType(); if (type != null && !string.IsNullOrWhiteSpace(type.Name)) { return type.Name.Replace("(Clone)", string.Empty).Trim(); } } catch { } if (!string.IsNullOrWhiteSpace(((Object)enemy).name)) { return ((Object)enemy).name.Replace("(Clone)", string.Empty).Trim(); } return string.Empty; } private static string NormalizeEnemyBreakdownKey(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } return ReplaceIgnoreCase(ReplaceIgnoreCase(ReplaceIgnoreCase(ReplaceIgnoreCase(ReplaceIgnoreCase(ReplaceIgnoreCase(ReplaceIgnoreCase(ReplaceIgnoreCase(ReplaceIgnoreCase(ReplaceIgnoreCase(ReplaceIgnoreCase(ReplaceIgnoreCase(value.Replace("(Clone)", string.Empty).Trim(), "Enemy ", string.Empty), "Peeper Ceiling Eye", "Peeper"), "Headgrab", "Head Grabber"), "Headman", "Head"), "Bomb Thrower", "Cleanup Crew"), "Banger", "Bang"), "Runner", "Reaper"), "Clown", "Beamer"), "Chef", "Cleanup Crew"), "Frog", "Cleanup Crew"), "Tumbler", "Cleanup Crew"), "Huntsman", "Hunter").Trim(); } private static string ReplaceIgnoreCase(string source, string oldValue, string newValue) { if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(oldValue)) { return source; } for (int num = source.IndexOf(oldValue, StringComparison.OrdinalIgnoreCase); num >= 0; num = source.IndexOf(oldValue, num + (newValue?.Length ?? 0), StringComparison.OrdinalIgnoreCase)) { source = source.Remove(num, oldValue.Length).Insert(num, newValue ?? string.Empty); } return source; } private void BeginOverlaySectionLine(StringBuilder builder, ref bool hasWrittenAnySection, ref bool sectionStarted) { if (builder == null) { return; } if (sectionStarted) { builder.Append('\n'); return; } if (hasWrittenAnySection) { builder.Append('\n'); if (sectionSpacing.Value) { builder.Append('\n'); } } hasWrittenAnySection = true; sectionStarted = true; } private void AppendOverlaySectionLine(StringBuilder builder, ref bool hasWrittenAnySection, ref bool sectionStarted, string line) { if (builder != null && !string.IsNullOrWhiteSpace(line)) { BeginOverlaySectionLine(builder, ref hasWrittenAnySection, ref sectionStarted); builder.Append(line); } } private static string ColorOverlayLine(string text, string colorHex) { if (string.IsNullOrWhiteSpace(text)) { return text; } string text2 = (string.IsNullOrWhiteSpace(colorHex) ? "ffffff" : colorHex.TrimStart(new char[1] { '#' })); return "" + text + ""; } private static int GetDistanceScaledFontSize(int maxFontSize, float shrinkPercent, float distance, float fullShrinkDistance, int hardMaxFontSize) { int num = Mathf.Clamp(maxFontSize, 8, hardMaxFontSize); float num2 = Mathf.Clamp(shrinkPercent, 0f, 75f) / 100f; float num3 = Mathf.Max(1f, fullShrinkDistance); float num4 = Mathf.Clamp01(Mathf.Max(0f, distance) / num3); float num5 = 1f + num2; float num6 = 1f - num2; float num7 = Mathf.Lerp(num5, num6, num4); return Mathf.Clamp(Mathf.RoundToInt((float)num * num7), 8, hardMaxFontSize); } private static Vector2 CalcLabelSize(GUIStyle style, string text) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) ReusableGuiContent.text = text ?? string.Empty; return style.CalcSize(ReusableGuiContent); } private static float CalcLabelHeight(GUIStyle style, string text, float width) { ReusableGuiContent.text = text ?? string.Empty; return style.CalcHeight(ReusableGuiContent, width); } private GUIStyle GetCenteredLabelStyle(int fontSize, bool shadow) { //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_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = (shadow ? centeredShadowLabelStyleCache : centeredRichLabelStyleCache); int key = Mathf.Clamp(fontSize, 8, 60); if (dictionary.TryGetValue(key, out var value)) { value.normal.textColor = (Color)(shadow ? new Color(0f, 0f, 0f, 0.85f) : Color.white); return value; } value = new GUIStyle(GUI.skin.label) { fontSize = key, fontStyle = (FontStyle)1, alignment = (TextAnchor)4, wordWrap = false, richText = !shadow }; value.normal.textColor = (Color)(shadow ? new Color(0f, 0f, 0f, 0.85f) : Color.white); dictionary[key] = value; return value; } private GUIStyle GetOverlayLabelStyle(int fontSize, bool shadow) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_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_0068: Expected O, but got Unknown Dictionary dictionary = (shadow ? overlayShadowStyleCache : overlayRichStyleCache); int key = Mathf.Clamp(fontSize, 10, 28); if (dictionary.TryGetValue(key, out var value)) { ApplyOverlayTextStyleColor(value, shadow); return value; } value = new GUIStyle(GUI.skin.label) { fontSize = key, fontStyle = (FontStyle)1, alignment = (TextAnchor)8, wordWrap = false, richText = !shadow }; ApplyOverlayTextStyleColor(value, shadow); dictionary[key] = value; return value; } private void ApplyOverlayTextStyleColor(GUIStyle style, bool shadow) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (style != null) { float overlayTextOpacity = GetOverlayTextOpacity01(); float num = (shadow ? Mathf.Min(0.85f, overlayTextOpacity) : overlayTextOpacity); style.normal.textColor = (shadow ? new Color(0f, 0f, 0f, num) : new Color(1f, 1f, 1f, num)); } } private float GetOverlayTextOpacity01() { return (float)((overlayTextOpacityPercent == null) ? 100 : Mathf.Clamp(overlayTextOpacityPercent.Value, 1, 100)) / 100f; } private void UpdateNativeOverlay() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) if (displayMode.Value != DisplayMode.原生UI显示) { return; } if (string.IsNullOrWhiteSpace(overlayText)) { ClearNativeOverlayContent(); return; } if (!string.Equals(lastNativeOverlayText, overlayText, StringComparison.Ordinal)) { RebuildNativeOverlay(); } EnsureNativeOverlay(); if (!((Object)(object)overlayLabel == (Object)null) && !((Object)(object)overlayRect == (Object)null)) { int fontSizeValue = Mathf.Clamp(fontSize.Value - 13, 5, 28); float overlayTextOpacity = GetOverlayTextOpacity01(); float num = (showBreakdown.Value ? 430f : 320f); overlayRect.anchorMin = new Vector2(1f, 0f); overlayRect.anchorMax = new Vector2(1f, 0f); overlayRect.pivot = new Vector2(1f, 0f); overlayRect.anchoredPosition = new Vector2(2f - (float)overlayOffsetX.Value, -2f + (float)overlayOffsetY.Value); FillNativeOverlayLines(overlayText, nativeOverlayLineTextBuffer); EnsureNativeOverlayLineCount(nativeOverlayLineTextBuffer.Count); float num2 = 0f; int num3 = nativeOverlayLineTextBuffer.Count - 1; int num4 = 0; while (num3 >= 0) { string text = nativeOverlayLineTextBuffer[num3]; bool isBlank = string.IsNullOrWhiteSpace(text); float nativeOverlayLineHeight = GetNativeOverlayLineHeight(fontSizeValue, isBlank); UpdateNativeOverlayLine(num4, text, num, num2, nativeOverlayLineHeight, fontSizeValue, overlayTextOpacity, isBlank); num2 += nativeOverlayLineHeight; num3--; num4++; } for (int i = nativeOverlayLineTextBuffer.Count; i < nativeOverlayLineLabels.Count; i++) { DeactivateNativeOverlayLine(i); } overlayRect.sizeDelta = new Vector2(num, Mathf.Max(1f, num2)); lastNativeOverlayText = overlayText; lastNativeOverlayFontSize = fontSizeValue; lastNativeOverlayOffsetX = overlayOffsetX.Value; lastNativeOverlayOffsetY = overlayOffsetY.Value; lastNativeOverlayShowBreakdown = showBreakdown.Value; lastNativeOverlayOpacity = overlayTextOpacity; lastNativeOverlayParent = ((Transform)overlayRect).parent; } } private void ClearNativeOverlayContent() { for (int i = 0; i < nativeOverlayLineLabels.Count; i++) { DeactivateNativeOverlayLine(i); } nativeOverlayLineTextBuffer.Clear(); lastNativeOverlayText = string.Empty; lastNativeOverlayFontSize = -1; lastNativeOverlayOffsetX = int.MinValue; lastNativeOverlayOffsetY = int.MinValue; lastNativeOverlayShowBreakdown = false; lastNativeOverlayOpacity = -1f; lastNativeOverlayParent = null; } private void RebuildNativeOverlay() { if ((Object)(object)overlayObject != (Object)null) { Object.Destroy((Object)(object)overlayObject); } overlayObject = null; overlayRect = null; overlayLabel = null; nativeOverlayLineLabels.Clear(); nativeOverlayLineRects.Clear(); nativeOverlayLineStates.Clear(); nativeOverlayLineTextBuffer.Clear(); lastNativeOverlayParent = null; } private void EnsureNativeOverlay() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown Transform nativeHudParent = GetNativeHudParent(); if ((Object)(object)overlayObject != (Object)null && (Object)(object)overlayLabel != (Object)null && (Object)(object)overlayRect != (Object)null) { if ((Object)(object)nativeHudParent != (Object)null && (Object)(object)((Transform)overlayRect).parent != (Object)(object)nativeHudParent) { ((Transform)overlayRect).SetParent(nativeHudParent, false); ((Transform)overlayRect).SetAsLastSibling(); TryCopyNativeHudStyle(overlayLabel); } return; } overlayObject = new GameObject("moreui.NativeOverlay", new Type[1] { typeof(RectTransform) }); overlayObject.transform.SetParent(nativeHudParent, false); overlayObject.transform.SetAsLastSibling(); overlayRect = overlayObject.GetComponent(); overlayLabel = overlayObject.AddComponent(); ((Graphic)overlayLabel).raycastTarget = false; ((TMP_Text)overlayLabel).richText = false; ((TMP_Text)overlayLabel).enableWordWrapping = false; ((TMP_Text)overlayLabel).alignment = (TextAlignmentOptions)1028; ((TMP_Text)overlayLabel).overflowMode = (TextOverflowModes)0; ((TMP_Text)overlayLabel).lineSpacing = -4f; ((TMP_Text)overlayLabel).paragraphSpacing = -1f; TryCopyNativeHudStyle(overlayLabel); ApplyStableNativeOverlayFont(overlayLabel); ((Component)overlayLabel).gameObject.SetActive(false); nativeOverlayLineLabels.Clear(); nativeOverlayLineRects.Clear(); nativeOverlayLineStates.Clear(); } private void EnsureNativeOverlayLineCount(int requiredCount) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (requiredCount < 0) { requiredCount = 0; } while (nativeOverlayLineLabels.Count < requiredCount) { GameObject val = new GameObject($"moreui.NativeOverlay.Line{nativeOverlayLineLabels.Count}", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(overlayObject.transform, false); RectTransform component = val.GetComponent(); TextMeshProUGUI val2 = val.AddComponent(); ((Graphic)val2).raycastTarget = false; ((TMP_Text)val2).richText = false; ((TMP_Text)val2).enableWordWrapping = false; ((TMP_Text)val2).alignment = (TextAlignmentOptions)1028; ((TMP_Text)val2).overflowMode = (TextOverflowModes)0; ((TMP_Text)val2).horizontalAlignment = (HorizontalAlignmentOptions)4; ((TMP_Text)val2).verticalAlignment = (VerticalAlignmentOptions)1024; ((TMP_Text)val2).lineSpacing = 0f; ((TMP_Text)val2).paragraphSpacing = 0f; TryCopyNativeHudStyle(val2); ApplyStableNativeOverlayFont(val2); nativeOverlayLineRects.Add(component); nativeOverlayLineLabels.Add(val2); nativeOverlayLineStates.Add(default(NativeOverlayLineState)); } } private void UpdateNativeOverlayLine(int index, string line, float width, float baseY, float lineHeight, int fontSizeValue, float opacity, bool isBlank) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_025d: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) if (index < 0 || index >= nativeOverlayLineLabels.Count) { return; } TextMeshProUGUI val = nativeOverlayLineLabels[index]; RectTransform val2 = nativeOverlayLineRects[index]; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return; } if (isBlank) { DeactivateNativeOverlayLine(index); return; } bool flag = line.IndexOf("= 0; Color val3 = (Color)(flag ? new Color(1f, 1f, 1f, opacity) : GetNativeOverlayLineColor(line, opacity)); string text = (flag ? line : StripNativeOverlayRichText(line)); Color32 val4 = Color32.op_Implicit(val3); NativeOverlayLineState nativeOverlayLineState = nativeOverlayLineStates[index]; if (!nativeOverlayLineState.Active || nativeOverlayLineState.RichText != flag || nativeOverlayLineState.FontSize != fontSizeValue || nativeOverlayLineState.Color.r != val4.r || nativeOverlayLineState.Color.g != val4.g || nativeOverlayLineState.Color.b != val4.b || nativeOverlayLineState.Color.a != val4.a || !string.Equals(nativeOverlayLineState.Text, text, StringComparison.Ordinal)) { ((Component)val).gameObject.SetActive(true); val.canvasRenderer.Clear(); ((TMP_Text)val).text = string.Empty; ((TMP_Text)val).richText = flag; ((TMP_Text)val).text = text; ApplyStableNativeOverlayFont(val); ((TMP_Text)val).fontSize = fontSizeValue; ((Graphic)val).color = val3; ((TMP_Text)val).enableWordWrapping = false; ((TMP_Text)val).alignment = (TextAlignmentOptions)1028; ((TMP_Text)val).overflowMode = (TextOverflowModes)0; ((TMP_Text)val).horizontalAlignment = (HorizontalAlignmentOptions)4; ((TMP_Text)val).verticalAlignment = (VerticalAlignmentOptions)1024; ((Graphic)val).SetAllDirty(); ((TMP_Text)val).ForceMeshUpdate(true, true); } else if (!((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(true); } if (!nativeOverlayLineState.Active || !Mathf.Approximately(nativeOverlayLineState.BaseY, baseY) || !Mathf.Approximately(nativeOverlayLineState.Width, width) || !Mathf.Approximately(nativeOverlayLineState.Height, lineHeight)) { val2.anchorMin = new Vector2(1f, 0f); val2.anchorMax = new Vector2(1f, 0f); val2.pivot = new Vector2(1f, 0f); val2.anchoredPosition = new Vector2(0f, baseY); val2.sizeDelta = new Vector2(width, lineHeight); } nativeOverlayLineStates[index] = new NativeOverlayLineState { Active = true, RichText = flag, FontSize = fontSizeValue, Text = text, Color = val4, Width = width, BaseY = baseY, Height = lineHeight }; } private void DeactivateNativeOverlayLine(int index) { if (index >= 0 && index < nativeOverlayLineLabels.Count) { TextMeshProUGUI val = nativeOverlayLineLabels[index]; if ((Object)(object)val != (Object)null) { val.canvasRenderer.Clear(); ((TMP_Text)val).text = string.Empty; ((Component)val).gameObject.SetActive(false); } if (index < nativeOverlayLineStates.Count) { nativeOverlayLineStates[index] = default(NativeOverlayLineState); } } } private void FillNativeOverlayLines(string text, List result) { result.Clear(); if (string.IsNullOrEmpty(text)) { return; } int num = 0; for (int i = 0; i < text.Length; i++) { char c = text[i]; if (c != '\r' && c == '\n') { result.Add(ExtractNativeOverlayLine(text, num, i)); num = i + 1; } } if (num <= text.Length) { result.Add(ExtractNativeOverlayLine(text, num, text.Length)); } } private static string ExtractNativeOverlayLine(string text, int start, int endExclusive) { if (string.IsNullOrEmpty(text)) { return string.Empty; } while (start < endExclusive && text[start] == '\r') { start++; } while (endExclusive > start && text[endExclusive - 1] == '\r') { endExclusive--; } if (endExclusive > start) { return text.Substring(start, endExclusive - start); } return string.Empty; } private static Color GetNativeOverlayLineColor(string line, float opacity) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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) if (string.IsNullOrWhiteSpace(line)) { return new Color(1f, 1f, 1f, opacity); } string text = TryExtractFirstColorHex(line); if (string.IsNullOrWhiteSpace(text)) { return new Color(1f, 1f, 1f, opacity); } Color result = default(Color); if (!ColorUtility.TryParseHtmlString("#" + text, ref result)) { return new Color(1f, 1f, 1f, opacity); } result.a = opacity; return result; } private string StripNativeOverlayRichText(string line) { if (string.IsNullOrEmpty(line)) { return string.Empty; } reusableNativeOverlayTagStripBuilder.Clear(); bool flag = false; foreach (char c in line) { switch (c) { case '<': flag = true; continue; case '>': flag = false; continue; } if (!flag) { reusableNativeOverlayTagStripBuilder.Append(c); } } return reusableNativeOverlayTagStripBuilder.ToString(); } private static string TryExtractFirstColorHex(string line) { if (string.IsNullOrEmpty(line)) { return null; } int num = line.IndexOf(" '9') && (character < 'a' || character > 'f')) { if (character >= 'A') { return character <= 'F'; } return false; } return true; } private static float GetNativeOverlayLineHeight(int fontSizeValue, bool isBlank) { if (isBlank) { return Mathf.Max(6f, (float)fontSizeValue * 0.6f); } return Mathf.Max(8f, (float)fontSizeValue + 6f); } private void ApplyStableNativeOverlayFont(TextMeshProUGUI target) { if (!((Object)(object)target == (Object)null)) { ResolveStableNativeOverlayFont(); if (!((Object)(object)nativeOverlayStableFont == (Object)null)) { ((TMP_Text)target).font = nativeOverlayStableFont; ((TMP_Text)target).fontSharedMaterial = (((Object)(object)nativeOverlayStableMaterial != (Object)null) ? nativeOverlayStableMaterial : ((TMP_Asset)nativeOverlayStableFont).material); ((TMP_Text)target).enableAutoSizing = false; ((TMP_Text)target).fontSizeMin = 5f; ((TMP_Text)target).fontSizeMax = 28f; } } } private void ResolveStableNativeOverlayFont() { if (!nativeOverlayStableFontResolved) { nativeOverlayStableFontResolved = true; object obj = InvokeTranslatorFontCacheMethod("GetOrCreateOverrideFontTextMeshPro") ?? InvokeTranslatorFontCacheMethod("GetOrCreateFallbackFontTextMeshPro"); nativeOverlayStableFont = (TMP_FontAsset)((obj is TMP_FontAsset) ? obj : null); nativeOverlayStableMaterial = (((Object)(object)nativeOverlayStableFont != (Object)null) ? ((TMP_Asset)nativeOverlayStableFont).material : null); } } private static object InvokeTranslatorFontCacheMethod(string methodName) { if (string.IsNullOrWhiteSpace(methodName)) { return null; } try { Type type = AccessTools.TypeByName("XUnity.AutoTranslator.Plugin.Core.Fonts.FontCache"); if (type == null) { return null; } return AccessTools.Method(type, methodName, (Type[])null, (Type[])null)?.Invoke(null, null); } catch { return null; } } private static Transform GetNativeHudParent() { TextMeshProUGUI nativeHudTextSource = GetNativeHudTextSource(); if ((Object)(object)nativeHudTextSource != (Object)null) { return ((TMP_Text)nativeHudTextSource).transform.parent; } if ((Object)(object)HUDCanvas.instance != (Object)null) { return ((Component)HUDCanvas.instance).transform; } Canvas val = Object.FindObjectOfType(); if (!((Object)(object)val == (Object)null)) { return ((Component)val).transform; } return null; } private static TextMeshProUGUI GetNativeHudTextSource() { if ((Object)(object)GoalUI.instance != (Object)null) { TextMeshProUGUI component = ((Component)GoalUI.instance).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } } if ((Object)(object)HaulUI.instance != (Object)null) { TextMeshProUGUI component2 = ((Component)HaulUI.instance).GetComponent(); if ((Object)(object)component2 != (Object)null) { return component2; } } return null; } private static void TryCopyNativeHudStyle(TextMeshProUGUI target) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null)) { TextMeshProUGUI nativeHudTextSource = GetNativeHudTextSource(); if ((Object)(object)nativeHudTextSource == (Object)null) { ((Graphic)target).color = Color.white; ((TMP_Text)target).alignment = (TextAlignmentOptions)1028; return; } ((TMP_Text)target).font = ((TMP_Text)nativeHudTextSource).font; ((TMP_Text)target).fontSharedMaterial = ((TMP_Text)nativeHudTextSource).fontSharedMaterial; ((Graphic)target).color = Color.white; ((TMP_Text)target).fontStyle = ((TMP_Text)nativeHudTextSource).fontStyle; ((TMP_Text)target).enableAutoSizing = false; ((TMP_Text)target).fontSizeMin = 5f; ((TMP_Text)target).fontSizeMax = 28f; ((TMP_Text)target).characterSpacing = 0f; ((TMP_Text)target).wordSpacing = 0f; ((TMP_Text)target).lineSpacing = -4f; ((TMP_Text)target).paragraphSpacing = -1f; ((TMP_Text)target).enableWordWrapping = false; ((TMP_Text)target).overflowMode = (TextOverflowModes)0; ((TMP_Text)target).isRightToLeftText = ((TMP_Text)nativeHudTextSource).isRightToLeftText; ((TMP_Text)target).extraPadding = false; ((TMP_Text)target).richText = false; ((TMP_Text)target).margin = ((TMP_Text)nativeHudTextSource).margin; ((TMP_Text)target).outlineColor = ((TMP_Text)nativeHudTextSource).outlineColor; ((TMP_Text)target).outlineWidth = ((TMP_Text)nativeHudTextSource).outlineWidth; ((TMP_Text)target).enableVertexGradient = false; ((TMP_Text)target).alignment = (TextAlignmentOptions)1028; } } private float UpdateAndGetLostMapValue(List valuables, HashSet haulObjects) { int num = SemiFunc.RunGetLevelsCompleted() + 1; if (trackedLevelNumber != num || previousExtractedValue < 0f) { trackedLevelNumber = num; previousExtractedValue = 0f; accumulatedLostValue = 0f; valuableSnapshots.Clear(); UpdateValuableLossSnapshots(extractionJustChanged: false, valuables, haulObjects); return accumulatedLostValue; } UpdateValuableLossSnapshots(extractionJustChanged: false, valuables, haulObjects); return accumulatedLostValue; } private void ResetLossTracking() { trackedLevelNumber = -1; valuableSnapshotGeneration = 0; previousExtractedValue = -1f; accumulatedLostValue = 0f; submittedFundsSnapshotLevelNumber = -1; submittedFundsBaselineTotalHaul = -1f; submittedFundsSnapshot = 0f; shopRemainingSnapshotLevelNumber = -1; shopRemainingFundsSnapshot = -1f; valuableSnapshots.Clear(); valuablesCurrentlyInDollarHaul.Clear(); ZichenMapValueService.Reset(); } private void UpdateValuableLossSnapshots(bool extractionJustChanged, List valuables, HashSet haulObjects) { haulObjects = haulObjects ?? EmptyReferenceSet; valuableSnapshotGeneration++; int num = valuableSnapshotGeneration; if (valuables != null) { foreach (ValuableObject valuable in valuables) { if (!((Object)(object)valuable == (Object)null) && IsValuableReady(valuable)) { int valuableKey = GetValuableKey(valuable); float valuableOriginalValueFast = GetValuableOriginalValueFast(valuable); float valuableCurrentValueFast = GetValuableCurrentValueFast(valuable); float num2 = Mathf.Max(0f, valuableOriginalValueFast - valuableCurrentValueFast); PhysGrabObject valuablePhysGrabObjectFast = GetValuablePhysGrabObjectFast(valuable); bool flag = IsValuableMarkedInHaul(valuableKey) || IsValuableInReferenceSet(valuable, valuablePhysGrabObjectFast, haulObjects); if (!valuableSnapshots.TryGetValue(valuableKey, out var value)) { ValuableSnapshot valuableSnapshot = default(ValuableSnapshot); valuableSnapshot.CountedLostValue = 0f; value = valuableSnapshot; } value.OriginalValue = valuableOriginalValueFast; value.CurrentValue = valuableCurrentValueFast; value.CurrentDamage = num2; value.WasInHaul = flag; value.SeenGeneration = num; float num3 = Mathf.Clamp(num2, 0f, Mathf.Max(0f, valuableOriginalValueFast)); if (!flag && num3 > value.CountedLostValue + 0.01f) { accumulatedLostValue += num3 - value.CountedLostValue; value.CountedLostValue = num3; } valuableSnapshots[valuableKey] = value; } } } reusableSnapshotKeys.Clear(); foreach (KeyValuePair valuableSnapshot2 in valuableSnapshots) { if (valuableSnapshot2.Value.SeenGeneration != num) { reusableSnapshotKeys.Add(valuableSnapshot2.Key); } } foreach (int reusableSnapshotKey in reusableSnapshotKeys) { ValuableSnapshot snapshot = valuableSnapshots[reusableSnapshotKey]; if (!snapshot.WasInHaul && !extractionJustChanged) { accumulatedLostValue += CalculateRemovedValuableLoss(snapshot); } valuableSnapshots.Remove(reusableSnapshotKey); } } private static float CalculateRemovedValuableLoss(ValuableSnapshot snapshot) { float num = Mathf.Max(0f, snapshot.OriginalValue); return Mathf.Max(0f, num - snapshot.CountedLostValue); } private static float GetShopRemainingFundsValue() { try { return (float)SemiFunc.StatGetRunCurrency() * 1000f; } catch { return 0f; } } private float GetShopRemainingFundsSnapshot() { int num = SemiFunc.RunGetLevelsCompleted() + 1; if (shopRemainingSnapshotLevelNumber != num || shopRemainingFundsSnapshot < 0f) { shopRemainingSnapshotLevelNumber = num; shopRemainingFundsSnapshot = GetShopRemainingFundsValue(); } return shopRemainingFundsSnapshot; } private static float GetRunTotalHaulValue() { try { return (float)SemiFunc.StatGetRunTotalHaul() * 1000f; } catch { return 0f; } } private float GetCurrentLevelSubmittedValue() { int submittedFundsLevelKey = GetSubmittedFundsLevelKey(); if (submittedFundsSnapshotLevelNumber != submittedFundsLevelKey || submittedFundsBaselineTotalHaul < 0f) { submittedFundsSnapshotLevelNumber = submittedFundsLevelKey; submittedFundsBaselineTotalHaul = GetRunTotalHaulValue(); submittedFundsSnapshot = 0f; } float num = Mathf.Max(0f, GetRunTotalHaulValue() - submittedFundsBaselineTotalHaul); submittedFundsSnapshot = Mathf.Max(submittedFundsSnapshot, num); return submittedFundsSnapshot; } private static int GetSubmittedFundsLevelKey() { int num = SemiFunc.RunGetLevelsCompleted(); try { return SemiFunc.RunIsShop() ? num : (num + 1); } catch { return num + 1; } } private static bool IsValuableReady(ValuableObject valuable) { if ((Object)(object)valuable == (Object)null) { return false; } return IsValuableValueSetFast(valuable); } private static int GetValuableKey(ValuableObject valuable) { PhotonView valuablePhotonViewFast = GetValuablePhotonViewFast(valuable); if ((Object)(object)valuablePhotonViewFast != (Object)null && valuablePhotonViewFast.ViewID != 0) { return valuablePhotonViewFast.ViewID; } return ((Object)valuable).GetInstanceID(); } private static void FillCurrentDollarHaulObjects(List result) { if (result == null) { return; } result.Clear(); List list = (((Object)(object)RoundDirector.instance == (Object)null) ? null : RoundDirector.instance.dollarHaulList); if (list == null) { return; } foreach (GameObject item in list) { if ((Object)(object)item != (Object)null) { result.Add(item); } } } private void FillCurrentCartObjects(List result) { if (result == null) { return; } result.Clear(); List cartObjectsCachedForFrame = GetCartObjectsCachedForFrame(); if (cartObjectsCachedForFrame == null || cartObjectsCachedForFrame.Count == 0) { return; } foreach (PhysGrabCart item in cartObjectsCachedForFrame) { if ((Object)(object)item == (Object)null) { continue; } AddEnumerableObjects(result, GetCartItemsInCartFast(item)); List physGrabInCartObjectsFast = GetPhysGrabInCartObjectsFast(item.physGrabInCart); if (physGrabInCartObjectsFast == null) { continue; } foreach (CartObject item2 in physGrabInCartObjectsFast) { PhysGrabObject val = item2?.physGrabObject; if ((Object)(object)val != (Object)null) { result.Add(val); } } } } private static void AddEnumerableObjects(List result, object rawList) { if (!(rawList is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { if (item != null) { result.Add(item); } } } private static void FillReferenceSet(List list, HashSet result) { if (result == null) { return; } result.Clear(); if (list == null || list.Count == 0) { return; } foreach (object item in list) { AddReferenceObjectVariants(item, result); } } private static void AddReferenceObjectVariants(object item, HashSet result) { if (item != null && result != null) { result.Add(item); GameObject objectGameObject = GetObjectGameObject(item); if ((Object)(object)objectGameObject != (Object)null) { result.Add(objectGameObject); } } } private static bool IsValuableMarkedInHaul(int key) { if (key != 0) { return valuablesCurrentlyInDollarHaul.Contains(key); } return false; } private static bool IsValuableInReferenceSet(ValuableObject valuable, object physGrabObject, HashSet set) { if ((Object)(object)valuable == (Object)null || set == null || set.Count == 0) { return false; } GameObject gameObject = ((Component)valuable).gameObject; GameObject objectGameObject = GetObjectGameObject(physGrabObject); if (!set.Contains(valuable) && (!((Object)(object)gameObject != (Object)null) || !set.Contains(gameObject)) && (physGrabObject == null || !set.Contains(physGrabObject))) { if ((Object)(object)objectGameObject != (Object)null) { return set.Contains(objectGameObject); } return false; } return true; } 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 string BuildLevelLine() { DisplayLanguage currentLanguage = CurrentLanguage; GetLevelInfo(currentLanguage, out var levelNumber, out var levelName); return $"{HudText.Level(currentLanguage)}: {levelNumber} - {levelName}"; } private string BuildPlayerCountLine() { DisplayLanguage currentLanguage = CurrentLanguage; GetPlayerCounts(out var totalPlayers, out var alivePlayers, out var deadPlayers); return $"{HudText.PlayerCounts(currentLanguage)}: {HudText.Dead(currentLanguage)} {deadPlayers} | {HudText.Alive(currentLanguage)} {alivePlayers} | {HudText.Total(currentLanguage)} {totalPlayers}"; } private static void GetLevelInfo(DisplayLanguage language, out int levelNumber, out string levelName) { levelNumber = SemiFunc.RunGetLevelsCompleted() + 1; levelName = HudText.UnknownLevel(language); if ((Object)(object)RunManager.instance != (Object)null && (Object)(object)RunManager.instance.levelCurrent != (Object)null) { string narrativeName = RunManager.instance.levelCurrent.NarrativeName; if (!string.IsNullOrWhiteSpace(narrativeName)) { levelName = LevelNameLocalizer.Translate(narrativeName.Trim(), language); } } } private void GetPlayerCounts(out int totalPlayers, out int alivePlayers, out int deadPlayers) { int frameCount = Time.frameCount; if (playerCountsFrame == frameCount) { totalPlayers = cachedTotalPlayers; alivePlayers = cachedAlivePlayers; deadPlayers = cachedDeadPlayers; return; } List playerObjectsCachedForFrame = GetPlayerObjectsCachedForFrame(); totalPlayers = playerObjectsCachedForFrame?.Count ?? 0; alivePlayers = 0; if (playerObjectsCachedForFrame != null) { foreach (PlayerAvatar item in playerObjectsCachedForFrame) { if (IsPlayerAlive(item)) { alivePlayers++; } } } deadPlayers = Math.Max(0, totalPlayers - alivePlayers); CachePlayerCountsForFrame(frameCount, totalPlayers, alivePlayers, deadPlayers); } private void AppendTeammateDistanceLines(List teammates, bool deadOnly, StringBuilder builder, ref bool hasWrittenAnySection, ref bool sectionStarted) { if (teammates == null || teammates.Count == 0 || builder == null) { return; } foreach (MoreUiPlayerDistance teammate in teammates) { if (teammate != null && teammate.IsDead == deadOnly) { string overlayLine = teammate.OverlayLine; AppendOverlaySectionLine(builder, ref hasWrittenAnySection, ref sectionStarted, overlayLine); } } } private List CreateTeammateDistanceInfos() { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_0317: Unknown result type (might be due to invalid IL or missing references) int frameCount = Time.frameCount; if (teammateDistanceCacheFrame == frameCount) { return teammateDistanceBuffer; } List playerObjectsCachedForFrame = GetPlayerObjectsCachedForFrame(); teammateDistanceBuffer.Clear(); if (playerObjectsCachedForFrame == null || playerObjectsCachedForFrame.Count == 0) { teammateDistanceCacheFrame = frameCount; CachePlayerCountsForFrame(frameCount, 0, 0, 0); return teammateDistanceBuffer; } PlayerAvatar localPlayer = GetLocalPlayer(playerObjectsCachedForFrame); int count = playerObjectsCachedForFrame.Count; int num = 0; bool localAlive = (Object)(object)localPlayer != (Object)null && IsPlayerAlive(localPlayer); Vector3 val = (((Object)(object)localPlayer == (Object)null) ? Vector3.zero : GetPlayerDistanceOrigin(localPlayer, localAlive)); foreach (PlayerAvatar item in playerObjectsCachedForFrame) { if ((Object)(object)item == (Object)null) { continue; } bool flag = IsPlayerAlive(item); if (flag) { num++; } if (!((Object)(object)localPlayer == (Object)null)) { bool flag2 = item == localPlayer; if (!(flag2 && flag)) { Vector3 playerReferencePosition = GetPlayerReferencePosition(item, !flag); float num2 = Vector3.Distance(val, playerReferencePosition); int num3 = Mathf.RoundToInt(num2); MoreUiPlayerDistance pooledTeammateDistanceInfo = GetPooledTeammateDistanceInfo(teammateDistanceBuffer.Count); pooledTeammateDistanceInfo.Name = GetCachedPlayerName(item); pooledTeammateDistanceInfo.DistanceMeters = num3; pooledTeammateDistanceInfo.DistanceValue = num2; pooledTeammateDistanceInfo.IsDead = !flag; pooledTeammateDistanceInfo.IsLocalPlayer = flag2; pooledTeammateDistanceInfo.ColorHex = GetCachedPlayerColorHex(item); pooledTeammateDistanceInfo.PlainTextNoDistance = (pooledTeammateDistanceInfo.IsDead ? ("☠ " + pooledTeammateDistanceInfo.Name) : (pooledTeammateDistanceInfo.Name ?? string.Empty)); pooledTeammateDistanceInfo.PlainText = (pooledTeammateDistanceInfo.IsDead ? $"{pooledTeammateDistanceInfo.PlainTextNoDistance} {num3}m" : $"{pooledTeammateDistanceInfo.PlainTextNoDistance} {num3}m"); pooledTeammateDistanceInfo.RichTextNoDistance = (pooledTeammateDistanceInfo.IsDead ? ("" + pooledTeammateDistanceInfo.Name + "") : ("" + pooledTeammateDistanceInfo.Name + "")); pooledTeammateDistanceInfo.RichText = (pooledTeammateDistanceInfo.IsDead ? $"{pooledTeammateDistanceInfo.Name} {num3}m" : $"{pooledTeammateDistanceInfo.Name} {num3}m"); pooledTeammateDistanceInfo.OverlayLine = (pooledTeammateDistanceInfo.IsDead ? $"{HudText.Dead(CurrentLanguage)} {pooledTeammateDistanceInfo.Name} {num3}m" : ColorOverlayLine($"{pooledTeammateDistanceInfo.Name} {num3}m", pooledTeammateDistanceInfo.ColorHex)); pooledTeammateDistanceInfo.LabelPosition = GetPlayerNameLabelPosition(item, !flag); teammateDistanceBuffer.Add(pooledTeammateDistanceInfo); } } } teammateDistanceCacheFrame = frameCount; CachePlayerCountsForFrame(frameCount, count, num, Math.Max(0, count - num)); teammateDistanceBuffer.Sort(ComparePlayerDistanceInfo); return teammateDistanceBuffer; } private void CachePlayerCountsForFrame(int frame, int totalPlayers, int alivePlayers, int deadPlayers) { playerCountsFrame = frame; cachedTotalPlayers = Math.Max(0, totalPlayers); cachedAlivePlayers = Math.Max(0, alivePlayers); cachedDeadPlayers = Math.Max(0, deadPlayers); } private MoreUiPlayerDistance GetPooledTeammateDistanceInfo(int index) { while (teammateDistancePool.Count <= index) { teammateDistancePool.Add(new MoreUiPlayerDistance()); } return teammateDistancePool[index]; } private static int ComparePlayerDistanceInfo(MoreUiPlayerDistance left, MoreUiPlayerDistance right) { if (left == right) { return 0; } if (left == null) { return 1; } if (right == null) { return -1; } int num = ((!left.IsDead) ? 1 : 0).CompareTo((!right.IsDead) ? 1 : 0); if (num != 0) { return num; } int num2 = left.DistanceMeters.CompareTo(right.DistanceMeters); if (num2 == 0) { return string.Compare(left.Name, right.Name, StringComparison.Ordinal); } return num2; } private void FillCartDistanceInfos(List result) { //IL_00e6: 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_00f8: 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_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) if (result == null) { return; } result.Clear(); if (!TryGetEnemyDistanceOrigin(out var origin)) { return; } List cartObjectsCachedForFrame = GetCartObjectsCachedForFrame(); if (cartObjectsCachedForFrame == null || cartObjectsCachedForFrame.Count == 0) { return; } EnsureCartLabelIndexLevel(); activeCartBuffer.Clear(); foreach (PhysGrabCart item in cartObjectsCachedForFrame) { if (IsCartCountable(item) && ShouldDisplayCart(item)) { activeCartBuffer.Add(item); } } AssignCartLabelIndices(activeCartBuffer); activeCartBuffer.Sort(CompareCartForLabelOrder); List grabbers = ((activeCartBuffer.Count == 0) ? null : GetGrabberObjectsCachedForFrame()); foreach (PhysGrabCart item2 in activeCartBuffer) { bool isSmallCart = IsSmallCartObject(item2); Vector3 cartReferencePosition = GetCartReferencePosition(item2); bool flag = IsCartBeingPushed(item2, grabbers); float num = Vector3.Distance(origin, cartReferencePosition); int num2 = Mathf.RoundToInt(num); string cartDisplayName = GetCartDisplayName(item2, isSmallCart); string text = (flag ? "44ff66" : "ffd84d"); string text2 = " " + cartDisplayName; string text3 = $"{text2} {num2}m"; MoreUiCartDistance pooledCartDistanceInfo = GetPooledCartDistanceInfo(result.Count); pooledCartDistanceInfo.Name = cartDisplayName; pooledCartDistanceInfo.Index = GetOrCreateCartLabelIndex(item2, isSmallCart); pooledCartDistanceInfo.IsSmallCart = isSmallCart; pooledCartDistanceInfo.DistanceMeters = num2; pooledCartDistanceInfo.DistanceValue = num; pooledCartDistanceInfo.IsBeingPushed = flag; pooledCartDistanceInfo.ColorHex = text; pooledCartDistanceInfo.PlainTextNoDistance = text2; pooledCartDistanceInfo.PlainText = text3; pooledCartDistanceInfo.RichTextNoDistance = "" + text2 + ""; pooledCartDistanceInfo.RichText = "" + text3 + ""; pooledCartDistanceInfo.ReferencePosition = cartReferencePosition; pooledCartDistanceInfo.LabelPosition = cartReferencePosition + Vector3.up * GetCachedCartLabelYOffset(item2, cartReferencePosition); result.Add(pooledCartDistanceInfo); } result.Sort(CompareCartDistanceInfo); } private MoreUiCartDistance GetPooledCartDistanceInfo(int index) { while (cartDistancePool.Count <= index) { cartDistancePool.Add(new MoreUiCartDistance()); } return cartDistancePool[index]; } private int CompareCartForLabelOrder(PhysGrabCart left, PhysGrabCart right) { bool flag = IsSmallCartObject(left); bool flag2 = IsSmallCartObject(right); int num = (flag ? 1 : 0).CompareTo(flag2 ? 1 : 0); if (num != 0) { return num; } return GetOrCreateCartLabelIndex(left, flag).CompareTo(GetOrCreateCartLabelIndex(right, flag2)); } private static int CompareCartDistanceInfo(MoreUiCartDistance left, MoreUiCartDistance right) { if (left == right) { return 0; } if (left == null) { return 1; } if (right == null) { return -1; } int num = (left.IsSmallCart ? 1 : 0).CompareTo(right.IsSmallCart ? 1 : 0); if (num == 0) { return left.Index.CompareTo(right.Index); } return num; } private bool IsCartCountable(PhysGrabCart cart) { //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)cart == (Object)null) && !((Object)(object)((Component)cart).gameObject == (Object)null)) { Scene scene = ((Component)cart).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { if (!((Component)cart).gameObject.activeInHierarchy) { return false; } if (IsSmallCartObject(cart) && IsSmallCartStored(cart)) { return false; } return true; } } return false; } private CartComponentCache GetCartComponents(PhysGrabCart cart) { if ((Object)(object)cart == (Object)null) { return default(CartComponentCache); } int instanceID = ((Object)cart).GetInstanceID(); if (this.cartComponentCache.TryGetValue(instanceID, out var value) && (Object)(object)value.Cart == (Object)(object)cart) { return value; } PhysGrabObject val = GetCartPhysGrabObjectFast(cart); if ((Object)(object)val == (Object)null) { val = ((Component)cart).GetComponent(); } ItemEquippable val2 = GetCartItemEquippableFast(cart); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)cart).GetComponent(); } CartComponentCache cartComponentCache = default(CartComponentCache); cartComponentCache.Cart = cart; cartComponentCache.PhysGrabObject = val; cartComponentCache.PhysGrabObjectComponent = (Component)(object)val; cartComponentCache.ItemEquippable = val2; CartComponentCache cartComponentCache2 = cartComponentCache; this.cartComponentCache[instanceID] = cartComponentCache2; return cartComponentCache2; } private bool ShouldDisplayCart(PhysGrabCart cart) { if (cartSectionEnabled != null && !cartSectionEnabled.Value) { return false; } if (!IsSmallCartObject(cart)) { if (cartOverlayEnabled != null) { return cartOverlayEnabled.Value; } return false; } if (smallCartOverlayEnabled != null) { return smallCartOverlayEnabled.Value; } return false; } private bool IsSmallCartObject(PhysGrabCart cart) { if ((Object)(object)cart == (Object)null) { return false; } int instanceID = ((Object)cart).GetInstanceID(); if (smallCartTypeCache.TryGetValue(instanceID, out var value)) { return value; } smallCartTypeCache[instanceID] = cart.isSmallCart; return cart.isSmallCart; } private bool IsSmallCartStored(PhysGrabCart cart) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 if ((Object)(object)cart == (Object)null) { return false; } ItemEquippable itemEquippable = GetCartComponents(cart).ItemEquippable; if ((Object)(object)itemEquippable == (Object)null) { return false; } ItemState? itemEquippableStateFast = GetItemEquippableStateFast(itemEquippable); if (itemEquippableStateFast.HasValue) { if ((int)itemEquippableStateFast.Value != 2) { return (int)itemEquippableStateFast.Value == 1; } return true; } return itemEquippable.IsEquipped(); } private static string GetHierarchyName(Transform transform) { if ((Object)(object)transform == (Object)null) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); Transform val = transform; int num = 0; while ((Object)(object)val != (Object)null && num < 8) { if (stringBuilder.Length > 0) { stringBuilder.Append(' '); } stringBuilder.Append(((Object)val).name); val = val.parent; num++; } return stringBuilder.ToString(); } private void EnsureCartLabelIndexLevel() { int num = SemiFunc.RunGetLevelsCompleted() + 1; if (cartLabelIndexLevelNumber != num) { cartLabelIndexLevelNumber = num; largeCartLabelIndices.Clear(); smallCartLabelIndices.Clear(); smallCartTypeCache.Clear(); nextLargeCartLabelIndex = 1; nextSmallCartLabelIndex = 1; } } private void ClearCartLabelIndices() { largeCartLabelIndices.Clear(); smallCartLabelIndices.Clear(); smallCartTypeCache.Clear(); cartLabelYOffsetCache.Clear(); cartComponentCache.Clear(); ClearCachedBoundsComponentData(); nextLargeCartLabelIndex = 1; nextSmallCartLabelIndex = 1; cartLabelIndexLevelNumber = -1; } private void AssignCartLabelIndices(List carts) { if (carts != null && carts.Count != 0) { AssignCartLabelIndicesForGroup(carts, targetSmallCart: false, largeCartLabelIndices, ref nextLargeCartLabelIndex); AssignCartLabelIndicesForGroup(carts, targetSmallCart: true, smallCartLabelIndices, ref nextSmallCartLabelIndex); } } private void AssignCartLabelIndicesForGroup(List carts, bool targetSmallCart, Dictionary labelIndices, ref int nextIndex) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) cartLabelCandidateBuffer.Clear(); foreach (PhysGrabCart cart in carts) { if (!((Object)(object)cart == (Object)null) && IsSmallCartObject(cart) == targetSmallCart) { int instanceID = ((Object)cart).GetInstanceID(); if (!labelIndices.ContainsKey(instanceID)) { cartLabelCandidateBuffer.Add(new CartLabelCandidate { Id = instanceID, Position = GetCartReferencePosition(cart) }); } } } cartLabelCandidateBuffer.Sort(CompareCartLabelCandidate); foreach (CartLabelCandidate item in cartLabelCandidateBuffer) { labelIndices[item.Id] = nextIndex++; } } private static int CompareCartLabelCandidate(CartLabelCandidate left, CartLabelCandidate right) { //IL_000d: 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) int num = left.Position.x.CompareTo(right.Position.x); if (num != 0) { return num; } int num2 = left.Position.z.CompareTo(right.Position.z); if (num2 == 0) { return left.Id.CompareTo(right.Id); } return num2; } private int GetOrCreateCartLabelIndex(PhysGrabCart cart, bool isSmallCart) { if ((Object)(object)cart == (Object)null) { return 0; } Dictionary obj = (isSmallCart ? smallCartLabelIndices : largeCartLabelIndices); int instanceID = ((Object)cart).GetInstanceID(); if (!obj.TryGetValue(instanceID, out var value)) { if (isSmallCart) { value = nextSmallCartLabelIndex++; smallCartLabelIndices[instanceID] = value; } else { value = nextLargeCartLabelIndex++; largeCartLabelIndices[instanceID] = value; } } return value; } private string GetCartDisplayName(PhysGrabCart cart, bool isSmallCart) { string arg = ((CurrentLanguage != DisplayLanguage.English) ? (isSmallCart ? "小购物车" : "购物车") : (isSmallCart ? "Small Cart" : "Cart")); return $"{arg}{GetOrCreateCartLabelIndex(cart, isSmallCart)}"; } private Vector3 GetCartReferencePosition(PhysGrabCart cart) { //IL_0009: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0077: 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_009a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cart == (Object)null) { return Vector3.zero; } Component physGrabObjectComponent = GetCartComponents(cart).PhysGrabObjectComponent; Vector3 anchorPosition = (((Object)(object)physGrabObjectComponent == (Object)null) ? ((Component)cart).transform.position : physGrabObjectComponent.transform.position); cartBoundsRootBuffer[0] = physGrabObjectComponent; cartBoundsRootBuffer[1] = (Component)(object)cart; if (TryGetObjectCenterNear(cartBoundsRootBuffer, anchorPosition, 4f, out var centerPosition)) { cartBoundsRootBuffer[0] = null; cartBoundsRootBuffer[1] = null; return centerPosition; } cartBoundsRootBuffer[0] = null; cartBoundsRootBuffer[1] = null; if ((Object)(object)physGrabObjectComponent != (Object)null) { return physGrabObjectComponent.transform.position; } return ((Component)cart).transform.position; } private Vector3 GetCartLabelPosition(PhysGrabCart cart, Vector3 referencePosition) { //IL_0025: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) Component physGrabObjectComponent = GetCartComponents(cart).PhysGrabObjectComponent; cartBoundsRootBuffer[0] = (Component)(object)cart; cartBoundsRootBuffer[1] = physGrabObjectComponent; if (TryGetObjectVisualBottomNear(cartBoundsRootBuffer, referencePosition, 4f, out var bottomPosition) || TryGetObjectBottomNear(cartBoundsRootBuffer, referencePosition, 4f, out bottomPosition)) { cartBoundsRootBuffer[0] = null; cartBoundsRootBuffer[1] = null; return bottomPosition; } cartBoundsRootBuffer[0] = null; cartBoundsRootBuffer[1] = null; return referencePosition; } private float GetCachedCartLabelYOffset(PhysGrabCart cart, Vector3 referencePosition) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cart == (Object)null) { return 0f; } int instanceID = ((Object)cart).GetInstanceID(); float time = Time.time; if (cartLabelYOffsetCache.TryGetValue(instanceID, out var value) && time - value.UpdatedAt <= 0.6f) { return value.YOffset; } float num = GetCartLabelPosition(cart, referencePosition).y - referencePosition.y; cartLabelYOffsetCache[instanceID] = new LabelYOffsetCache { YOffset = num, UpdatedAt = time }; return num; } private bool IsCartBeingPushed(PhysGrabCart cart, List grabbers) { if ((Object)(object)cart == (Object)null) { return false; } PhysGrabObject physGrabObject = GetCartComponents(cart).PhysGrabObject; if ((Object)(object)physGrabObject == (Object)null) { return false; } List playerGrabbing = physGrabObject.playerGrabbing; if (playerGrabbing != null) { foreach (PhysGrabber item in playerGrabbing) { if (IsLiveGrabberObject(item)) { return true; } } } if (GetCartBeingPulledFast(cart)) { return true; } if (IsActiveCartState(GetCartStateFast(cart))) { return true; } if (physGrabObject.grabbed) { return true; } if (grabbers != null && grabbers.Count > 0) { foreach (PhysGrabber grabber in grabbers) { if (!((Object)(object)grabber == (Object)null) && GetGrabberHeldObjectFast(grabber) == physGrabObject) { bool grabbed = grabber.grabbed; bool grabberIsPushingFast = GetGrabberIsPushingFast(grabber); bool grabberIsPullingFast = GetGrabberIsPullingFast(grabber); if (grabbed || grabberIsPushingFast || grabberIsPullingFast) { return true; } } } } return false; } private static bool IsActiveCartState(State? state) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Invalid comparison between Unknown and I4 //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 if (!state.HasValue) { return false; } if ((int)state.Value != 1) { return (int)state.Value == 2; } return true; } private static bool IsLiveGrabberObject(object playerGrabber) { if (playerGrabber == null) { return false; } Behaviour val = (Behaviour)((playerGrabber is Behaviour) ? playerGrabber : null); if (val != null) { return val.isActiveAndEnabled; } Component val2 = (Component)((playerGrabber is Component) ? playerGrabber : null); if (val2 != null) { if ((Object)(object)val2.gameObject != (Object)null) { return val2.gameObject.activeInHierarchy; } return false; } return true; } private static string BuildExplorationProgressLine(DisplayLanguage language, int progress) { return $"{HudText.ExplorationProgress(language)}: {Mathf.Clamp(progress, 0, 100)}%"; } private static string BuildUnextractedFundsLine(DisplayLanguage language, float value) { return HudText.UnextractedFunds(language) + ": " + FormatMoney(value); } private static float CalculateUnextractedFunds(float initialMapValue, int explorationProgressPercent, float unexploredMapValue, bool hasLiveValuableData) { if (initialMapValue <= 0f) { return 0f; } if (hasLiveValuableData) { return Mathf.Clamp(unexploredMapValue, 0f, initialMapValue); } float num = Mathf.Clamp(100f - (float)explorationProgressPercent, 0f, 100f) / 100f; return Mathf.Clamp(initialMapValue * num, 0f, initialMapValue); } private static float CalculateRemainingMapValue(float fallbackMapValue, List valuables, HashSet haulObjects) { if (!TryGetRemainingMapValue(valuables, haulObjects, out var remainingValue)) { return Mathf.Max(0f, fallbackMapValue); } return Mathf.Max(0f, remainingValue); } private static bool TryGetRemainingMapValue(List valuables, HashSet haulObjects, out float remainingValue) { remainingValue = 0f; if (valuables == null || valuables.Count == 0) { return false; } haulObjects = haulObjects ?? EmptyReferenceSet; bool result = false; foreach (ValuableObject valuable in valuables) { if (!((Object)(object)valuable == (Object)null) && IsValuableReady(valuable)) { result = true; PhysGrabObject valuablePhysGrabObjectFast = GetValuablePhysGrabObjectFast(valuable); if (!IsValuableMarkedInHaul(GetValuableKey(valuable)) && !IsValuableInReferenceSet(valuable, valuablePhysGrabObjectFast, haulObjects)) { remainingValue += GetValuableCurrentValueFast(valuable); } } } return result; } private static int CalculateExplorationProgress(float mapValue, float initialMapValue, List valuables, HashSet haulObjects, HashSet cartObjects, out float unexploredValue, out bool hasLiveValuableData) { if (initialMapValue <= 0f) { unexploredValue = 0f; hasLiveValuableData = false; return 0; } hasLiveValuableData = TryGetUnexploredMapValue(valuables, haulObjects, cartObjects, out unexploredValue); float num2; if (!hasLiveValuableData) { float num = Mathf.Clamp(mapValue / initialMapValue * 100f, 0f, 100f); num2 = 100f - num; } else { float num3 = Mathf.Clamp(unexploredValue / initialMapValue * 100f, 0f, 100f); num2 = 100f - num3; } return Mathf.RoundToInt(Mathf.Clamp(num2, 0f, 100f)); } private static bool TryGetUnexploredMapValue(List valuables, HashSet haulObjects, HashSet cartObjects, out float unexploredValue) { unexploredValue = 0f; if (valuables == null || valuables.Count == 0) { return false; } haulObjects = haulObjects ?? EmptyReferenceSet; cartObjects = cartObjects ?? EmptyReferenceSet; bool result = false; foreach (ValuableObject valuable in valuables) { if (!((Object)(object)valuable == (Object)null) && IsValuableReady(valuable)) { result = true; PhysGrabObject valuablePhysGrabObjectFast = GetValuablePhysGrabObjectFast(valuable); if (!IsValuableInReferenceSet(valuable, valuablePhysGrabObjectFast, haulObjects) && !IsValuableInReferenceSet(valuable, valuablePhysGrabObjectFast, cartObjects)) { unexploredValue += GetValuableCurrentValueFast(valuable); } } } return result; } private static string BuildMapValueLine(DisplayLanguage language, float mapValue) { return HudText.MapTotalValue(language) + ": " + FormatMoney(mapValue); } private static bool IsPlayerAlive(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return false; } int frameCount = Time.frameCount; if (playerAliveFrameCacheFrame != frameCount) { playerAliveFrameCacheFrame = frameCount; PlayerAliveFrameCache.Clear(); } int instanceID = ((Object)player).GetInstanceID(); if (PlayerAliveFrameCache.TryGetValue(instanceID, out var value)) { return value; } bool flag = IsPlayerAliveUncached(player); PlayerAliveFrameCache[instanceID] = flag; return flag; } private static bool IsPlayerAliveUncached(PlayerAvatar player) { bool playerDeadSetFast = GetPlayerDeadSetFast(player); bool playerIsDisabledFast = GetPlayerIsDisabledFast(player); if (!playerDeadSetFast && !playerIsDisabledFast) { return true; } if (HasPlayerDeathMarker(player)) { return false; } Transform playerTransform; return TryGetPlayerLiveTransform(player, requireActive: true, out playerTransform); } private static PlayerAvatar GetLocalPlayer(List players) { int frameCount = Time.frameCount; if (cachedLocalPlayerFrame == frameCount) { return cachedLocalPlayer; } cachedLocalPlayerFrame = frameCount; cachedLocalPlayer = null; PlayerAvatar val = null; if (players != null) { foreach (PlayerAvatar player in players) { if (!((Object)(object)player == (Object)null)) { if ((Object)(object)val == (Object)null) { val = player; } if (GetPlayerIsLocalFast(player)) { cachedLocalPlayer = player; return cachedLocalPlayer; } } } } PlayerAvatar instance = PlayerAvatar.instance; if ((Object)(object)instance != (Object)null) { cachedLocalPlayer = instance; return cachedLocalPlayer; } cachedLocalPlayer = val; return cachedLocalPlayer; } private void FillVehicleDistanceInfos(List result) { //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_009c: 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_01b9: 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_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) if (result == null) { return; } result.Clear(); if (!TryGetEnemyDistanceOrigin(out var origin)) { return; } EnsureVehicleLabelIndexLevel(); activeVehicleBuffer.Clear(); foreach (ItemVehicle trackedVehicle in trackedVehicles) { if (ShouldDisplayVehicle(trackedVehicle)) { activeVehicleBuffer.Add(trackedVehicle); } } foreach (ItemVehicle item in activeVehicleBuffer) { bool vehicleIsRacingFast = GetVehicleIsRacingFast(item); bool vehicleHasRider = GetVehicleHasRider(item); Vector3 position = ((Component)item).transform.position; float num = Vector3.Distance(origin, position); int num2 = Mathf.RoundToInt(num); int orCreateVehicleLabelIndex = GetOrCreateVehicleLabelIndex(item); string vehicleDisplayName = GetVehicleDisplayName(item, vehicleIsRacingFast, orCreateVehicleLabelIndex); string text = (vehicleHasRider ? "44ff66" : "ffd84d"); string text2 = vehicleDisplayName; string text3 = $"{text2} {num2}m"; MoreUiVehicleDistance pooledVehicleDistanceInfo = GetPooledVehicleDistanceInfo(result.Count); pooledVehicleDistanceInfo.Name = vehicleDisplayName; pooledVehicleDistanceInfo.Index = orCreateVehicleLabelIndex; pooledVehicleDistanceInfo.IsRacingVehicle = vehicleIsRacingFast; pooledVehicleDistanceInfo.DistanceMeters = num2; pooledVehicleDistanceInfo.DistanceValue = num; pooledVehicleDistanceInfo.HasRider = vehicleHasRider; pooledVehicleDistanceInfo.ColorHex = text; pooledVehicleDistanceInfo.PlainTextNoDistance = text2; pooledVehicleDistanceInfo.PlainText = text3; pooledVehicleDistanceInfo.RichTextNoDistance = "" + text2 + ""; pooledVehicleDistanceInfo.RichText = "" + text3 + ""; pooledVehicleDistanceInfo.LabelPosition = position + Vector3.up * -0.5f; result.Add(pooledVehicleDistanceInfo); } } private MoreUiVehicleDistance GetPooledVehicleDistanceInfo(int index) { while (vehicleDistancePool.Count <= index) { vehicleDistancePool.Add(new MoreUiVehicleDistance()); } return vehicleDistancePool[index]; } private bool ShouldDisplayVehicle(ItemVehicle v) { if ((Object)(object)v == (Object)null || (Object)(object)((Component)v).gameObject == (Object)null || !((Component)v).gameObject.activeInHierarchy) { return false; } if (vehicleSectionEnabled != null && !vehicleSectionEnabled.Value) { return false; } if (!GetVehicleIsRacingFast(v)) { if (vehicleOverlayEnabled != null) { return vehicleOverlayEnabled.Value; } return false; } if (racingVehicleOverlayEnabled != null) { return racingVehicleOverlayEnabled.Value; } return false; } private void EnsureVehicleLabelIndexLevel() { int num = SemiFunc.RunGetLevelsCompleted() + 1; if (vehicleLabelIndexLevelNumber != num) { vehicleLabelIndexLevelNumber = num; vehicleLabelIndices.Clear(); nextVehicleLabelIndex = 1; } } private int GetOrCreateVehicleLabelIndex(ItemVehicle v) { if ((Object)(object)v == (Object)null) { return 0; } int instanceID = ((Object)v).GetInstanceID(); if (!vehicleLabelIndices.TryGetValue(instanceID, out var value)) { value = nextVehicleLabelIndex++; vehicleLabelIndices[instanceID] = value; } return value; } private string GetVehicleDisplayName(ItemVehicle v, bool isRacing, int idx) { bool flag = UseChinese(); string arg = ((!isRacing) ? (flag ? "载货车" : "Cargo") : (flag ? "赛车" : "Kart")); return $"{arg}{idx}"; } private static string UnknownPlayerLabel() { if (!UseChinese()) { return "Unknown Player"; } return "未知玩家"; } private string GetCachedPlayerName(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return UnknownPlayerLabel(); } int frameCount = Time.frameCount; if (playerNameCacheFrame != frameCount) { playerNameCacheFrame = frameCount; playerNameCache.Clear(); } int instanceID = ((Object)player).GetInstanceID(); if (playerNameCache.TryGetValue(instanceID, out var value)) { return value; } string playerName = GetPlayerName(player); playerNameCache[instanceID] = playerName; return playerName; } private string GetCachedPlayerColorHex(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return "ffffff"; } int instanceID = ((Object)player).GetInstanceID(); int playerHeadTopColorIndex = GetPlayerHeadTopColorIndex(player); float unscaledTime = Time.unscaledTime; if (playerHeadTopColorIndex >= 0 && playerColorCache.TryGetValue(instanceID, out var value) && value.ColorIndex == playerHeadTopColorIndex && unscaledTime - value.UpdatedAt <= 0.2f && !string.IsNullOrWhiteSpace(value.ColorHex)) { return value.ColorHex; } string playerHeadTopColorHex = GetPlayerHeadTopColorHex(player); if (playerHeadTopColorIndex >= 0) { playerColorCache[instanceID] = new PlayerColorCacheEntry { ColorIndex = playerHeadTopColorIndex, ColorHex = playerHeadTopColorHex, UpdatedAt = unscaledTime }; } if (!string.IsNullOrWhiteSpace(playerHeadTopColorHex)) { return playerHeadTopColorHex; } return "ffffff"; } private static string GetPlayerName(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return UnknownPlayerLabel(); } string playerInternalNameFast = GetPlayerInternalNameFast(player); if (!string.IsNullOrWhiteSpace(playerInternalNameFast)) { return playerInternalNameFast.Trim(); } try { PhotonView photonView = player.photonView; object obj; if (photonView == null) { obj = null; } else { Player owner = photonView.Owner; obj = ((owner != null) ? owner.NickName : null); } string text = (string)obj; if (!string.IsNullOrWhiteSpace(text)) { return text.Trim(); } } catch { } try { string text2 = SemiFunc.PlayerGetName(player); if (!string.IsNullOrWhiteSpace(text2)) { return text2.Trim(); } } catch { } if (!string.IsNullOrWhiteSpace(((Object)player).name)) { return ((Object)player).name.Replace("(Clone)", string.Empty).Trim(); } return UnknownPlayerLabel(); } private static string GetPlayerHeadTopColorHex(PlayerAvatar player) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (TryGetPlayerHeadTopColor(player, out var color)) { color.a = 1f; return ColorUtility.ToHtmlStringRGB(color).ToLowerInvariant(); } return "ffffff"; } private static bool TryGetPlayerHeadTopColor(PlayerAvatar player, out Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) color = Color.white; if ((Object)(object)player == (Object)null) { return false; } try { color = SemiFunc.PlayerGetColorMain(player); return color.a > 0.01f; } catch { return false; } } private static int GetPlayerHeadTopColorIndex(PlayerAvatar player) { if ((Object)(object)player == (Object)null || (Object)(object)player.playerCosmetics == (Object)null) { return -1; } try { int[] playerCosmeticsColorsFast = GetPlayerCosmeticsColorsFast(player.playerCosmetics); if (playerCosmeticsColorsFast != null && playerCosmeticsColorsFast.Length > 5) { return playerCosmeticsColorsFast[5]; } } catch { } return -1; } private static Vector3 GetPlayerDistanceOrigin(PlayerAvatar localPlayer, bool localAlive) { //IL_0009: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)localPlayer == (Object)null) { return Vector3.zero; } if (localAlive) { return GetPlayerReferencePosition(localPlayer, preferDeathPosition: false); } if (TryGetSpectateOrigin(localPlayer, out var position)) { return position; } return GetPlayerReferencePosition(localPlayer, preferDeathPosition: true); } private static bool TryGetSpectateOrigin(PlayerAvatar localPlayer, 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_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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; SpectateCamera instance = SpectateCamera.instance; if ((Object)(object)instance == (Object)null) { return TryGetMainCameraPosition(out position); } PlayerAvatar val = GetSpectateCameraPlayerOverrideFast(instance) ?? GetSpectateCameraPlayerFast(instance); if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)localPlayer && IsPlayerAlive(val)) { position = GetPlayerReferencePosition(val, preferDeathPosition: false); return true; } Camera spectateCameraMainCameraFast = GetSpectateCameraMainCameraFast(instance); if ((Object)(object)spectateCameraMainCameraFast != (Object)null) { position = ((Component)spectateCameraMainCameraFast).transform.position; return true; } return TryGetMainCameraPosition(out position); } private static bool TryGetMainCameraPosition(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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) position = Vector3.zero; Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return false; } position = ((Component)main).transform.position; return true; } private static Vector3 GetPlayerReferencePosition(PlayerAvatar player, bool preferDeathPosition) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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_0104: 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_00cd: 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_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return Vector3.zero; } int key = ((Object)player).GetInstanceID() ^ (preferDeathPosition ? 1 : 0); float time = Time.time; Plugin instance = Instance; if ((Object)(object)instance != (Object)null && instance.playerPositionCache.TryGetValue(key, out var value) && time - value.UpdatedAt <= 0.15f) { return value.Position; } if (!preferDeathPosition) { goto IL_0108; } PlayerDeathHead playerDeathHeadFast = GetPlayerDeathHeadFast(player); Vector3 val; if ((Object)(object)playerDeathHeadFast != (Object)null) { PhysGrabObject deathHeadPhysGrabObjectFast = GetDeathHeadPhysGrabObjectFast(playerDeathHeadFast); if ((Object)(object)deathHeadPhysGrabObjectFast != (Object)null) { val = ((Component)deathHeadPhysGrabObjectFast).transform.position; } else { Transform deathHeadOverridePositionTransformFast = GetDeathHeadOverridePositionTransformFast(playerDeathHeadFast); val = (((Object)(object)deathHeadOverridePositionTransformFast != (Object)null) ? deathHeadOverridePositionTransformFast.position : ((!TryGetDeathHeadTriggeredPositionFast(playerDeathHeadFast, out var position)) ? ((Component)playerDeathHeadFast).transform.position : position)); } } else if ((Object)(object)player.deathSpot != (Object)null) { val = player.deathSpot.transform.position; } else { if (!TryGetPlayerLastNavmeshPositionFast(player, out var position2)) { goto IL_0108; } val = position2; } goto IL_0139; IL_0139: if ((Object)(object)instance != (Object)null) { instance.playerPositionCache[key] = new PlayerPositionCache { Position = val, UpdatedAt = time }; } return val; IL_0108: val = ((!TryGetPlayerLiveTransform(player, !preferDeathPosition, out var playerTransform) && !TryGetPlayerLiveTransform(player, requireActive: false, out playerTransform)) ? ((Component)player).transform.position : playerTransform.position); goto IL_0139; } private static Vector3 GetPlayerNameLabelPosition(PlayerAvatar player, bool preferDeathPosition) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_002f: Unknown result type (might be due to invalid IL or missing references) if (!preferDeathPosition && TryGetAlivePlayerNameLabelPosition(player, out var labelPosition)) { return labelPosition; } return GetPlayerReferencePosition(player, preferDeathPosition) + Vector3.up * (preferDeathPosition ? 0.35f : 2f); } private static bool TryGetAlivePlayerNameLabelPosition(PlayerAvatar player, out Vector3 labelPosition) { //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_004b: 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) labelPosition = Vector3.zero; if ((Object)(object)player == (Object)null) { return false; } PlayerAvatarVisuals playerAvatarVisuals = player.playerAvatarVisuals; if ((Object)(object)playerAvatarVisuals == (Object)null || !IsUsableTransform(((Component)playerAvatarVisuals).transform, requireActive: true) || !IsUsableTransform(playerAvatarVisuals.headLookAtTransform, requireActive: true)) { return false; } labelPosition = playerAvatarVisuals.headLookAtTransform.position; labelPosition.y += 0.35f; if ((Object)(object)SessionManager.instance != (Object)null && player == SessionManager.instance.CrownedPlayerGet()) { labelPosition.y += 0.02f; } return true; } private static bool HasPlayerDeathMarker(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return false; } PlayerDeathHead playerDeathHeadFast = GetPlayerDeathHeadFast(player); if ((Object)(object)playerDeathHeadFast != (Object)null && (Object)(object)playerDeathHeadFast != (Object)null && IsUsableTransform(((Component)playerDeathHeadFast).transform, requireActive: true)) { return true; } if ((Object)(object)player.deathSpot != (Object)null && IsUsableTransform(player.deathSpot.transform, requireActive: true)) { return true; } return false; } private static bool TryGetPlayerLiveTransform(PlayerAvatar player, bool requireActive, out Transform playerTransform) { playerTransform = null; if ((Object)(object)player == (Object)null) { return false; } if (IsUsableTransform(player.playerTransform, requireActive)) { playerTransform = player.playerTransform; return true; } if (IsUsableTransform(((Component)player).transform, requireActive)) { playerTransform = ((Component)player).transform; return true; } return false; } private static bool IsUsableTransform(Transform transform, bool requireActive) { //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)transform == (Object)null) && !((Object)(object)((Component)transform).gameObject == (Object)null)) { Scene scene = ((Component)transform).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { if (requireActive) { return ((Component)transform).gameObject.activeInHierarchy; } return true; } } return false; } private static Vector3 GetEnemyReferencePosition(Enemy enemy) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Transform enemyReferenceTransform = GetEnemyReferenceTransform(enemy); if (!((Object)(object)enemyReferenceTransform == (Object)null)) { return enemyReferenceTransform.position; } return Vector3.zero; } private static Transform GetEnemyReferenceTransform(Enemy enemy) { Transform enemyCenterTransform = GetEnemyCenterTransform(enemy); if ((Object)(object)enemyCenterTransform != (Object)null) { return enemyCenterTransform; } Component enemyRootComponent = GetEnemyRootComponent(enemy); if ((Object)(object)enemyRootComponent != (Object)null) { return enemyRootComponent.transform; } Component enemyParentComponent = GetEnemyParentComponent(enemy); if (!((Object)(object)enemyParentComponent == (Object)null)) { return enemyParentComponent.transform; } return null; } private static bool TryGetObjectBoundsNear(IEnumerable roots, Vector3 anchorPosition, float maxHorizontalDistance, bool useColliders, BoundsPosition positionType, out Vector3 result) { //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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) result = Vector3.zero; if (!TryCollectBoundsNear(roots, anchorPosition, maxHorizontalDistance, useColliders, out var bounds)) { return false; } result = (Vector3)(positionType switch { BoundsPosition.Center => ((Bounds)(ref bounds)).center, BoundsPosition.Bottom => new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).center.z), _ => ((Bounds)(ref bounds)).center, }); return true; } private static bool TryGetObjectCenterNear(IEnumerable roots, Vector3 anchorPosition, float maxHorizontalDistance, out Vector3 centerPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (TryGetObjectBoundsNear(roots, anchorPosition, maxHorizontalDistance, useColliders: false, BoundsPosition.Center, out centerPosition)) { return true; } return TryGetObjectBoundsNear(roots, anchorPosition, maxHorizontalDistance, useColliders: true, BoundsPosition.Center, out centerPosition); } private static bool TryGetObjectVisualBottomNear(IEnumerable roots, Vector3 anchorPosition, float maxHorizontalDistance, out Vector3 bottomPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return TryGetObjectBoundsNear(roots, anchorPosition, maxHorizontalDistance, useColliders: false, BoundsPosition.Bottom, out bottomPosition); } private static bool TryGetObjectBottomNear(IEnumerable roots, Vector3 anchorPosition, float maxHorizontalDistance, out Vector3 bottomPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return TryGetObjectBoundsNear(roots, anchorPosition, maxHorizontalDistance, useColliders: true, BoundsPosition.Bottom, out bottomPosition); } private static bool TryCollectBoundsNear(IEnumerable roots, Vector3 anchorPosition, float maxHorizontalDistance, bool useColliders, out Bounds bounds) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); if (roots == null) { return false; } bool hasBounds = false; HashSet boundsVisitedBuffer = BoundsVisitedBuffer; boundsVisitedBuffer.Clear(); float maxDistanceSquared = maxHorizontalDistance * maxHorizontalDistance; foreach (Component root in roots) { if ((Object)(object)root == (Object)null || (Object)(object)root.gameObject == (Object)null) { continue; } Scene scene = root.gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { continue; } int instanceID = ((Object)root.gameObject).GetInstanceID(); if (!boundsVisitedBuffer.Add(instanceID)) { continue; } Renderer[] childRenderers = GetChildRenderers(root); foreach (Renderer val in childRenderers) { if ((Object)(object)val != (Object)null && val.enabled && IsBoundsNear(val.bounds, anchorPosition, maxDistanceSquared)) { EncapsulateBounds(ref bounds, ref hasBounds, val.bounds); } } if (!useColliders) { continue; } Collider[] childColliders = GetChildColliders(root); foreach (Collider val2 in childColliders) { if ((Object)(object)val2 != (Object)null && val2.enabled && IsBoundsNear(val2.bounds, anchorPosition, maxDistanceSquared)) { EncapsulateBounds(ref bounds, ref hasBounds, val2.bounds); } } } boundsVisitedBuffer.Clear(); return hasBounds; } private static bool IsBoundsNear(Bounds bounds, Vector3 anchorPosition, float maxDistanceSquared) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_001f: 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_0030: 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_0036: Unknown result type (might be due to invalid IL or missing references) Vector2 val = new Vector2(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).center.z); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(anchorPosition.x, anchorPosition.z); Vector2 val3 = val - val2; return ((Vector2)(ref val3)).sqrMagnitude <= maxDistanceSquared; } private static Renderer[] GetChildRenderers(Component root) { if ((Object)(object)root == (Object)null || (Object)(object)root.gameObject == (Object)null) { return Array.Empty(); } int instanceID = ((Object)root.gameObject).GetInstanceID(); if (!CachedChildRenderers.TryGetValue(instanceID, out var value)) { BoundsRendererBuffer.Clear(); root.GetComponentsInChildren(false, BoundsRendererBuffer); value = ((BoundsRendererBuffer.Count == 0) ? Array.Empty() : BoundsRendererBuffer.ToArray()); CachedChildRenderers[instanceID] = value; BoundsRendererBuffer.Clear(); } return value; } private static Collider[] GetChildColliders(Component root) { if ((Object)(object)root == (Object)null || (Object)(object)root.gameObject == (Object)null) { return Array.Empty(); } int instanceID = ((Object)root.gameObject).GetInstanceID(); if (!CachedChildColliders.TryGetValue(instanceID, out var value)) { BoundsColliderBuffer.Clear(); root.GetComponentsInChildren(false, BoundsColliderBuffer); value = ((BoundsColliderBuffer.Count == 0) ? Array.Empty() : BoundsColliderBuffer.ToArray()); CachedChildColliders[instanceID] = value; BoundsColliderBuffer.Clear(); } return value; } private static void ClearCachedBoundsComponentData() { CachedChildRenderers.Clear(); CachedChildColliders.Clear(); } private static void EncapsulateBounds(ref Bounds bounds, ref bool hasBounds, Bounds nextBounds) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!hasBounds) { bounds = nextBounds; hasBounds = true; } else { ((Bounds)(ref bounds)).Encapsulate(nextBounds); } } private static Component GetEnemyRootComponent(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return null; } return (Component)(object)enemy; } private static Transform GetEnemyCenterTransform(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return null; } return enemy.CenterTransform; } private static Component GetEnemyParentComponent(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return null; } return (Component)(object)GetEnemyParentFast(enemy); } private static bool IsEnemyCountable(Enemy enemy) { //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)enemy == (Object)null) && !((Object)(object)((Component)enemy).gameObject == (Object)null)) { Scene scene = ((Component)enemy).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { EnemyHealth enemyHealthFast = GetEnemyHealthFast(enemy); if ((Object)(object)enemyHealthFast != (Object)null && GetEnemyHealthDeadFast(enemyHealthFast)) { return false; } EnemyParent enemyParentFast = GetEnemyParentFast(enemy); if ((Object)(object)enemyParentFast != (Object)null && !GetEnemyParentSpawnedFast(enemyParentFast)) { return false; } return true; } } return false; } private string GetCachedEnemyDisplayName(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return GetEnemyDisplayName(enemy); } DisplayLanguage currentLanguage = CurrentLanguage; bool useEnemyNicknameNames = UseEnemyNicknameNames; if (!hasCachedEnemyDisplayNameLanguage || cachedEnemyDisplayNameLanguage != currentLanguage || cachedEnemyNicknameEnabled != useEnemyNicknameNames) { enemyDisplayNameCache.Clear(); cachedEnemyDisplayNameLanguage = currentLanguage; cachedEnemyNicknameEnabled = useEnemyNicknameNames; hasCachedEnemyDisplayNameLanguage = true; } int enemyKey = GetEnemyKey(enemy); if (enemyDisplayNameCache.TryGetValue(enemyKey, out var value)) { return value; } string enemyDisplayName = GetEnemyDisplayName(enemy); enemyDisplayNameCache[enemyKey] = enemyDisplayName; return enemyDisplayName; } private string GetEnemyDisplayName(Enemy enemy) { if ((Object)(object)enemy == (Object)null) { return string.Empty; } EnemyParent enemyParentFast = GetEnemyParentFast(enemy); if ((Object)(object)enemyParentFast != (Object)null && TryGetEnemyParentDisplayName(enemyParentFast, out var name)) { return EnemyNameLocalizer.Translate(name, CurrentLanguage, UseEnemyNicknameNames); } string text = ((object)(EnemyType)(ref enemy.Type)).ToString(); if (!string.IsNullOrWhiteSpace(text)) { return EnemyNameLocalizer.Translate(text.Trim(), CurrentLanguage, UseEnemyNicknameNames); } if (!string.IsNullOrWhiteSpace(((Object)enemy).name)) { return EnemyNameLocalizer.Translate(((Object)enemy).name.Replace("(Clone)", string.Empty).Trim(), CurrentLanguage, UseEnemyNicknameNames); } return HudText.UnknownEnemy(CurrentLanguage); } private static bool TryGetEnemyParentDisplayName(EnemyParent parent, out string name) { name = string.Empty; if ((Object)(object)parent == (Object)null) { return false; } string enemyName = parent.enemyName; if (!IsInternalEnemyName(enemyName)) { name = enemyName.Trim(); return true; } LocalizedAsset enemyNameLocalized = parent.enemyNameLocalized; if ((Object)(object)enemyNameLocalized != (Object)null) { try { string localizedString = enemyNameLocalized.GetLocalizedString(); if (!string.IsNullOrWhiteSpace(localizedString) && !IsInternalEnemyName(localizedString)) { name = localizedString.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 static string FormatMoney(float value) { return "$" + Mathf.RoundToInt(value).ToString("N0", MoneyCulture); } private void SetNativeOverlayVisible(bool visible) { if ((Object)(object)overlayObject != (Object)null && overlayObject.activeSelf != visible) { overlayObject.SetActive(visible); } } private void OnGUI() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 if (!IsModEnabled()) { return; } Event current = Event.current; if (current == null || (int)current.type == 7) { if (overlayEnabled.Value && displayMode.Value == DisplayMode.文字显示 && !string.IsNullOrEmpty(overlayText)) { DrawMainTextOverlay(); } if (ShouldDrawCartWorldLabels()) { DrawCartWorldLabels(); } if (ShouldDrawVehicleWorldLabels()) { DrawVehicleWorldLabels(); } if (ShouldDrawTeammateWorldLabels()) { DrawTeammateWorldLabels(); } } } private bool ShouldDrawCartWorldLabels() { if (IsModEnabled() && IsCartFeatureEnabled()) { return IsRuntimeSessionActive(); } return false; } private bool ShouldDrawVehicleWorldLabels() { if (IsModEnabled() && IsVehicleFeatureEnabled()) { return IsRuntimeSessionActive(); } return false; } private bool ShouldDrawTeammateWorldLabels() { if (!IsModEnabled() || !IsRuntimeSessionActive()) { return false; } if (teammateOverlayEnabled == null || !teammateOverlayEnabled.Value) { return false; } bool num = teammateDeadOverlayEnabled != null && teammateDeadOverlayEnabled.Value; bool flag = teammateAliveOverlayEnabled != null && teammateAliveOverlayEnabled.Value; return num || flag; } private void DrawMainTextOverlay() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) int overlayFontSize = Mathf.Clamp(fontSize.Value, 10, 28); GUIStyle overlayLabelStyle = GetOverlayLabelStyle(overlayFontSize, shadow: false); GUIStyle overlayLabelStyle2 = GetOverlayLabelStyle(overlayFontSize, shadow: true); EnsureTextOverlayLayout(overlayLabelStyle, overlayFontSize); GUI.Label(cachedTextOverlayShadowRect, cachedTextOverlayPlainText, overlayLabelStyle2); GUI.Label(cachedTextOverlayRect, overlayText, overlayLabelStyle); } private void EnsureTextOverlayLayout(GUIStyle mainStyle, int overlayFontSize) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) bool flag = showBreakdown != null && showBreakdown.Value; int num = ((overlayOffsetX != null) ? overlayOffsetX.Value : 0); int num2 = ((overlayOffsetY != null) ? overlayOffsetY.Value : 0); if (!string.Equals(lastTextOverlaySource, overlayText, StringComparison.Ordinal) || lastTextOverlayFontSize != overlayFontSize || lastTextOverlayShowBreakdown != flag || lastTextOverlayOffsetX != num || lastTextOverlayOffsetY != num2 || lastTextOverlayScreenWidth != Screen.width || lastTextOverlayScreenHeight != Screen.height) { cachedTextOverlayWidth = (flag ? 430f : 320f); float num3 = CalcLabelHeight(mainStyle, overlayText, cachedTextOverlayWidth); float num4 = (float)Screen.width - cachedTextOverlayWidth - 12f - (float)num; float num5 = (float)Screen.height - num3 - 26f - (float)num2; cachedTextOverlayRect = new Rect(num4, num5, cachedTextOverlayWidth, num3); cachedTextOverlayShadowRect = new Rect(num4 + 1f, num5 + 1f, cachedTextOverlayWidth, num3); cachedTextOverlayPlainText = GetPlainOverlayText(); lastTextOverlaySource = overlayText; lastTextOverlayFontSize = overlayFontSize; lastTextOverlayShowBreakdown = flag; lastTextOverlayOffsetX = num; lastTextOverlayOffsetY = num2; lastTextOverlayScreenWidth = Screen.width; lastTextOverlayScreenHeight = Screen.height; } } private string GetPlainOverlayText() { if (string.Equals(lastPlainOverlaySource, overlayText, StringComparison.Ordinal)) { return lastPlainOverlayText; } lastPlainOverlaySource = overlayText; lastPlainOverlayText = StripRichText(overlayText); return lastPlainOverlayText; } private void DrawCartWorldLabels() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) Camera worldLabelCamera = GetWorldLabelCamera(); if ((Object)(object)worldLabelCamera == (Object)null) { return; } List list = cartDistanceCache; if (list.Count == 0) { return; } int num = Mathf.Clamp((cartFontSize == null) ? 20 : cartFontSize.Value, 10, 36); float fullShrinkDistance = 20f; GUIStyle centeredLabelStyle = GetCenteredLabelStyle(num, shadow: false); GUIStyle centeredLabelStyle2 = GetCenteredLabelStyle(num, shadow: true); Rect val3 = default(Rect); foreach (MoreUiCartDistance item in list) { if (TryWorldToGuiPoint(worldLabelCamera, item.LabelPosition, out var guiPosition)) { int distanceScaledFontSize = GetDistanceScaledFontSize(num, 30f, item.DistanceValue, fullShrinkDistance, 42); GUIStyle val = ((distanceScaledFontSize == num) ? centeredLabelStyle : GetCenteredLabelStyle(distanceScaledFontSize, shadow: false)); GUIStyle val2 = ((distanceScaledFontSize == num) ? centeredLabelStyle2 : GetCenteredLabelStyle(distanceScaledFontSize, shadow: true)); string text = BuildCartWorldLabelPlainText(item); string text2 = "" + text + ""; Vector2 cachedCenteredLabelSize = GetCachedCenteredLabelSize(distanceScaledFontSize, text); float num2 = Mathf.Clamp(cachedCenteredLabelSize.x + 18f, 90f, 330f); float num3 = cachedCenteredLabelSize.y + 6f; float num4 = guiPosition.x - num2 / 2f; float num5 = guiPosition.y - num3 - 6f; ((Rect)(ref val3))..ctor(num4, num5, num2, num3); GUI.Label(new Rect(((Rect)(ref val3)).x + 1f, ((Rect)(ref val3)).y + 1f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), text, val2); GUI.Label(val3, text2, val); } } } private string BuildCartWorldLabelPlainText(MoreUiCartDistance cart) { if (cart == null) { return ""; } if (cartDistanceEnabled == null || !cartDistanceEnabled.Value) { return cart.PlainTextNoDistance; } return cart.PlainText; } private void DrawVehicleWorldLabels() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: 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) Camera worldLabelCamera = GetWorldLabelCamera(); if ((Object)(object)worldLabelCamera == (Object)null) { return; } List list = vehicleDistanceCache; if (list.Count == 0) { return; } int num = Mathf.Clamp((vehicleFontSize == null) ? 20 : vehicleFontSize.Value, 10, 36); float fullShrinkDistance = 20f; GUIStyle centeredLabelStyle = GetCenteredLabelStyle(num, shadow: false); GUIStyle centeredLabelStyle2 = GetCenteredLabelStyle(num, shadow: true); Rect val3 = default(Rect); foreach (MoreUiVehicleDistance item in list) { if (TryWorldToGuiPoint(worldLabelCamera, item.LabelPosition, out var guiPosition)) { int distanceScaledFontSize = GetDistanceScaledFontSize(num, 30f, item.DistanceValue, fullShrinkDistance, 42); GUIStyle val = ((distanceScaledFontSize == num) ? centeredLabelStyle : GetCenteredLabelStyle(distanceScaledFontSize, shadow: false)); GUIStyle val2 = ((distanceScaledFontSize == num) ? centeredLabelStyle2 : GetCenteredLabelStyle(distanceScaledFontSize, shadow: true)); string text = ((vehicleDistanceEnabled != null && vehicleDistanceEnabled.Value) ? item.PlainText : item.PlainTextNoDistance); string text2 = "" + text + ""; Vector2 cachedCenteredLabelSize = GetCachedCenteredLabelSize(distanceScaledFontSize, text); float num2 = Mathf.Clamp(cachedCenteredLabelSize.x + 18f, 90f, 330f); float num3 = cachedCenteredLabelSize.y + 6f; float num4 = guiPosition.x - num2 / 2f; float num5 = guiPosition.y - num3 - 6f; ((Rect)(ref val3))..ctor(num4, num5, num2, num3); GUI.Label(new Rect(((Rect)(ref val3)).x + 1f, ((Rect)(ref val3)).y + 1f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), text, val2); GUI.Label(val3, text2, val); } } } private void DrawTeammateWorldLabels() { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_017a: 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) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) Camera worldLabelCamera = GetWorldLabelCamera(); if ((Object)(object)worldLabelCamera == (Object)null) { return; } List list = CreateTeammateDistanceInfos(); if (list == null || list.Count == 0) { return; } bool flag = teammateDeadOverlayEnabled != null && teammateDeadOverlayEnabled.Value; bool flag2 = teammateAliveOverlayEnabled != null && teammateAliveOverlayEnabled.Value; bool flag3 = flag && teammateDeadEdgeOverlayEnabled != null && teammateDeadEdgeOverlayEnabled.Value; bool flag4 = flag2 && teammateAliveEdgeOverlayEnabled != null && teammateAliveEdgeOverlayEnabled.Value; leftEdgeTeammateLabelBuffer.Clear(); rightEdgeTeammateLabelBuffer.Clear(); Rect val = default(Rect); foreach (MoreUiPlayerDistance item in list) { if (item == null || item.IsLocalPlayer || (item.IsDead ? (!flag) : (!flag2))) { continue; } TeammateLabelLayout layout = BuildTeammateLabelLayout(item); if (!TryWorldToGuiPoint(worldLabelCamera, item.LabelPosition, out var guiPosition)) { if ((item.IsDead ? flag3 : flag4) && TryGetEdgeGuiPoint(worldLabelCamera, item.LabelPosition, out var guiPosition2, out var isLeftEdge)) { QueueTeammateEdgeLabel(item, layout, guiPosition2, isLeftEdge); } } else { float num = Mathf.Clamp(guiPosition.x - layout.Width / 2f, 4f, Mathf.Max(4f, (float)Screen.width - layout.Width - 4f)); float num2 = Mathf.Clamp(guiPosition.y - layout.Height - 2f, 4f, Mathf.Max(4f, (float)Screen.height - layout.Height - 4f)); ((Rect)(ref val))..ctor(num, num2, layout.Width, layout.Height); GUI.Label(new Rect(((Rect)(ref val)).x + 1f, ((Rect)(ref val)).y + 1f, ((Rect)(ref val)).width, ((Rect)(ref val)).height), layout.PlainText, layout.ShadowStyle); GUI.Label(val, layout.RichText, layout.LabelStyle); } } DrawTeammateEdgeLabels(leftEdgeTeammateLabelBuffer, leftEdgeTeammateRectBuffer, isLeftEdge: true); DrawTeammateEdgeLabels(rightEdgeTeammateLabelBuffer, rightEdgeTeammateRectBuffer, isLeftEdge: false); } private TeammateLabelLayout BuildTeammateLabelLayout(MoreUiPlayerDistance teammate) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) int distanceScaledFontSize = GetDistanceScaledFontSize(Mathf.Clamp(teammateFontSize.Value, 10, 60), 30f, teammate.DistanceValue, 20f, 60); bool showDistance = teammateDistanceEnabled != null && teammateDistanceEnabled.Value; string text = BuildTeammateWorldLabelPlainText(teammate, showDistance); string richText = BuildTeammateWorldLabelRichText(teammate, showDistance, text); float num = Mathf.Max(120f, (float)Screen.width - 8f); int num2 = distanceScaledFontSize; GUIStyle centeredLabelStyle = GetCenteredLabelStyle(num2, shadow: false); GUIStyle centeredLabelStyle2 = GetCenteredLabelStyle(num2, shadow: true); Vector2 cachedCenteredLabelSize = GetCachedCenteredLabelSize(num2, text); while (num2 > 10 && cachedCenteredLabelSize.x + 14f > num) { num2--; centeredLabelStyle = GetCenteredLabelStyle(num2, shadow: false); centeredLabelStyle2 = GetCenteredLabelStyle(num2, shadow: true); cachedCenteredLabelSize = GetCachedCenteredLabelSize(num2, text); } TeammateLabelLayout result = default(TeammateLabelLayout); result.PlainText = text; result.RichText = richText; result.Width = Mathf.Clamp(cachedCenteredLabelSize.x + 14f, 72f, num); result.Height = cachedCenteredLabelSize.y + 4f; result.LabelStyle = centeredLabelStyle; result.ShadowStyle = centeredLabelStyle2; return result; } private static string BuildTeammateWorldLabelPlainText(MoreUiPlayerDistance teammate, bool showDistance) { if (teammate == null) { return string.Empty; } if (!showDistance) { return teammate.PlainTextNoDistance; } return teammate.PlainText; } private static string BuildTeammateWorldLabelRichText(MoreUiPlayerDistance teammate, bool showDistance, string plainText) { if (teammate == null) { return string.Empty; } if (!showDistance) { return teammate.RichTextNoDistance; } return teammate.RichText; } private Vector2 GetCachedCenteredLabelSize(int fontSize, string text) { //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_0043: 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_0021: Unknown result type (might be due to invalid IL or missing references) LabelSizeCacheKey key = new LabelSizeCacheKey(Mathf.Clamp(fontSize, 8, 60), text); if (centeredLabelSizeCache.TryGetValue(key, out var value)) { return value; } value = CalcLabelSize(GetCenteredLabelStyle(key.FontSize, shadow: false), key.Text); centeredLabelSizeCache[key] = value; return value; } private void QueueTeammateEdgeLabel(MoreUiPlayerDistance teammate, TeammateLabelLayout layout, Vector2 guiPosition, bool isLeftEdge) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (teammate != null) { float preferredY = Mathf.Clamp(guiPosition.y - layout.Height / 2f, 4f, Mathf.Max(4f, (float)Screen.height - layout.Height - 4f)); TeammateEdgeLabelDrawInfo teammateEdgeLabelDrawInfo = default(TeammateEdgeLabelDrawInfo); teammateEdgeLabelDrawInfo.IsLeftEdge = isLeftEdge; teammateEdgeLabelDrawInfo.DistanceMeters = teammate.DistanceMeters; teammateEdgeLabelDrawInfo.PreferredY = preferredY; teammateEdgeLabelDrawInfo.Width = layout.Width; teammateEdgeLabelDrawInfo.Height = layout.Height; teammateEdgeLabelDrawInfo.PlainText = layout.PlainText; teammateEdgeLabelDrawInfo.RichText = layout.RichText; teammateEdgeLabelDrawInfo.LabelStyle = layout.LabelStyle; teammateEdgeLabelDrawInfo.ShadowStyle = layout.ShadowStyle; TeammateEdgeLabelDrawInfo item = teammateEdgeLabelDrawInfo; if (isLeftEdge) { leftEdgeTeammateLabelBuffer.Add(item); } else { rightEdgeTeammateLabelBuffer.Add(item); } } } private static void EnsureRectBufferCapacity(List rectBuffer, int count) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) while (rectBuffer.Count < count) { rectBuffer.Add(default(Rect)); } } private void DrawTeammateEdgeLabels(List labels, List rectBuffer, bool isLeftEdge) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) if (labels == null || labels.Count == 0) { return; } labels.Sort(CompareTeammateEdgeLabelInfo); EnsureRectBufferCapacity(rectBuffer, labels.Count); float num = 4f; float num2 = 0f; for (int i = 0; i < labels.Count; i++) { TeammateEdgeLabelDrawInfo teammateEdgeLabelDrawInfo = labels[i]; float num3 = (isLeftEdge ? 8f : Mathf.Max(8f, (float)Screen.width - teammateEdgeLabelDrawInfo.Width - 8f)); float num4 = Mathf.Max(teammateEdgeLabelDrawInfo.PreferredY, num); rectBuffer[i] = new Rect(num3, num4, teammateEdgeLabelDrawInfo.Width, teammateEdgeLabelDrawInfo.Height); num = num4 + teammateEdgeLabelDrawInfo.Height + 2f; num2 = Mathf.Max(num2, num - (float)Screen.height + 4f); } if (num2 > 0f) { for (int j = 0; j < labels.Count; j++) { Rect value = rectBuffer[j]; ((Rect)(ref value)).y = Mathf.Max(4f, ((Rect)(ref value)).y - num2); rectBuffer[j] = value; } } for (int k = 0; k < labels.Count; k++) { TeammateEdgeLabelDrawInfo teammateEdgeLabelDrawInfo2 = labels[k]; Rect val = rectBuffer[k]; GUI.Label(new Rect(((Rect)(ref val)).x + 1f, ((Rect)(ref val)).y + 1f, ((Rect)(ref val)).width, ((Rect)(ref val)).height), teammateEdgeLabelDrawInfo2.PlainText, teammateEdgeLabelDrawInfo2.ShadowStyle); GUI.Label(val, teammateEdgeLabelDrawInfo2.RichText, teammateEdgeLabelDrawInfo2.LabelStyle); } } private static int CompareTeammateEdgeLabelInfo(TeammateEdgeLabelDrawInfo left, TeammateEdgeLabelDrawInfo right) { int num = left.DistanceMeters.CompareTo(right.DistanceMeters); if (num != 0) { return num; } return left.PreferredY.CompareTo(right.PreferredY); } private static bool TryWorldToGuiPoint(Camera camera, Vector3 worldPosition, out Vector2 guiPosition, float margin = 80f) { //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_0017: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) guiPosition = Vector2.zero; if ((Object)(object)camera == (Object)null) { return false; } Vector3 val = camera.WorldToScreenPoint(worldPosition); if (val.z <= 0.05f) { return false; } float num = val.x; float num2 = val.y; RenderTexture targetTexture = camera.targetTexture; if ((Object)(object)targetTexture != (Object)null && ((Texture)targetTexture).width > 0 && ((Texture)targetTexture).height > 0) { num *= (float)Screen.width / (float)((Texture)targetTexture).width; num2 *= (float)Screen.height / (float)((Texture)targetTexture).height; } if (num < 0f - margin || num > (float)Screen.width + margin || num2 < 0f - margin || num2 > (float)Screen.height + margin) { return false; } guiPosition = new Vector2(num, (float)Screen.height - num2); return true; } private static bool TryGetEdgeGuiPoint(Camera camera, Vector3 worldPosition, out Vector2 guiPosition, out bool isLeftEdge) { //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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) guiPosition = Vector2.zero; isLeftEdge = false; if ((Object)(object)camera == (Object)null) { return false; } Vector3 val = camera.WorldToScreenPoint(worldPosition); bool flag = val.z <= 0.05f; float num = val.x; float num2 = val.y; if (flag) { num = (float)Screen.width - num; num2 = (float)Screen.height - num2; } float num3 = num; float num4 = (float)Screen.height - num2; bool flag2 = num3 >= 0f && num3 <= (float)Screen.width; bool flag3 = num4 >= 0f && num4 <= (float)Screen.height; if (!flag && flag2 && flag3) { return false; } isLeftEdge = num3 <= (float)Screen.width * 0.5f; guiPosition = new Vector2(isLeftEdge ? 0f : ((float)Screen.width), Mathf.Clamp(num4, 4f, Mathf.Max(4f, (float)Screen.height - 4f))); return true; } private static Camera GetWorldLabelCamera() { int frameCount = Time.frameCount; if (cachedWorldLabelCameraFrame == frameCount) { return cachedWorldLabelCamera; } Camera main = Camera.main; if ((Object)(object)main != (Object)null) { cachedWorldLabelCameraFrame = frameCount; cachedWorldLabelCamera = main; return cachedWorldLabelCamera; } Camera spectateCameraMainCameraFast = GetSpectateCameraMainCameraFast(SpectateCamera.instance); if ((Object)(object)spectateCameraMainCameraFast != (Object)null) { cachedWorldLabelCameraFrame = frameCount; cachedWorldLabelCamera = spectateCameraMainCameraFast; return cachedWorldLabelCamera; } cachedWorldLabelCameraFrame = frameCount; cachedWorldLabelCamera = null; return cachedWorldLabelCamera; } private static string StripRichText(string text) { if (string.IsNullOrEmpty(text)) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(text.Length); bool flag = false; foreach (char c in text) { if (c == '<') { flag = true; } else if (flag) { if (c == '>') { flag = false; } } else { stringBuilder.Append(c); } } return stringBuilder.ToString(); } } internal sealed class MoreUiTrackedObjectNotifier : MonoBehaviour { private ValuableObject trackedValuable; private PhysGrabCart trackedCart; private Enemy trackedEnemy; private ValuableDiscoverCustom trackedCustomDiscoverable; private CosmeticShopMachine trackedCosmeticShopMachine; private ItemVehicle trackedVehicle; internal void TrackValuable(ValuableObject valuable) { if ((Object)(object)valuable != (Object)null) { trackedValuable = valuable; } } internal void TrackCart(PhysGrabCart cart) { if ((Object)(object)cart != (Object)null) { trackedCart = cart; } } internal void TrackEnemy(Enemy enemy) { if ((Object)(object)enemy != (Object)null) { trackedEnemy = enemy; } } internal void TrackCustomDiscoverable(ValuableDiscoverCustom customDiscoverable) { if ((Object)(object)customDiscoverable != (Object)null) { trackedCustomDiscoverable = customDiscoverable; } } internal void TrackCosmeticShopMachine(CosmeticShopMachine machine) { if ((Object)(object)machine != (Object)null) { trackedCosmeticShopMachine = machine; } } internal void TrackVehicle(ItemVehicle vehicle) { if ((Object)(object)vehicle != (Object)null) { trackedVehicle = vehicle; } } private void OnDestroy() { Plugin.NotifyTrackedObjectDestroyed(trackedValuable, trackedCart, trackedEnemy, trackedCustomDiscoverable, trackedCosmeticShopMachine, trackedVehicle); } } internal static class ZichenMapValueService { private static int builtInLevelNumber = -1; private static float builtInInitialValue; private static bool hasBuiltInInitialValue; private static readonly Dictionary trackedCurrentValues = new Dictionary(); private static readonly Dictionary trackedOriginalValues = new Dictionary(); private static float trackedCurrentTotal; private static float trackedOriginalTotal; public static void Reset() { builtInLevelNumber = -1; builtInInitialValue = 0f; hasBuiltInInitialValue = false; trackedCurrentValues.Clear(); trackedOriginalValues.Clear(); trackedCurrentTotal = 0f; trackedOriginalTotal = 0f; } public static void RegisterValueSet(ValuableObject valuable, float value, int levelNumber) { EnsureLevel(levelNumber); if (!((Object)(object)valuable == (Object)null) && !(value <= 0f)) { TrackValue(valuable, value, Mathf.Max(value, GetValuableOriginalValue(valuable))); } } public static void RegisterValueSet(ValuableObject valuable, int levelNumber) { EnsureLevel(levelNumber); if (!((Object)(object)valuable == (Object)null)) { float valuableCurrentValue = GetValuableCurrentValue(valuable); if (!(valuableCurrentValue <= 0f)) { TrackValue(valuable, valuableCurrentValue, Mathf.Max(valuableCurrentValue, GetValuableOriginalValue(valuable))); } } } public static void RegisterBreak(ValuableObject valuable, float valueLost, int levelNumber) { EnsureLevel(levelNumber); if (!((Object)(object)valuable == (Object)null) && !(valueLost <= 0f)) { int key = GetKey(valuable); if (trackedCurrentValues.TryGetValue(key, out var value)) { float value2; float originalValue = (trackedOriginalValues.TryGetValue(key, out value2) ? value2 : Mathf.Max(value, GetValuableOriginalValue(valuable))); TrackValue(key, value - valueLost, originalValue); } else { RegisterValueSet(valuable, levelNumber); } } } public static void RegisterDestroy(ValuableObject valuable, int levelNumber) { EnsureLevel(levelNumber); if (!((Object)(object)valuable == (Object)null)) { RemoveTrackedValue(GetKey(valuable)); } } public static void SyncFromLiveValuables(IEnumerable valuables, int levelNumber) { EnsureLevel(levelNumber); trackedCurrentValues.Clear(); trackedOriginalValues.Clear(); trackedCurrentTotal = 0f; trackedOriginalTotal = 0f; if (valuables == null) { return; } foreach (ValuableObject valuable in valuables) { if (IsValuableReady(valuable)) { TrackValue(valuable, GetValuableCurrentValue(valuable), GetValuableOriginalValue(valuable)); } } } public static bool TryGetValues(IEnumerable valuables, int levelNumber, out float mapValue, out float initialMapValue) { mapValue = 0f; initialMapValue = 0f; EnsureLevel(levelNumber); float num = 0f; float num2 = 0f; bool flag = false; if (valuables != null) { foreach (ValuableObject valuable in valuables) { if (IsValuableReady(valuable)) { flag = true; float valuableCurrentValue = GetValuableCurrentValue(valuable); float valuableOriginalValue = GetValuableOriginalValue(valuable); num += valuableCurrentValue; num2 += valuableOriginalValue; TrackValue(valuable, valuableCurrentValue, valuableOriginalValue); } } } float num3 = trackedCurrentTotal; float num4 = trackedOriginalTotal; if (!flag && num3 <= 0f && num4 <= 0f) { return false; } num = Mathf.Max(num, num3); num2 = Mathf.Max(num2, num4); float num5 = Mathf.Max(num, num2); if (!hasBuiltInInitialValue || num5 > builtInInitialValue) { builtInInitialValue = num5; hasBuiltInInitialValue = builtInInitialValue > 0f; } if (!hasBuiltInInitialValue) { return false; } mapValue = Mathf.Max(0f, num); initialMapValue = Mathf.Max(mapValue, builtInInitialValue); return true; } private static bool IsValuableReady(ValuableObject valuable) { if ((Object)(object)valuable == (Object)null) { return false; } if (!Plugin.IsValuableValueSetFast(valuable)) { return false; } float valuableCurrentValueFast = Plugin.GetValuableCurrentValueFast(valuable); float valuableOriginalValueFast = Plugin.GetValuableOriginalValueFast(valuable); if (!(valuableCurrentValueFast > 0f)) { return valuableOriginalValueFast > 0f; } return true; } private static void EnsureLevel(int levelNumber) { if (levelNumber != builtInLevelNumber) { builtInLevelNumber = levelNumber; builtInInitialValue = 0f; hasBuiltInInitialValue = false; trackedCurrentValues.Clear(); trackedOriginalValues.Clear(); trackedCurrentTotal = 0f; trackedOriginalTotal = 0f; } } private static void TrackValue(ValuableObject valuable, float currentValue, float originalValue) { if (!((Object)(object)valuable == (Object)null)) { TrackValue(GetKey(valuable), currentValue, originalValue); } } private static void TrackValue(int key, float currentValue, float originalValue) { if (key == 0) { return; } if (currentValue <= 0f) { RemoveTrackedValue(key); return; } float num = Mathf.Max(0f, currentValue); float num2 = Mathf.Max(Mathf.Max(0f, originalValue), num); if (trackedCurrentValues.TryGetValue(key, out var value)) { trackedCurrentTotal += num - value; } else { trackedCurrentTotal += num; } if (trackedOriginalValues.TryGetValue(key, out var value2)) { trackedOriginalTotal += num2 - value2; } else { trackedOriginalTotal += num2; } trackedCurrentValues[key] = num; trackedOriginalValues[key] = num2; } private static void RemoveTrackedValue(int key) { if (key != 0) { if (trackedCurrentValues.TryGetValue(key, out var value)) { trackedCurrentTotal = Mathf.Max(0f, trackedCurrentTotal - value); trackedCurrentValues.Remove(key); } if (trackedOriginalValues.TryGetValue(key, out var value2)) { trackedOriginalTotal = Mathf.Max(0f, trackedOriginalTotal - value2); trackedOriginalValues.Remove(key); } } } private static int GetKey(ValuableObject valuable) { if (!((Object)(object)valuable == (Object)null)) { return ((Object)valuable).GetInstanceID(); } return 0; } private static float GetValuableCurrentValue(ValuableObject valuable) { return Plugin.GetValuableCurrentValueFast(valuable); } private static float GetValuableOriginalValue(ValuableObject valuable) { return Plugin.GetValuableOriginalValueFast(valuable); } } internal sealed class ReferenceObjectComparer : IEqualityComparer { public static readonly ReferenceObjectComparer Instance = new ReferenceObjectComparer(); private 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; } } public sealed class MoreUiPlayerDistance { public string Name { get; internal set; } = string.Empty; public int DistanceMeters { get; internal set; } public float DistanceValue { get; internal set; } public bool IsDead { get; internal set; } public bool IsLocalPlayer { get; internal set; } public string ColorHex { get; internal set; } = "FFFFFF"; public string PlainTextNoDistance { get; internal set; } = string.Empty; public string PlainText { get; internal set; } = string.Empty; public string RichTextNoDistance { get; internal set; } = string.Empty; public string RichText { get; internal set; } = string.Empty; public string OverlayLine { get; internal set; } = string.Empty; public Vector3 LabelPosition { get; internal set; } } internal struct TeammateEdgeLabelDrawInfo { public bool IsLeftEdge; public int DistanceMeters; public float PreferredY; public float Width; public float Height; public string PlainText; public string RichText; public GUIStyle LabelStyle; public GUIStyle ShadowStyle; } internal struct TeammateLabelLayout { public string PlainText; public string RichText; public float Width; public float Height; public GUIStyle LabelStyle; public GUIStyle ShadowStyle; } public sealed class MoreUiCartDistance { public string Name { get; internal set; } = string.Empty; public int Index { get; internal set; } public bool IsSmallCart { get; internal set; } public int DistanceMeters { get; internal set; } public float DistanceValue { get; internal set; } public bool IsBeingPushed { get; internal set; } public string ColorHex { get; internal set; } = "ffd84d"; public string PlainTextNoDistance { get; internal set; } = string.Empty; public string PlainText { get; internal set; } = string.Empty; public string RichTextNoDistance { get; internal set; } = string.Empty; public string RichText { get; internal set; } = string.Empty; public Vector3 ReferencePosition { get; internal set; } public Vector3 LabelPosition { get; internal set; } } public sealed class MoreUiVehicleDistance { public string Name { get; internal set; } = string.Empty; public int Index { get; internal set; } public bool IsRacingVehicle { get; internal set; } public int DistanceMeters { get; internal set; } public float DistanceValue { get; internal set; } public bool HasRider { get; internal set; } public string ColorHex { get; internal set; } = "ffd84d"; public string PlainTextNoDistance { get; internal set; } = string.Empty; public string PlainText { get; internal set; } = string.Empty; public string RichTextNoDistance { get; internal set; } = string.Empty; public string RichText { get; internal set; } = string.Empty; public Vector3 LabelPosition { get; internal set; } } internal readonly struct LabelSizeCacheKey : IEquatable { public readonly int FontSize; public readonly string Text; public LabelSizeCacheKey(int fontSize, string text) { FontSize = fontSize; Text = text ?? string.Empty; } public bool Equals(LabelSizeCacheKey other) { if (FontSize == other.FontSize) { return string.Equals(Text, other.Text, StringComparison.Ordinal); } return false; } public override bool Equals(object obj) { if (obj is LabelSizeCacheKey other) { return Equals(other); } return false; } public override int GetHashCode() { return (FontSize * 397) ^ ((Text != null) ? Text.GetHashCode() : 0); } } internal struct NativeOverlayLineState { public bool Active; public bool RichText; public int FontSize; public string Text; public Color32 Color; public float Width; public float BaseY; public float Height; } internal static class HudText { public static string UnknownLevel(DisplayLanguage language) { if (!IsEnglish(language)) { return "未知"; } return "Unknown"; } public static string UnknownEnemy(DisplayLanguage language) { if (!IsEnglish(language)) { return "未知怪物"; } return "Unknown Enemy"; } public static string Danger(DisplayLanguage language) { if (!IsEnglish(language)) { return "危险"; } return "DANGER"; } public static string EnemyTotal(DisplayLanguage language) { if (!IsEnglish(language)) { return "怪物总数"; } return "Enemies"; } public static string TokenBoxCount(DisplayLanguage language) { if (!IsEnglish(language)) { return "装饰箱"; } return "Lottery Boxes"; } public static string MapLostValue(DisplayLanguage language) { if (!IsEnglish(language)) { return "损坏宝物"; } return "Run Lost Funds"; } public static string ExplorationProgress(DisplayLanguage language) { if (!IsEnglish(language)) { return "收集进度"; } return "Extraction Progress"; } public static string UnextractedFunds(DisplayLanguage language) { if (!IsEnglish(language)) { return "未收集"; } return "Unextracted Funds"; } public static string MapTotalValue(DisplayLanguage language) { if (!IsEnglish(language)) { return "地图库存"; } return "Map Remaining Funds"; } public static string ValueUnavailable(DisplayLanguage language) { if (!IsEnglish(language)) { return "无法加载"; } return "Unavailable"; } public static string MapValueDataUnavailable(DisplayLanguage language) { if (!IsEnglish(language)) { return "地图价值数据暂不可用"; } return "Map value data is temporarily unavailable"; } public static string EvacuatedFunds(DisplayLanguage language) { if (!IsEnglish(language)) { return "提交/商店资金"; } return "Submitted / Shop Funds"; } public static string CurrentRunEvacuatedFunds(DisplayLanguage language) { if (!IsEnglish(language)) { return "提交资金"; } return "Run Submitted Funds"; } public static string WarehouseFunds(DisplayLanguage language) { if (!IsEnglish(language)) { return "商店库存"; } return "Shop Remaining Funds"; } public static string Level(DisplayLanguage language) { if (!IsEnglish(language)) { return "关卡"; } return "Level"; } public static string DeadTeammates(DisplayLanguage language) { if (!IsEnglish(language)) { return "死亡队友"; } return "Dead Teammates"; } public static string PlayerCounts(DisplayLanguage language) { if (!IsEnglish(language)) { return "玩家"; } return "Players"; } public static string Dead(DisplayLanguage language) { if (!IsEnglish(language)) { return "死亡"; } return "Dead"; } public static string Alive(DisplayLanguage language) { if (!IsEnglish(language)) { return "存活"; } return "Alive"; } public static string Total(DisplayLanguage language) { if (!IsEnglish(language)) { return "总数"; } return "Total"; } private static bool IsEnglish(DisplayLanguage language) { return language == DisplayLanguage.English; } } internal static class EnemyNameLocalizer { 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"] = "小狗", ["Duck"] = "邪恶鸭子", ["Enemy Duck"] = "邪恶鸭子", ["Elsa"] = "小狗", ["Enemy Elsa"] = "小狗", ["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) { return Translate(rawName, language, useNicknames: false); } 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 (TryGetTranslatedName(activeMap, text, out var translated)) { return translated; } string text2 = NormalizeKey(text); if (TryGetTranslatedName(activeMap, text2, out translated)) { return translated; } string text3 = SimplifyEnemyComponentName(text2); if (!string.Equals(text3, text2, StringComparison.OrdinalIgnoreCase) && TryGetTranslatedName(activeMap, text3, out translated)) { return translated; } Match match = Regex.Match(text2, "^(?\\d+)\\s+(?.+)$"); 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 (TryGetTranslatedName(activeMap, text4, out translated)) { return value + " " + translated; } if (TryGetTranslatedName(activeMap, text5, out translated)) { return value + " " + translated; } string key = SimplifyEnemyComponentName(text4); if (TryGetTranslatedName(activeMap, key, out translated)) { return value + " " + translated; } string key2 = SimplifyEnemyComponentName(text5); if (TryGetTranslatedName(activeMap, key2, out translated)) { return value + " " + translated; } } return text; } private static bool TryGetTranslatedName(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) { return Regex.Replace(Regex.Replace(Regex.Replace(rawName.Replace("(Clone)", string.Empty).Replace("Enemy Group - ", string.Empty).Replace("Enemy - ", string.Empty) .Replace("_", " ") .Replace("-", " ") .Trim(), "(?<=[a-z])(?=[A-Z])", " "), "^Enemy\\s+", string.Empty, RegexOptions.IgnoreCase), "\\s+", " ").Trim(); } private static string SimplifyEnemyComponentName(string cleaned) { if (string.IsNullOrWhiteSpace(cleaned)) { return string.Empty; } string text = Regex.Replace(cleaned, "\\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.*$", string.Empty, RegexOptions.IgnoreCase).Trim(); if (!string.IsNullOrWhiteSpace(text)) { return text; } return cleaned; } } internal static class LevelNameLocalizer { private static readonly Dictionary NameMap = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["Swiftbroom Academy"] = "迅帚学院", ["Headman Manor"] = "黑德曼庄园", ["McJannek Station"] = "麦詹内克站", ["Service Station"] = "服务站", ["The Factory"] = "工厂", ["Museum of Human Art"] = "人类艺术博物馆", ["Arena"] = "竞技场", ["Lobby"] = "大厅", ["Shop"] = "商店", ["Tutorial"] = "教程" }; public static string Translate(string rawName, DisplayLanguage language) { if (string.IsNullOrWhiteSpace(rawName)) { return HudText.UnknownLevel(language); } string text = rawName.Trim(); if (language == DisplayLanguage.English) { return text; } if (!NameMap.TryGetValue(text, out var value)) { return text; } return value; } } internal sealed class ConfigurationManagerAttributes { public int? Order; public Action CustomDrawer; public bool? ReadOnly; public bool? Browsable; public bool? HideDefaultButton; public string Category; public string DispName; public string Description; } internal struct ValuableSnapshot { public float OriginalValue; public float CurrentValue; public float CurrentDamage; public float CountedLostValue; public bool WasInHaul; public int SeenGeneration; } internal struct CartLabelCandidate { public int Id; public Vector3 Position; } internal struct LabelYOffsetCache { public float YOffset; public float UpdatedAt; } internal struct PlayerPositionCache { public Vector3 Position; public float UpdatedAt; } internal struct PlayerColorCacheEntry { public int ColorIndex; public string ColorHex; public float UpdatedAt; } internal struct CartComponentCache { public PhysGrabCart Cart; public PhysGrabObject PhysGrabObject; public Component PhysGrabObjectComponent; public ItemEquippable ItemEquippable; } internal static class REPOConfigCreateHook { public static void Postfix(object[] __args, object __result) { try { if (__args != null && __args.Length != 0 && __result != null && __args[0] is string label) { Plugin.RegisterLiveLabelIfMatched(label, __result); } } catch { } } public static void CreateModEntriesPrefix(object[] __args) { try { Plugin._currentRenderingConfigFilePath = null; if (__args != null && __args.Length >= 2 && __args[1] is ConfigEntryBase[] array && array.Length != 0) { ConfigEntryBase val = array[0]; if (((val != null) ? val.ConfigFile : null) != null) { Plugin._currentRenderingConfigFilePath = val.ConfigFile.ConfigFilePath; } } } catch { } } public static void CreateModEntriesPostfix() { Plugin._currentRenderingConfigFilePath = null; } } public enum BoundsPosition { Center, Bottom }