using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.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; } } } namespace IndependentCadaverInfectionBar { internal static class ModConfig { internal static ConfigEntry InfectionBarEnabled { get; private set; } internal static ConfigEntry InfectionBarAlwaysVisible { get; private set; } internal static ConfigEntry DebugLogging { get; private set; } internal static ConfigEntry DebugVanillaHudLiveLayoutRefresh { get; private set; } internal static ConfigEntry HudStyleMode { get; private set; } internal static ConfigEntry UiWidth { get; private set; } internal static ConfigEntry UiHeight { get; private set; } internal static ConfigEntry AnchorPreset { get; private set; } internal static ConfigEntry PositionOffsetX { get; private set; } internal static ConfigEntry PositionOffsetY { get; private set; } internal static ConfigEntry TextOffsetX { get; private set; } internal static ConfigEntry TextOffsetY { get; private set; } internal static ConfigEntry TextFontSize { get; private set; } internal static ConfigEntry ShowPanelBackground { get; private set; } internal static ConfigEntry PanelBackgroundAlpha { get; private set; } internal static ConfigEntry TerminalFadeAlpha { get; private set; } internal static ConfigEntry ReduceAliasing { get; private set; } internal static ConfigEntry SortingOrder { get; private set; } internal static ConfigEntry VanillaRingScale { get; private set; } internal static ConfigEntry VanillaRingOffsetX { get; private set; } internal static ConfigEntry VanillaRingOffsetY { get; private set; } internal static ConfigEntry VanillaWarningTextOffsetEnabled { get; private set; } internal static ConfigEntry VanillaWarningTextOffsetX { get; private set; } internal static ConfigEntry VanillaWarningTextOffsetY { get; private set; } internal static ConfigEntry LabelLanguageMode { get; private set; } internal static void Bind(ConfigFile config) { InfectionBarEnabled = config.Bind("General", "InfectionBarEnabled", true, "Whether to show the standalone Cadaver infection bar."); InfectionBarAlwaysVisible = config.Bind("General", "InfectionBarAlwaysVisible", false, "Whether the infection bar should stay visible even when infection is at 0%."); DebugLogging = config.Bind("General", "DebugLogging", false, "Whether to write diagnostic logs for infection bar lifecycle and native HUD attachment."); DebugVanillaHudLiveLayoutRefresh = config.Bind("Debug", "DebugVanillaHudLiveLayoutRefresh", false, "For layout validation only. When enabled, the vanilla HUD ring and curved text are force-resynced every frame, which costs more CPU."); HudStyleMode = config.Bind("General", "HudStyleMode", "Auto", "HUD style mode for this isolated test. Supported values: Auto, CurrentStyle, VanillaStaminaRingStyle."); UiWidth = config.Bind("Layout", "UiWidth", 215f, "Overall width of the full infection bar UI root."); UiHeight = config.Bind("Layout", "UiHeight", 34f, "Overall height of the full infection bar UI root."); AnchorPreset = config.Bind("Layout", "AnchorPreset", "TopLeft", "Anchor preset used inside the native HUD container. Supported values: BottomLeft, BottomCenter, BottomRight, Center, TopLeft, TopCenter, TopRight."); PositionOffsetX = config.Bind("Layout", "PositionOffsetX", 30f, "Horizontal offset relative to the selected anchor preset."); PositionOffsetY = config.Bind("Layout", "PositionOffsetY", -135f, "Vertical offset relative to the selected anchor preset."); TextOffsetX = config.Bind("Layout", "TextOffsetX", 9f, "Horizontal offset of the infection label text inside the bar root."); TextOffsetY = config.Bind("Layout", "TextOffsetY", 1f, "Vertical offset of the infection label text inside the bar root."); TextFontSize = config.Bind("Layout", "TextFontSize", 13, "Font size of the infection label text."); ShowPanelBackground = config.Bind("Layout", "ShowPanelBackground", false, "Whether to show the faint panel background behind the infection bar."); PanelBackgroundAlpha = config.Bind("Layout", "PanelBackgroundAlpha", 0.22f, "Alpha of the panel background when it is enabled."); TerminalFadeAlpha = config.Bind("Layout", "TerminalFadeAlpha", 0.25f, "Alpha used while the in-game terminal is actively being used."); ReduceAliasing = config.Bind("Layout", "ReduceAliasing", true, "Uses more conservative UI alignment and minimum element thickness to reduce jagged edges and blur when the infection bar is slightly tilted."); SortingOrder = config.Bind("Layout", "SortingOrder", 5, "Sorting order for the standalone overlay canvas."); VanillaRingScale = config.Bind("VanillaHud", "VanillaRingScale", 1.3f, "Scale multiplier applied to the infection ring derived from the original sprint meter UI."); VanillaRingOffsetX = config.Bind("VanillaHud", "VanillaRingOffsetX", -32.5f, "Additional horizontal fine-tune offset after the automatic outer-ring placement."); VanillaRingOffsetY = config.Bind("VanillaHud", "VanillaRingOffsetY", 16f, "Additional vertical fine-tune offset after the automatic outer-ring placement."); VanillaWarningTextOffsetEnabled = config.Bind("VanillaHud", "VanillaWarningTextOffsetEnabled", true, "Whether vanilla HUD mode should move the original warning text right so it does not overlap the infection ring."); VanillaWarningTextOffsetX = config.Bind("VanillaHud", "VanillaWarningTextOffsetX", 60f, "Horizontal offset applied to the original warning text root while vanilla HUD mode is active."); VanillaWarningTextOffsetY = config.Bind("VanillaHud", "VanillaWarningTextOffsetY", 0f, "Vertical offset applied to the original warning text root while vanilla HUD mode is active."); LabelLanguageMode = config.Bind("Language", "LabelLanguageMode", "Auto", "Auto, English, or Chinese."); } } internal static class InfectionBarCompatibility { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnClientHelloMessage; public static HandleNamedMessageDelegate <1>__OnHostStateMessage; } private const string ClientHelloMessageName = "InfectionBar_ClientHello_v1"; private const string HostStateMessageName = "InfectionBar_HostState_v1"; private const float MessageIntervalSeconds = 2f; private const float GracePeriodSeconds = 8f; private const string HostMissingReason = "host does not have InfectionBar installed"; private const string MissingClientsReason = "one or more clients do not have InfectionBar installed"; private static readonly InfectionBarCompatibilityState hostClientState = new InfectionBarCompatibilityState(); private static readonly List hostStateRecipients = new List(); private static ManualLogSource logger; private static CustomMessagingManager registeredMessagingManager; private static NetworkManager observedNetworkManager; private static ulong observedLocalClientId = ulong.MaxValue; private static bool observedIsServer; private static bool observedIsConnectedClient; private static bool hudAllowed = true; private static string disableReason = string.Empty; private static float nextClientHelloTime; private static float nextHostStateTime; private static float clientConnectionStartTime = -1f; private static float lastHostStateReceivedTime = -1f; private static bool receivedHostState; private static bool hostStateAllowed = true; private static int hostStateMissingClientCount; private static bool clientStoppedHelloForMissingHost; private static bool loggedHostMissingWarning; private static bool loggedMissingClientsWarning; private static bool loggedHandlerRegistrationWarning; internal static bool HudAllowed => hudAllowed; internal static string DisableReason => disableReason; internal static void Initialize(ManualLogSource pluginLogger) { logger = pluginLogger; SetHudAllowed(allowed: true, string.Empty); } internal static void Tick() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.ShutdownInProgress || !singleton.IsListening) { UnregisterHandlers(); ResetSessionState(0f); observedNetworkManager = null; return; } EnsureHandlers(singleton.CustomMessagingManager); float unscaledTime = Time.unscaledTime; ResetSessionIfNeeded(singleton, unscaledTime); if (singleton.IsServer) { TickHost(singleton, unscaledTime); } else if (singleton.IsClient && singleton.IsConnectedClient) { TickClient(singleton, unscaledTime); } else { SetHudAllowed(allowed: true, string.Empty); } } private static void ResetSessionIfNeeded(NetworkManager networkManager, float now) { ulong num = (networkManager.IsClient ? networkManager.LocalClientId : 0); if (!((Object)(object)observedNetworkManager == (Object)(object)networkManager) || observedLocalClientId != num || observedIsServer != networkManager.IsServer || observedIsConnectedClient != networkManager.IsConnectedClient) { observedNetworkManager = networkManager; observedLocalClientId = num; observedIsServer = networkManager.IsServer; observedIsConnectedClient = networkManager.IsConnectedClient; ResetSessionState(now); } } private static void ResetSessionState(float now) { hostClientState.Reset(); hostStateRecipients.Clear(); nextClientHelloTime = 0f; nextHostStateTime = 0f; clientConnectionStartTime = now; lastHostStateReceivedTime = -1f; receivedHostState = false; hostStateAllowed = true; hostStateMissingClientCount = 0; clientStoppedHelloForMissingHost = false; SetHudAllowed(allowed: true, string.Empty); } private static void TickHost(NetworkManager networkManager, float now) { IReadOnlyList connectedClientsIds = networkManager.ConnectedClientsIds; hostClientState.UpdateConnectedClients(connectedClientsIds, 0uL, now); int num = hostClientState.CountMissingClients(now, 8f); if (num > 0) { SetHudAllowed(allowed: false, "one or more clients do not have InfectionBar installed"); LogMissingClientsWarningOnce(); } else { SetHudAllowed(allowed: true, string.Empty); } if (!(now < nextHostStateTime)) { nextHostStateTime = now + 2f; SendHostState(networkManager.CustomMessagingManager, connectedClientsIds, hudAllowed, num); } } private static void TickClient(NetworkManager networkManager, float now) { if (clientConnectionStartTime < 0f) { clientConnectionStartTime = now; } SendClientHelloIfNeeded(networkManager.CustomMessagingManager, now); if (!receivedHostState) { if (now - clientConnectionStartTime >= 8f) { clientStoppedHelloForMissingHost = true; SetHudAllowed(allowed: false, "host does not have InfectionBar installed"); LogHostMissingWarningOnce(); } else { SetHudAllowed(allowed: true, string.Empty); } } else if (lastHostStateReceivedTime >= 0f && now - lastHostStateReceivedTime >= 8f) { SetHudAllowed(allowed: false, "host does not have InfectionBar installed"); LogHostMissingWarningOnce(); } else if (hostStateAllowed) { SetHudAllowed(allowed: true, string.Empty); } else { SetHudAllowed(allowed: false, "one or more clients do not have InfectionBar installed"); if (hostStateMissingClientCount > 0) { LogMissingClientsWarningOnce(); } } } private static void SendClientHelloIfNeeded(CustomMessagingManager messagingManager, float now) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (clientStoppedHelloForMissingHost || messagingManager == null || now < nextClientHelloTime) { return; } nextClientHelloTime = now + 2f; try { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(128, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe("1.1.2", false); messagingManager.SendNamedMessage("InfectionBar_ClientHello_v1", 0uL, val, (NetworkDelivery)2); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } catch (Exception ex) { LogHandlerWarningOnce("Failed to send InfectionBar ClientHello: " + ex.Message); } } private static void SendHostState(CustomMessagingManager messagingManager, IReadOnlyList connectedClientIds, bool allowed, int missingClientCount) { //IL_0049: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (messagingManager == null) { return; } hostClientState.CollectInstalledClientIds(connectedClientIds, 0uL, hostStateRecipients); if (hostStateRecipients.Count == 0) { return; } try { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(256, (Allocator)2, -1); try { bool flag = allowed; int num = missingClientCount; ((FastBufferWriter)(ref val)).WriteValueSafe("1.1.2", false); ((FastBufferWriter)(ref val)).WriteValueSafe(ref flag, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); messagingManager.SendNamedMessage("InfectionBar_HostState_v1", (IReadOnlyList)hostStateRecipients, val, (NetworkDelivery)2); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } catch (Exception ex) { LogHandlerWarningOnce("Failed to send InfectionBar HostState: " + ex.Message); } } private static void EnsureHandlers(CustomMessagingManager messagingManager) { //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) //IL_0032: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown if (messagingManager == null || registeredMessagingManager == messagingManager) { return; } UnregisterHandlers(); try { object obj = <>O.<0>__OnClientHelloMessage; if (obj == null) { HandleNamedMessageDelegate val = OnClientHelloMessage; <>O.<0>__OnClientHelloMessage = val; obj = (object)val; } messagingManager.RegisterNamedMessageHandler("InfectionBar_ClientHello_v1", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<1>__OnHostStateMessage; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnHostStateMessage; <>O.<1>__OnHostStateMessage = val2; obj2 = (object)val2; } messagingManager.RegisterNamedMessageHandler("InfectionBar_HostState_v1", (HandleNamedMessageDelegate)obj2); registeredMessagingManager = messagingManager; } catch (Exception ex) { try { messagingManager.UnregisterNamedMessageHandler("InfectionBar_ClientHello_v1"); messagingManager.UnregisterNamedMessageHandler("InfectionBar_HostState_v1"); } catch { } registeredMessagingManager = null; LogHandlerWarningOnce("Failed to register InfectionBar network handlers: " + ex.Message); } } private static void UnregisterHandlers() { if (registeredMessagingManager != null) { try { registeredMessagingManager.UnregisterNamedMessageHandler("InfectionBar_ClientHello_v1"); registeredMessagingManager.UnregisterNamedMessageHandler("InfectionBar_HostState_v1"); } catch { } registeredMessagingManager = null; } } private static void OnClientHelloMessage(ulong senderClientId, FastBufferReader reader) { NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsServer && senderClientId != 0L) { try { string empty = string.Empty; ((FastBufferReader)(ref reader)).ReadValueSafe(ref empty, false); } catch { } hostClientState.RecordClientHello(senderClientId); } } private static void OnHostStateMessage(ulong senderClientId, FastBufferReader reader) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: 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) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.IsServer || senderClientId != 0L) { return; } try { string empty = string.Empty; bool flag = false; int num = 0; ((FastBufferReader)(ref reader)).ReadValueSafe(ref empty, false); ((FastBufferReader)(ref reader)).ReadValueSafe(ref flag, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); receivedHostState = true; lastHostStateReceivedTime = Time.unscaledTime; hostStateAllowed = flag; hostStateMissingClientCount = num; } catch (Exception ex) { LogHandlerWarningOnce("Failed to read InfectionBar HostState: " + ex.Message); } } private static void SetHudAllowed(bool allowed, string reason) { hudAllowed = allowed; disableReason = (allowed ? string.Empty : (reason ?? string.Empty)); } private static void LogHostMissingWarningOnce() { if (!loggedHostMissingWarning) { if (logger != null) { logger.LogWarning((object)"host does not have InfectionBar installed"); } loggedHostMissingWarning = true; } } private static void LogMissingClientsWarningOnce() { if (!loggedMissingClientsWarning) { if (logger != null) { logger.LogWarning((object)"one or more clients do not have InfectionBar installed"); } loggedMissingClientsWarning = true; } } private static void LogHandlerWarningOnce(string message) { if (!loggedHandlerRegistrationWarning) { if (logger != null) { logger.LogWarning((object)message); } loggedHandlerRegistrationWarning = true; } } } internal sealed class InfectionBarCompatibilityState { private readonly Dictionary firstSeenTimes = new Dictionary(); private readonly HashSet installedClients = new HashSet(); private readonly HashSet connectedClientSet = new HashSet(); private readonly List idsToRemove = new List(); internal void Reset() { firstSeenTimes.Clear(); installedClients.Clear(); connectedClientSet.Clear(); idsToRemove.Clear(); } internal void UpdateConnectedClients(IReadOnlyList connectedClientIds, ulong serverClientId, float now) { connectedClientSet.Clear(); if (connectedClientIds != null) { for (int i = 0; i < connectedClientIds.Count; i++) { ulong num = connectedClientIds[i]; connectedClientSet.Add(num); if (num != serverClientId && !firstSeenTimes.ContainsKey(num)) { firstSeenTimes[num] = now; } } } PruneDisconnectedClients(firstSeenTimes, serverClientId); PruneDisconnectedClients(installedClients, serverClientId); } internal void RecordClientHello(ulong clientId) { installedClients.Add(clientId); } internal int CountMissingClients(float now, float gracePeriodSeconds) { int num = 0; foreach (KeyValuePair firstSeenTime in firstSeenTimes) { if (!installedClients.Contains(firstSeenTime.Key) && now - firstSeenTime.Value >= gracePeriodSeconds) { num++; } } return num; } internal void CollectInstalledClientIds(IReadOnlyList connectedClientIds, ulong serverClientId, List results) { results.Clear(); if (connectedClientIds == null) { return; } for (int i = 0; i < connectedClientIds.Count; i++) { ulong num = connectedClientIds[i]; if (num != serverClientId && installedClients.Contains(num)) { results.Add(num); } } } private void PruneDisconnectedClients(Dictionary clients, ulong serverClientId) { idsToRemove.Clear(); foreach (KeyValuePair client in clients) { if (client.Key != serverClientId && !connectedClientSet.Contains(client.Key)) { idsToRemove.Add(client.Key); } } for (int i = 0; i < idsToRemove.Count; i++) { clients.Remove(idsToRemove[i]); } } private void PruneDisconnectedClients(HashSet clients, ulong serverClientId) { idsToRemove.Clear(); foreach (ulong client in clients) { if (client != serverClientId && !connectedClientSet.Contains(client)) { idsToRemove.Add(client); } } for (int i = 0; i < idsToRemove.Count; i++) { clients.Remove(idsToRemove[i]); } } } internal sealed class InfectionBarController : MonoBehaviour { private enum HudStyle { Current, VanillaStaminaRing } private enum VanillaArcTextSlot { WeightStaminaUpper, WeightInfectionInner, InfectionOuter } private enum VanillaArcRadiusBand { Inner, Middle, Outer } private readonly struct NativeHudState { internal float Alpha { get; } internal bool IsValid { get; } internal NativeHudState(float alpha, bool isValid) { Alpha = alpha; IsValid = isValid; } } private const string EladsHudPluginGuid = "me.eladnlg.customhud"; private const string VanillaWarningRootPathSuffix = "IngamePlayerHUD/SpecialHUDGraphics/RadiationIncrease"; private const float NativeHudStateRefreshIntervalSeconds = 0.1f; private const float HudIntroAlphaSampleSeconds = 4f; private static Sprite pixelSprite; private static float nextTerminalLookupTime; private static float nextNativeHudElementLookupTime; private static float nextNativeHudParentFallbackLookupTime; private static float nextVanillaWarningRootLookupTime; private static float nextNativeHudStateRefreshTime; private static HUDManager cachedHudManagerInstance; private static StartOfRound cachedStartOfRoundInstance; private static Terminal cachedTerminal; private static NativeHudState cachedNativeHudState; private static Transform cachedNativeHudElementTransform; private static RectTransform cachedNativeHudParentFallback; private static RectTransform cachedVanillaWarningRoot; private static bool cachedEladsHudInstalled; private static bool hasCachedEladsHudInstalled; private static FieldInfo hudPlayerInfoField; private static FieldInfo hudContainerField; private static FieldInfo hudElementsField; private static FieldInfo hudHudHiddenField; private static FieldInfo hudTerminalScriptField; private static FieldInfo hudRadiationGraphicAnimatorField; private static FieldInfo terminalInUseField; private ManualLogSource logger; private InfectionDataProvider dataProvider; private InfectionLayout layout; private LanguageHelper languageHelper; private CanvasGroup canvasGroup; private RectTransform infectionRoot; private Image panelBackground; private Image topLine; private Image infectionBackground; private Image infectionBar; private Text infectionText; private Image vanillaSprintMeterReference; private RectTransform vanillaWeightTextRoot; private CanvasGroup vanillaWeightTextCanvasGroup; private RectTransform vanillaInfectionTextRoot; private CanvasGroup vanillaInfectionTextCanvasGroup; private RectTransform vanillaInfectionValueTextRoot; private CanvasGroup vanillaInfectionValueTextCanvasGroup; private TextMeshProUGUI hiddenWeightCounter; private bool hiddenWeightCounterWasEnabled; private string lastVanillaWeightText = string.Empty; private string lastVanillaInfectionText = string.Empty; private string lastAppliedVanillaWeightText = string.Empty; private string lastAppliedVanillaInfectionText = string.Empty; private bool hasAppliedVanillaWeightText; private bool hasAppliedVanillaInfectionText; private bool hasClearedVanillaInfectionValueText; private VanillaArcTextSlot lastAppliedVanillaWeightSlot; private Vector2 lastAppliedVanillaWeightRootSize; private Vector2 lastAppliedVanillaInfectionRootSize; private bool hasVanillaLayoutSignature; private Vector2 lastVanillaAnchorMin; private Vector2 lastVanillaAnchorMax; private Vector2 lastVanillaPivot; private Vector2 lastVanillaSizeDelta; private Vector2 lastVanillaAnchoredPosition; private Quaternion lastVanillaLocalRotation; private Vector3 lastVanillaLocalScale; private float lastVanillaRingScale; private float lastVanillaRingOffsetX; private float lastVanillaRingOffsetY; private RectTransform shiftedVanillaWarningRoot; private Vector2 originalVanillaWarningAnchoredPosition; private bool hasOriginalVanillaWarningAnchoredPosition; private bool loggedMissingVanillaWarningRoot; private string cachedInfectionLabel = "Infection"; private float nextInfectionLabelRefreshTime; private float lastRenderedInfectionFillAmount = -1f; private int lastRenderedInfectionPercent = -1; private string lastRenderedInfectionLabel = string.Empty; private bool lastVisibleState; private bool loggedMissingNativeHudParent; private bool loggedNativeHudParentFallback; private int lastTickFrame = -1; private float currentHudAlpha = 1f; private RectTransform hudIntroAlphaSampleSource; private float hudIntroAlphaSampleUntilTime; private bool hudIntroAlphaSamplingActive; private bool layoutDirty = true; private bool hudStyleDirty = true; private bool layoutConfigEventsSubscribed; private bool hasActiveHudStyle; private HudStyle activeHudStyle; private bool loggedMissingSprintMeter; private bool loggedVanillaSprintMeterDiagnostics; private const string VanillaArcCharacterPrefix = "VanillaArcChar_"; private const float SprintMeterSpriteSize = 326f; private static readonly float[] SprintMeterArcAngles = new float[43] { -162.5f, -157.5f, -152.5f, -147.5f, -142.5f, -137.5f, -132.5f, -127.5f, -122.5f, -117.5f, -112.5f, -107.5f, -102.5f, -97.5f, -92.5f, -87.5f, -82.5f, -77.5f, -72.5f, -67.5f, -62.5f, -57.5f, -52.5f, -47.5f, -42.5f, -37.5f, -32.5f, -27.5f, -22.5f, -17.5f, -12.5f, -7.5f, -2.5f, 2.5f, 7.5f, 17.5f, 22.5f, 27.5f, 32.5f, 37.5f, 42.5f, 47.5f, 52.5f }; private static readonly float[] SprintMeterArcInnerRadii = new float[43] { 148.3f, 146.4f, 155.9f, 153.8f, 159.1f, 157.7f, 154.7f, 144.9f, 145.9f, 140.7f, 134f, 125.9f, 122.8f, 118f, 115.8f, 108.8f, 106.8f, 104f, 97.1f, 100.4f, 98.6f, 97.8f, 97.4f, 97.7f, 98.4f, 96.5f, 100.6f, 102.2f, 104.1f, 107.9f, 111.2f, 114.8f, 119.9f, 125.5f, 129f, 144f, 150.1f, 155.9f, 158f, 165f, 165.2f, 166.8f, 164.5f }; private static readonly float[] SprintMeterArcMiddleRadii = new float[43] { 150.5f, 154.2f, 158.1f, 160.2f, 162.2f, 162f, 159.6f, 155.3f, 151.6f, 145.6f, 139.5f, 133.8f, 128.2f, 123.1f, 120.7f, 113.6f, 111f, 108.3f, 105.6f, 104.3f, 102.6f, 101.6f, 101.5f, 101.5f, 102.1f, 103f, 104.5f, 106.4f, 108.7f, 112.3f, 116.1f, 120.3f, 125.5f, 130.5f, 134.2f, 149.4f, 155.7f, 161.2f, 165.2f, 168.4f, 169.4f, 168.7f, 166.4f }; private static readonly float[] SprintMeterArcOuterRadii = new float[43] { 152.1f, 158.5f, 161.1f, 165.2f, 165.5f, 165.5f, 164.1f, 160.9f, 163.2f, 150.6f, 145.2f, 140.9f, 133.5f, 128.2f, 123.9f, 117.6f, 115.1f, 112.2f, 110.8f, 112.3f, 106.7f, 105.3f, 105.1f, 105.4f, 106.2f, 109.9f, 108.1f, 110.3f, 113f, 116.4f, 120.8f, 127.6f, 130.5f, 135.8f, 139.3f, 154.7f, 161f, 167.2f, 169.6f, 171.7f, 173.9f, 171.2f, 168.6f }; internal void Initialize(ManualLogSource logger, InfectionDataProvider dataProvider, InfectionLayout layout, LanguageHelper languageHelper) { this.logger = logger; this.dataProvider = dataProvider; this.layout = layout; this.languageHelper = languageHelper; SubscribeLayoutConfigEvents(); layoutDirty = true; } private void Update() { Tick(); } internal void Tick() { if (lastTickFrame != Time.frameCount) { lastTickFrame = Time.frameCount; InfectionBarCompatibility.Tick(); if (!InfectionBarCompatibility.HudAllowed) { HideForCompatibility(); return; } ResetSceneCachesIfHudManagerChanged(); PlayerControllerB localPlayer = dataProvider.GetLocalPlayer(); EnsureInfectionUI(localPlayer); UpdateInfection(localPlayer); } } internal void Shutdown() { DestroyInfectionUI(); ClearCachedSceneReferences(); cachedHudManagerInstance = null; cachedStartOfRoundInstance = null; UnsubscribeLayoutConfigEvents(); } private void OnDestroy() { Shutdown(); } private void EnsureInfectionUI(PlayerControllerB player) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_0425: Unknown result type (might be due to invalid IL or missing references) //IL_0434: Unknown result type (might be due to invalid IL or missing references) //IL_0443: Unknown result type (might be due to invalid IL or missing references) //IL_0451: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Unknown result type (might be due to invalid IL or missing references) //IL_0504: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_0525: Unknown result type (might be due to invalid IL or missing references) //IL_0534: Unknown result type (might be due to invalid IL or missing references) //IL_0543: Unknown result type (might be due to invalid IL or missing references) //IL_0565: Unknown result type (might be due to invalid IL or missing references) //IL_056a: Unknown result type (might be due to invalid IL or missing references) //IL_0576: Unknown result type (might be due to invalid IL or missing references) //IL_05fa: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)infectionRoot != (Object)null && hasActiveHudStyle && !hudStyleDirty) { RefreshLayoutIfNeeded(player); return; } HudStyle hudStyle = ResolveHudStyle(); hudStyleDirty = false; if ((Object)(object)infectionRoot != (Object)null) { if (hasActiveHudStyle && activeHudStyle == hudStyle) { RefreshLayoutIfNeeded(player); return; } DestroyInfectionUI(); } if (hudStyle == HudStyle.VanillaStaminaRing) { TryCreateVanillaStaminaRingUI(player); return; } RectTransform nativeHudParentTransform = GetNativeHudParentTransform(); if ((Object)(object)nativeHudParentTransform == (Object)null) { if (ShouldLogDiagnostics() && !loggedMissingNativeHudParent) { logger.LogWarning((object)"Waiting for native HUD parent before creating infection bar UI."); loggedMissingNativeHudParent = true; } return; } loggedMissingNativeHudParent = false; GameObject val = new GameObject("IndependentCadaverInfectionBarRoot", new Type[2] { typeof(RectTransform), typeof(CanvasGroup) }); val.transform.SetParent((Transform)(object)nativeHudParentTransform, false); NativeHudState nativeHudState = GetNativeHudState(); lastVisibleState = false; lastRenderedInfectionFillAmount = -1f; lastRenderedInfectionPercent = -1; lastRenderedInfectionLabel = string.Empty; currentHudAlpha = (nativeHudState.IsValid ? nativeHudState.Alpha : 1f); canvasGroup = val.GetComponent(); canvasGroup.alpha = currentHudAlpha; canvasGroup.ignoreParentGroups = true; canvasGroup.interactable = false; canvasGroup.blocksRaycasts = false; Vector2 effectiveRootSize = GetEffectiveRootSize(); Vector2 effectiveBarSize = GetEffectiveBarSize(); infectionRoot = val.GetComponent(); infectionRoot.anchorMin = layout.GetAnchorMin(); infectionRoot.anchorMax = layout.GetAnchorMax(); infectionRoot.pivot = layout.GetPivot(); infectionRoot.sizeDelta = effectiveRootSize; infectionRoot.anchoredPosition = AlignVector2(layout.GetAnchoredPosition()); ApplyNativeHudElementRotation(); RectTransform val2 = CreateRect("Panel", (Transform)(object)infectionRoot, effectiveRootSize, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(0f, 0f)); panelBackground = ((Component)val2).gameObject.AddComponent(); panelBackground.sprite = GetPixelSprite(); ((Graphic)panelBackground).color = new Color(0.1f, 0.02f, 0.02f, Mathf.Clamp01(ModConfig.PanelBackgroundAlpha.Value)); ((Behaviour)panelBackground).enabled = ModConfig.ShowPanelBackground.Value; RectTransform val3 = CreateRect("TopLine", (Transform)(object)infectionRoot, new Vector2(effectiveBarSize.x, effectiveBarSize.y), new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(0f, 1f)); val3.anchoredPosition = AlignVector2(new Vector2(8f, -6f)); topLine = ((Component)val3).gameObject.AddComponent(); topLine.sprite = GetPixelSprite(); ((Graphic)topLine).color = new Color(0.84f, 0.18f, 0.16f, 0.72f); RectTransform val4 = CreateRect("Background", (Transform)(object)infectionRoot, new Vector2(effectiveBarSize.x, effectiveBarSize.y), new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(0f, 1f)); val4.anchoredPosition = AlignVector2(new Vector2(8f, -6f)); infectionBackground = ((Component)val4).gameObject.AddComponent(); infectionBackground.sprite = GetPixelSprite(); infectionBackground.type = (Type)1; ((Graphic)infectionBackground).color = new Color(0.24f, 0.05f, 0.05f, 0.42f); RectTransform val5 = CreateRect("Fill", (Transform)(object)val4, effectiveBarSize, new Vector2(0f, 0f), new Vector2(1f, 1f), new Vector2(0f, 0f)); val5.anchoredPosition = Vector2.zero; val5.sizeDelta = Vector2.zero; val5.offsetMin = Vector2.zero; val5.offsetMax = Vector2.zero; infectionBar = ((Component)val5).gameObject.AddComponent(); infectionBar.sprite = GetPixelSprite(); infectionBar.type = (Type)3; infectionBar.fillMethod = (FillMethod)0; infectionBar.fillOrigin = 0; infectionBar.fillAmount = 0f; ((Graphic)infectionBar).color = new Color(0.91f, 0.23f, 0.19f, 0.98f); RectTransform val6 = CreateRect("Text", (Transform)(object)infectionRoot, new Vector2(effectiveRootSize.x - 16f, 18f), new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(0f, 0f)); val6.anchoredPosition = AlignVector2(new Vector2(ModConfig.TextOffsetX.Value, ModConfig.TextOffsetY.Value)); ((Transform)val6).localRotation = Quaternion.identity; infectionText = ((Component)val6).gameObject.AddComponent(); infectionText.font = Resources.GetBuiltinResource("Arial.ttf"); infectionText.fontSize = ModConfig.TextFontSize.Value; infectionText.alignment = (TextAnchor)3; infectionText.horizontalOverflow = (HorizontalWrapMode)1; infectionText.verticalOverflow = (VerticalWrapMode)1; ((Graphic)infectionText).color = new Color(0.97f, 0.95f, 0.92f, 0.94f); cachedInfectionLabel = DetermineInfectionLabel(); nextInfectionLabelRefreshTime = Time.unscaledTime + 5f; infectionText.text = cachedInfectionLabel + " 0%"; ((Component)infectionRoot).gameObject.SetActive(false); if (ShouldLogDiagnostics()) { logger.LogInfo((object)"Standalone infection bar UI created. style=Current"); } activeHudStyle = HudStyle.Current; hasActiveHudStyle = true; hudStyleDirty = false; Transform obj = ResolveNativeHudElementTransform(); StartHudIntroAlphaSampling((RectTransform)(((object)((obj is RectTransform) ? obj : null)) ?? ((object)nativeHudParentTransform))); ApplyHudAlpha(currentHudAlpha * GetHudIntroAlphaMultiplier(nativeHudState)); } private HudStyle ResolveHudStyle() { string a = (ModConfig.HudStyleMode?.Value ?? "Auto").Trim(); if (string.Equals(a, "Current", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "CurrentStyle", StringComparison.OrdinalIgnoreCase)) { return HudStyle.Current; } if (string.Equals(a, "Vanilla", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "VanillaStamina", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "VanillaStaminaRing", StringComparison.OrdinalIgnoreCase) || string.Equals(a, "VanillaStaminaRingStyle", StringComparison.OrdinalIgnoreCase)) { return HudStyle.VanillaStaminaRing; } if (!IsEladsHudInstalled()) { return HudStyle.VanillaStaminaRing; } return HudStyle.Current; } private static bool IsEladsHudInstalled() { if (hasCachedEladsHudInstalled) { return cachedEladsHudInstalled; } cachedEladsHudInstalled = DetectEladsHudInstalled(); hasCachedEladsHudInstalled = true; return cachedEladsHudInstalled; } private static bool DetectEladsHudInstalled() { if (Chainloader.PluginInfos.ContainsKey("me.eladnlg.customhud")) { return true; } foreach (PluginInfo value in Chainloader.PluginInfos.Values) { object obj; if (value == null) { obj = null; } else { BepInPlugin metadata = value.Metadata; obj = ((metadata != null) ? metadata.GUID : null); } if (obj == null) { obj = string.Empty; } string text = (string)obj; object obj2; if (value == null) { obj2 = null; } else { BepInPlugin metadata2 = value.Metadata; obj2 = ((metadata2 != null) ? metadata2.Name : null); } if (obj2 == null) { obj2 = string.Empty; } string text2 = (string)obj2; bool flag = text.IndexOf("Elads", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("Elads", StringComparison.OrdinalIgnoreCase) >= 0; bool flag2 = text.IndexOf("HUD", StringComparison.OrdinalIgnoreCase) >= 0 || text2.IndexOf("HUD", StringComparison.OrdinalIgnoreCase) >= 0; if (flag && flag2) { return true; } } return false; } private bool TryCreateVanillaStaminaRingUI(PlayerControllerB player) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: 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) if (!TryGetSprintMeter(player, out var sprintMeterImage, out var sprintMeterRect)) { if (ShouldLogDiagnostics() && !loggedMissingSprintMeter) { logger.LogWarning((object)"Waiting for original sprint meter UI before creating vanilla infection ring."); loggedMissingSprintMeter = true; } return false; } Transform parent = ((Transform)sprintMeterRect).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)val == (Object)null) { if (ShouldLogDiagnostics() && !loggedMissingSprintMeter) { logger.LogWarning((object)"Original sprint meter UI has no RectTransform parent."); loggedMissingSprintMeter = true; } return false; } loggedMissingSprintMeter = false; LogVanillaSprintMeterDiagnostics(sprintMeterImage, sprintMeterRect); GameObject val2 = new GameObject("IndependentCadaverInfectionBarVanillaStaminaRingRoot", new Type[2] { typeof(RectTransform), typeof(CanvasGroup) }); val2.transform.SetParent((Transform)(object)val, false); NativeHudState nativeHudState = GetNativeHudState(); lastVisibleState = false; lastRenderedInfectionFillAmount = -1f; lastRenderedInfectionPercent = -1; lastRenderedInfectionLabel = string.Empty; currentHudAlpha = (nativeHudState.IsValid ? nativeHudState.Alpha : 1f); canvasGroup = val2.GetComponent(); canvasGroup.alpha = currentHudAlpha; canvasGroup.ignoreParentGroups = true; canvasGroup.interactable = false; canvasGroup.blocksRaycasts = false; infectionRoot = val2.GetComponent(); vanillaSprintMeterReference = sprintMeterImage; ApplyVanillaStaminaRingTransform(sprintMeterRect); RectTransform val3 = CreateRect("VanillaRingBackground", (Transform)(object)infectionRoot, Vector2.zero, Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f)); StretchToParent(val3); infectionBackground = ((Component)val3).gameObject.AddComponent(); CopySprintMeterImageStyle(sprintMeterImage, infectionBackground, new Color(0.34f, 0.05f, 0.04f, 0.42f)); ApplyVanillaRingFillAmount(infectionBackground, 1f); RectTransform val4 = CreateRect("VanillaRingFill", (Transform)(object)infectionRoot, Vector2.zero, Vector2.zero, Vector2.one, new Vector2(0.5f, 0.5f)); StretchToParent(val4); infectionBar = ((Component)val4).gameObject.AddComponent(); CopySprintMeterImageStyle(sprintMeterImage, infectionBar, new Color(0.91f, 0.18f, 0.13f, 0.95f)); ApplyVanillaRingFillAmount(infectionBar, 0f); CreateVanillaArcTexts(sprintMeterRect); cachedInfectionLabel = DetermineInfectionLabel(); nextInfectionLabelRefreshTime = Time.unscaledTime + 5f; SetInfectionText(FormatInfectionText(cachedInfectionLabel, 0)); ((Component)infectionRoot).gameObject.SetActive(false); if ((Object)(object)vanillaWeightTextRoot != (Object)null) { ((Component)vanillaWeightTextRoot).gameObject.SetActive(false); } if ((Object)(object)vanillaInfectionTextRoot != (Object)null) { ((Component)vanillaInfectionTextRoot).gameObject.SetActive(false); } if ((Object)(object)vanillaInfectionValueTextRoot != (Object)null) { ((Component)vanillaInfectionValueTextRoot).gameObject.SetActive(false); } activeHudStyle = HudStyle.VanillaStaminaRing; hasActiveHudStyle = true; hudStyleDirty = false; layoutDirty = false; StartHudIntroAlphaSampling(sprintMeterRect); ApplyHudAlpha(currentHudAlpha * GetHudIntroAlphaMultiplier(nativeHudState)); if (ShouldLogDiagnostics()) { logger.LogInfo((object)"Standalone infection bar UI created. style=VanillaStaminaRing"); } return true; } private static bool TryGetSprintMeter(PlayerControllerB player, out Image sprintMeterImage, out RectTransform sprintMeterRect) { sprintMeterImage = player?.sprintMeterUI; sprintMeterRect = (((Object)(object)sprintMeterImage != (Object)null) ? ((Graphic)sprintMeterImage).rectTransform : null); if ((Object)(object)sprintMeterImage != (Object)null) { return (Object)(object)sprintMeterRect != (Object)null; } return false; } private void RefreshVanillaStaminaRingLayout(PlayerControllerB player) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) if (!TryGetSprintMeter(player, out var sprintMeterImage, out var sprintMeterRect)) { return; } Transform parent = ((Transform)sprintMeterRect).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); int num; if ((Object)(object)val != (Object)null) { num = (((Object)(object)((Transform)infectionRoot).parent != (Object)(object)val) ? 1 : 0); if (num != 0) { ((Transform)infectionRoot).SetParent((Transform)(object)val, false); } } else { num = 0; } vanillaSprintMeterReference = sprintMeterImage; bool flag = ShouldForceVanillaHudLiveLayoutRefresh(); bool flag2 = ((uint)num | (flag ? 1u : 0u)) != 0 || layoutDirty || HasVanillaSprintMeterLayoutChanged(sprintMeterRect); if (flag2) { ApplyVanillaStaminaRingTransform(sprintMeterRect); RefreshVanillaArcTextLayout(sprintMeterRect, forceTextRefresh: true); CopySprintMeterImageStyle(sprintMeterImage, infectionBackground, new Color(0.34f, 0.05f, 0.04f, 0.42f)); CopySprintMeterImageStyle(sprintMeterImage, infectionBar, new Color(0.91f, 0.18f, 0.13f, 0.95f)); ApplyVanillaRingFillAmount(infectionBackground, 1f); ApplyVanillaRingFillAmount(infectionBar, (lastRenderedInfectionFillAmount >= 0f) ? VanillaRingFillMapping.MapInfectionToVisibleFill(lastRenderedInfectionFillAmount) : infectionBar.fillAmount); CaptureVanillaSprintMeterLayoutSignature(sprintMeterRect); layoutDirty = false; } SetOriginalWeightCounterHidden(ModConfig.InfectionBarEnabled.Value); UpdateVanillaWeightText(flag || flag2); ApplyVanillaInfectionTextSegments(flag || flag2); } private void CreateVanillaArcTexts(RectTransform sprintMeterRect) { Transform parent = ((Transform)sprintMeterRect).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if (!((Object)(object)val == (Object)null)) { CreateVanillaArcTextRoot("IndependentCadaverInfectionBarVanillaWeightText", val, out vanillaWeightTextRoot, out vanillaWeightTextCanvasGroup); CreateVanillaArcTextRoot("IndependentCadaverInfectionBarVanillaInfectionText", val, out vanillaInfectionTextRoot, out vanillaInfectionTextCanvasGroup); CreateVanillaArcTextRoot("IndependentCadaverInfectionBarVanillaInfectionValueText", val, out vanillaInfectionValueTextRoot, out vanillaInfectionValueTextCanvasGroup); UpdateVanillaWeightText(force: true); RefreshVanillaArcTextLayout(sprintMeterRect, forceTextRefresh: true); } } private void CreateVanillaArcTextRoot(string name, RectTransform parent, out RectTransform root, out CanvasGroup group) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown GameObject val = new GameObject(name, new Type[2] { typeof(RectTransform), typeof(CanvasGroup) }); val.transform.SetParent((Transform)(object)parent, false); root = val.GetComponent(); group = val.GetComponent(); group.alpha = currentHudAlpha; group.ignoreParentGroups = true; group.interactable = false; group.blocksRaycasts = false; ((Component)root).gameObject.SetActive(false); } private void RefreshVanillaArcTextLayout(RectTransform sprintMeterRect, bool forceTextRefresh) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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_00f1: 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_011b: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: 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) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)vanillaWeightTextRoot == (Object)null) && !((Object)(object)vanillaInfectionTextRoot == (Object)null) && !((Object)(object)vanillaInfectionValueTextRoot == (Object)null)) { Transform parent = ((Transform)sprintMeterRect).parent; RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)val != (Object)null && (Object)(object)((Transform)vanillaWeightTextRoot).parent != (Object)(object)val) { ((Transform)vanillaWeightTextRoot).SetParent((Transform)(object)val, false); ((Transform)vanillaInfectionTextRoot).SetParent((Transform)(object)val, false); ((Transform)vanillaInfectionValueTextRoot).SetParent((Transform)(object)val, false); } Vector2 val2 = sprintMeterRect.anchoredPosition + GetVanillaOuterRingOffset(sprintMeterRect) + new Vector2(ModConfig.VanillaRingOffsetX.Value, ModConfig.VanillaRingOffsetY.Value); Vector2 rectReferenceSize = GetRectReferenceSize(sprintMeterRect); float num = Mathf.Max(0.1f, ModConfig.VanillaRingScale.Value); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(Mathf.Abs(rectReferenceSize.x) * num, Mathf.Abs(rectReferenceSize.y) * num); bool num2 = lastVisibleState; ApplyVanillaTextRect(position: num2 ? val2 : sprintMeterRect.anchoredPosition, size: (Vector2)(num2 ? val3 : new Vector2(Mathf.Abs(rectReferenceSize.x), Mathf.Abs(rectReferenceSize.y))), rect: vanillaWeightTextRoot, anchorMin: sprintMeterRect.anchorMin, anchorMax: sprintMeterRect.anchorMax, pivot: new Vector2(0.5f, 0.5f), rotation: ((Transform)sprintMeterRect).localRotation, scale: ((Transform)sprintMeterRect).localScale); ApplyVanillaTextRect(vanillaInfectionTextRoot, sprintMeterRect.anchorMin, sprintMeterRect.anchorMax, new Vector2(0.5f, 0.5f), val3, val2, ((Transform)sprintMeterRect).localRotation, ((Transform)sprintMeterRect).localScale); ApplyVanillaTextRect(vanillaInfectionValueTextRoot, sprintMeterRect.anchorMin, sprintMeterRect.anchorMax, new Vector2(0.5f, 0.5f), val3, val2, ((Transform)sprintMeterRect).localRotation, ((Transform)sprintMeterRect).localScale); UpdateVanillaWeightText(forceTextRefresh); ApplyVanillaInfectionTextSegments(forceTextRefresh); } } private bool HasVanillaSprintMeterLayoutChanged(RectTransform sprintMeterRect) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0039: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_00d8: 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_00e2: Unknown result type (might be due to invalid IL or missing references) if (!hasVanillaLayoutSignature) { return true; } Vector2 val = lastVanillaAnchorMin - sprintMeterRect.anchorMin; if (!(((Vector2)(ref val)).sqrMagnitude > 0.0001f)) { val = lastVanillaAnchorMax - sprintMeterRect.anchorMax; if (!(((Vector2)(ref val)).sqrMagnitude > 0.0001f)) { val = lastVanillaPivot - sprintMeterRect.pivot; if (!(((Vector2)(ref val)).sqrMagnitude > 0.0001f)) { val = lastVanillaSizeDelta - sprintMeterRect.sizeDelta; if (!(((Vector2)(ref val)).sqrMagnitude > 0.0001f)) { val = lastVanillaAnchoredPosition - sprintMeterRect.anchoredPosition; if (!(((Vector2)(ref val)).sqrMagnitude > 0.0001f) && !(Quaternion.Angle(lastVanillaLocalRotation, ((Transform)sprintMeterRect).localRotation) > 0.01f)) { Vector3 val2 = lastVanillaLocalScale - ((Transform)sprintMeterRect).localScale; if (!(((Vector3)(ref val2)).sqrMagnitude > 0.0001f) && !(Mathf.Abs(lastVanillaRingScale - ModConfig.VanillaRingScale.Value) > 0.0001f) && !(Mathf.Abs(lastVanillaRingOffsetX - ModConfig.VanillaRingOffsetX.Value) > 0.0001f)) { return Mathf.Abs(lastVanillaRingOffsetY - ModConfig.VanillaRingOffsetY.Value) > 0.0001f; } } } } } } return true; } private void CaptureVanillaSprintMeterLayoutSignature(RectTransform sprintMeterRect) { //IL_0009: 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_0039: 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_0045: 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_0051: 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) hasVanillaLayoutSignature = true; lastVanillaAnchorMin = sprintMeterRect.anchorMin; lastVanillaAnchorMax = sprintMeterRect.anchorMax; lastVanillaPivot = sprintMeterRect.pivot; lastVanillaSizeDelta = sprintMeterRect.sizeDelta; lastVanillaAnchoredPosition = sprintMeterRect.anchoredPosition; lastVanillaLocalRotation = ((Transform)sprintMeterRect).localRotation; lastVanillaLocalScale = ((Transform)sprintMeterRect).localScale; lastVanillaRingScale = ModConfig.VanillaRingScale.Value; lastVanillaRingOffsetX = ModConfig.VanillaRingOffsetX.Value; lastVanillaRingOffsetY = ModConfig.VanillaRingOffsetY.Value; } private static bool ShouldForceVanillaHudLiveLayoutRefresh() { return ModConfig.DebugVanillaHudLiveLayoutRefresh?.Value ?? false; } private void ApplyOrRestoreVanillaWarningTextOffset(bool infectionRingVisible) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //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_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: 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) if (!(activeHudStyle == HudStyle.VanillaStaminaRing && infectionRingVisible) || !ModConfig.InfectionBarEnabled.Value || !ModConfig.VanillaWarningTextOffsetEnabled.Value) { RestoreVanillaWarningTextOffset(); return; } RectTransform val = ResolveVanillaWarningRoot(); if ((Object)(object)val == (Object)null) { if (ShouldLogDiagnostics() && !loggedMissingVanillaWarningRoot) { logger.LogWarning((object)"Waiting for original warning text root before applying vanilla HUD warning text offset."); loggedMissingVanillaWarningRoot = true; } return; } loggedMissingVanillaWarningRoot = false; if ((Object)(object)shiftedVanillaWarningRoot != (Object)(object)val) { RestoreVanillaWarningTextOffset(); shiftedVanillaWarningRoot = val; originalVanillaWarningAnchoredPosition = val.anchoredPosition; hasOriginalVanillaWarningAnchoredPosition = true; } if (!hasOriginalVanillaWarningAnchoredPosition) { originalVanillaWarningAnchoredPosition = val.anchoredPosition; hasOriginalVanillaWarningAnchoredPosition = true; } VanillaWarningTextOffsetCalculator.CalculateShiftedPosition(enabled: true, originalVanillaWarningAnchoredPosition.x, originalVanillaWarningAnchoredPosition.y, ModConfig.VanillaWarningTextOffsetX.Value, ModConfig.VanillaWarningTextOffsetY.Value, out var shiftedX, out var shiftedY); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(shiftedX, shiftedY); Vector2 val3 = val.anchoredPosition - val2; if (((Vector2)(ref val3)).sqrMagnitude > 0.0001f) { val.anchoredPosition = val2; } } private void RestoreVanillaWarningTextOffset() { //IL_002f: 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_001d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)shiftedVanillaWarningRoot != (Object)null && hasOriginalVanillaWarningAnchoredPosition) { shiftedVanillaWarningRoot.anchoredPosition = originalVanillaWarningAnchoredPosition; } shiftedVanillaWarningRoot = null; originalVanillaWarningAnchoredPosition = Vector2.zero; hasOriginalVanillaWarningAnchoredPosition = false; loggedMissingVanillaWarningRoot = false; } private static RectTransform ResolveVanillaWarningRoot() { if ((Object)(object)cachedVanillaWarningRoot != (Object)null) { return cachedVanillaWarningRoot; } if (Time.unscaledTime < nextVanillaWarningRootLookupTime) { return null; } nextVanillaWarningRootLookupTime = Time.unscaledTime + 1f; HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { return null; } if ((Object)(object)instance.statusEffectText != (Object)null) { cachedVanillaWarningRoot = ((TMP_Text)instance.statusEffectText).rectTransform; return cachedVanillaWarningRoot; } if (hudRadiationGraphicAnimatorField == null) { hudRadiationGraphicAnimatorField = typeof(HUDManager).GetField("radiationGraphicAnimator", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } object? obj = hudRadiationGraphicAnimatorField?.GetValue(instance); Component val = (Component)((obj is Component) ? obj : null); if (val != null) { Transform transform = val.transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (val2 != null) { cachedVanillaWarningRoot = val2; return cachedVanillaWarningRoot; } } Transform[] componentsInChildren = ((Component)instance).GetComponentsInChildren(true); foreach (Transform val3 in componentsInChildren) { RectTransform val4 = (RectTransform)(object)((val3 is RectTransform) ? val3 : null); if (val4 != null && IsVanillaWarningRoot(val3)) { cachedVanillaWarningRoot = val4; return cachedVanillaWarningRoot; } } return null; } private static bool IsVanillaWarningRoot(Transform transform) { if ((Object)(object)transform != (Object)null && string.Equals(((Object)transform).name, "RadiationIncrease", StringComparison.OrdinalIgnoreCase)) { return GetHierarchyPath(transform).EndsWith("IngamePlayerHUD/SpecialHUDGraphics/RadiationIncrease", StringComparison.OrdinalIgnoreCase); } return false; } private static void GetVanillaArcParameters(VanillaArcTextSlot slot, int textLength, out float startAngle, out float endAngle, out VanillaArcRadiusBand radiusBand, out float radiusOffsetPixels) { float num; float num2; float num3; switch (slot) { case VanillaArcTextSlot.WeightInfectionInner: num = 24f; num2 = 16f; num3 = 4.8f; radiusBand = VanillaArcRadiusBand.Outer; radiusOffsetPixels = 86f; break; case VanillaArcTextSlot.InfectionOuter: num = 42f; num2 = 22f; num3 = 4.4f; radiusBand = VanillaArcRadiusBand.Outer; radiusOffsetPixels = 150f; break; default: num = 43f; num2 = 16f; num3 = 4.8f; radiusBand = VanillaArcRadiusBand.Outer; radiusOffsetPixels = 92f; break; } float num4 = ((textLength <= 1) ? 0f : Mathf.Min(num2, num3 * (float)(textLength - 1))); startAngle = num + num4 * 0.5f; endAngle = num - num4 * 0.5f; } private static float GetVanillaArcCharacterRotation(float angle, VanillaArcTextSlot slot) { return slot switch { VanillaArcTextSlot.WeightInfectionInner => Mathf.Clamp(angle - 56f, -42f, -10f), VanillaArcTextSlot.InfectionOuter => Mathf.Clamp(angle - 58f, -48f, -10f), _ => Mathf.Clamp(angle - 54f, -36f, -8f), }; } private static float GetVanillaArcFontScale(VanillaArcTextSlot slot) { return slot switch { VanillaArcTextSlot.InfectionOuter => 0.62f, VanillaArcTextSlot.WeightInfectionInner => 0.6f, _ => 0.66f, }; } private static float GetVanillaArcCharacterClearancePixels(VanillaArcTextSlot slot) { return slot switch { VanillaArcTextSlot.WeightInfectionInner => 78f, VanillaArcTextSlot.InfectionOuter => 118f, _ => 70f, }; } private static float GetSprintMeterArcRadius(float angle, VanillaArcRadiusBand band) { float[] array = band switch { VanillaArcRadiusBand.Outer => SprintMeterArcOuterRadii, VanillaArcRadiusBand.Inner => SprintMeterArcInnerRadii, _ => SprintMeterArcMiddleRadii, }; if (angle <= SprintMeterArcAngles[0]) { return array[0]; } int num = SprintMeterArcAngles.Length - 1; if (angle >= SprintMeterArcAngles[num]) { return array[num]; } for (int i = 0; i < num; i++) { float num2 = SprintMeterArcAngles[i]; float num3 = SprintMeterArcAngles[i + 1]; if (!(angle < num2) && !(angle > num3)) { float num4 = Mathf.InverseLerp(num2, num3, angle); return Mathf.Lerp(array[i], array[i + 1], num4); } } return array[num]; } private static float ApplyVanillaArcTextClearance(float angle, float radius, VanillaArcTextSlot slot, VanillaArcRadiusBand band) { float vanillaArcCharacterClearancePixels = GetVanillaArcCharacterClearancePixels(slot); GetSprintMeterArcRadius(angle, VanillaArcRadiusBand.Inner); float sprintMeterArcRadius = GetSprintMeterArcRadius(angle, VanillaArcRadiusBand.Outer); return slot switch { VanillaArcTextSlot.WeightInfectionInner => Mathf.Max(radius, sprintMeterArcRadius + vanillaArcCharacterClearancePixels), VanillaArcTextSlot.InfectionOuter => Mathf.Max(radius, sprintMeterArcRadius + vanillaArcCharacterClearancePixels), _ => Mathf.Max(radius, sprintMeterArcRadius + vanillaArcCharacterClearancePixels), }; } private static void ApplyVanillaTextRect(RectTransform rect, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 size, Vector2 position, Quaternion rotation, Vector3 scale) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = anchorMin; rect.anchorMax = anchorMax; rect.pivot = pivot; rect.sizeDelta = size; rect.anchoredPosition = position; ((Transform)rect).localRotation = rotation; ((Transform)rect).localScale = scale; } private static void ApplyVanillaArcText(RectTransform root, string text, Color color, VanillaArcTextSlot slot) { //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) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return; } string text2 = text ?? string.Empty; DisableRootText(root); SetUnusedVanillaArcCharactersInactive(root, text2.Length); if (text2.Length == 0) { return; } Vector2 sizeDelta = root.sizeDelta; if (((Vector2)(ref sizeDelta)).sqrMagnitude < 0.0001f) { ((Vector2)(ref sizeDelta))..ctor(80f, 80f); } VanillaArcGlyphLayout[] array = VanillaArcTextLayout.Build(text2, GetVanillaArcTextTrack(slot), Mathf.Abs(sizeDelta.x), Mathf.Abs(sizeDelta.y)); for (int i = 0; i < array.Length; i++) { VanillaArcGlyphLayout vanillaArcGlyphLayout = array[i]; RectTransform orCreateVanillaArcCharacter = GetOrCreateVanillaArcCharacter(root, i); TextMeshProUGUI component = ((Component)orCreateVanillaArcCharacter).GetComponent(); ((Component)orCreateVanillaArcCharacter).gameObject.SetActive(true); orCreateVanillaArcCharacter.anchoredPosition = new Vector2(vanillaArcGlyphLayout.LocalX, vanillaArcGlyphLayout.LocalY); ((Transform)orCreateVanillaArcCharacter).localRotation = Quaternion.Euler(0f, 0f, vanillaArcGlyphLayout.RotationZ); ((Transform)orCreateVanillaArcCharacter).localScale = Vector3.one; string text3 = vanillaArcGlyphLayout.Character.ToString(); if (!string.Equals(((TMP_Text)component).text, text3, StringComparison.Ordinal)) { ((TMP_Text)component).text = text3; } CopyWeightCounterTextStyle(component, color); ((TMP_Text)component).fontSize = ((TMP_Text)component).fontSize * vanillaArcGlyphLayout.FontScale; ((TMP_Text)component).alignment = (TextAlignmentOptions)514; ((Graphic)component).raycastTarget = false; ((TMP_Text)component).enableWordWrapping = false; ((TMP_Text)component).overflowMode = (TextOverflowModes)0; } } private static VanillaArcTextTrack GetVanillaArcTextTrack(VanillaArcTextSlot slot) { return slot switch { VanillaArcTextSlot.WeightInfectionInner => VanillaArcTextTrack.InfectionWeightInner, VanillaArcTextSlot.InfectionOuter => VanillaArcTextTrack.InfectionLabelOuter, _ => VanillaArcTextTrack.StaminaWeightUpper, }; } private static void DisableRootText(RectTransform root) { TextMeshProUGUI component = ((Component)root).GetComponent(); if (!((Object)(object)component == (Object)null)) { ((Behaviour)component).enabled = false; ((TMP_Text)component).text = string.Empty; } } private static RectTransform GetOrCreateVanillaArcCharacter(RectTransform root, int index) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) string text = "VanillaArcChar_" + index.ToString("00"); Transform val = ((Transform)root).Find(text); if ((Object)(object)val != (Object)null) { return (RectTransform)(object)((val is RectTransform) ? val : null); } GameObject val2 = new GameObject(text, new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); val2.transform.SetParent((Transform)(object)root, false); RectTransform component = val2.GetComponent(); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.sizeDelta = new Vector2(36f, 36f); TextMeshProUGUI component2 = val2.GetComponent(); ((Graphic)component2).raycastTarget = false; ((TMP_Text)component2).enableWordWrapping = false; ((TMP_Text)component2).overflowMode = (TextOverflowModes)0; ((TMP_Text)component2).alignment = (TextAlignmentOptions)514; return component; } private static void SetUnusedVanillaArcCharactersInactive(RectTransform root, int activeCount) { for (int i = 0; i < ((Transform)root).childCount; i++) { Transform child = ((Transform)root).GetChild(i); if (((Object)child).name.StartsWith("VanillaArcChar_", StringComparison.Ordinal) && int.TryParse(((Object)child).name.Substring("VanillaArcChar_".Length), out var result)) { ((Component)child).gameObject.SetActive(result < activeCount); } } } private static void CopyWeightCounterTextStyle(TextMeshProUGUI target, Color color) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null)) { TextMeshProUGUI val = HUDManager.Instance?.weightCounter; if ((Object)(object)val != (Object)null) { ((TMP_Text)target).font = ((TMP_Text)val).font; ((TMP_Text)target).fontSharedMaterial = ((TMP_Text)val).fontSharedMaterial; ((TMP_Text)target).fontSize = ((TMP_Text)val).fontSize; ((TMP_Text)target).fontStyle = ((TMP_Text)val).fontStyle; ((TMP_Text)target).alignment = ((TMP_Text)val).alignment; ((TMP_Text)target).characterSpacing = ((TMP_Text)val).characterSpacing; ((TMP_Text)target).wordSpacing = ((TMP_Text)val).wordSpacing; ((TMP_Text)target).lineSpacing = ((TMP_Text)val).lineSpacing; } else { ((TMP_Text)target).fontSize = 16f; ((TMP_Text)target).alignment = (TextAlignmentOptions)514; } ((Graphic)target).color = color; } } private void UpdateVanillaWeightText(bool force = false) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_005d: 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) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI val = HUDManager.Instance?.weightCounter; string text = (((Object)(object)val != (Object)null) ? ((TMP_Text)val).text : string.Empty); VanillaArcTextSlot vanillaArcTextSlot = (lastVisibleState ? VanillaArcTextSlot.WeightInfectionInner : VanillaArcTextSlot.WeightStaminaUpper); Vector2 val2 = (((Object)(object)vanillaWeightTextRoot != (Object)null) ? vanillaWeightTextRoot.sizeDelta : Vector2.zero); Vector2 val3 = lastAppliedVanillaWeightRootSize - val2; bool flag = ((Vector2)(ref val3)).sqrMagnitude > 0.0001f; lastVanillaWeightText = text; if (force || !hasAppliedVanillaWeightText || lastAppliedVanillaWeightSlot != vanillaArcTextSlot || flag || !string.Equals(lastAppliedVanillaWeightText, text, StringComparison.Ordinal)) { ApplyVanillaArcText(vanillaWeightTextRoot, text, new Color(0.95f, 0.4f, 0.04f, 0.96f), vanillaArcTextSlot); lastAppliedVanillaWeightText = text; lastAppliedVanillaWeightSlot = vanillaArcTextSlot; lastAppliedVanillaWeightRootSize = val2; hasAppliedVanillaWeightText = true; } } private void ApplyVanillaInfectionTextSegments(bool force = false) { //IL_001b: 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_0020: 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_0027: 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_0084: 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_00d3: Unknown result type (might be due to invalid IL or missing references) Vector2 val = (((Object)(object)vanillaInfectionTextRoot != (Object)null) ? vanillaInfectionTextRoot.sizeDelta : Vector2.zero); Vector2 val2 = lastAppliedVanillaInfectionRootSize - val; bool flag = ((Vector2)(ref val2)).sqrMagnitude > 0.0001f; if (force || !hasAppliedVanillaInfectionText || flag || !string.Equals(lastAppliedVanillaInfectionText, lastVanillaInfectionText, StringComparison.Ordinal)) { ApplyVanillaArcText(vanillaInfectionTextRoot, lastVanillaInfectionText, new Color(0.95f, 0.26f, 0.18f, 0.95f), VanillaArcTextSlot.InfectionOuter); lastAppliedVanillaInfectionText = lastVanillaInfectionText; lastAppliedVanillaInfectionRootSize = val; hasAppliedVanillaInfectionText = true; } if (force || !hasClearedVanillaInfectionValueText) { ApplyVanillaArcText(vanillaInfectionValueTextRoot, string.Empty, new Color(0.95f, 0.26f, 0.18f, 0.95f), VanillaArcTextSlot.InfectionOuter); hasClearedVanillaInfectionValueText = true; } } private void SetOriginalWeightCounterHidden(bool hidden) { TextMeshProUGUI val = HUDManager.Instance?.weightCounter; if (!hidden) { RestoreOriginalWeightCounter(); } else if (!((Object)(object)val == (Object)null)) { if ((Object)(object)hiddenWeightCounter != (Object)(object)val) { RestoreOriginalWeightCounter(); hiddenWeightCounter = val; hiddenWeightCounterWasEnabled = ((Behaviour)val).enabled; } if (((Behaviour)val).enabled) { ((Behaviour)val).enabled = false; } } } private void RestoreOriginalWeightCounter() { if ((Object)(object)hiddenWeightCounter != (Object)null && ((Behaviour)hiddenWeightCounter).enabled != hiddenWeightCounterWasEnabled) { ((Behaviour)hiddenWeightCounter).enabled = hiddenWeightCounterWasEnabled; } hiddenWeightCounter = null; hiddenWeightCounterWasEnabled = false; } private static Vector2 GetRectReferenceSize(RectTransform rectTransform) { //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_0009: 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_0024: 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_0023: Unknown result type (might be due to invalid IL or missing references) Rect rect = rectTransform.rect; Vector2 result = ((Rect)(ref rect)).size; if (((Vector2)(ref result)).sqrMagnitude < 0.0001f) { result = rectTransform.sizeDelta; } return result; } private void ApplyVanillaStaminaRingTransform(RectTransform sprintMeterRect) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0045: 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_005c: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(0.1f, ModConfig.VanillaRingScale.Value); Vector2 vanillaOuterRingOffset = GetVanillaOuterRingOffset(sprintMeterRect); infectionRoot.anchorMin = sprintMeterRect.anchorMin; infectionRoot.anchorMax = sprintMeterRect.anchorMax; infectionRoot.pivot = sprintMeterRect.pivot; infectionRoot.sizeDelta = sprintMeterRect.sizeDelta * num; infectionRoot.anchoredPosition = sprintMeterRect.anchoredPosition + vanillaOuterRingOffset + new Vector2(ModConfig.VanillaRingOffsetX.Value, ModConfig.VanillaRingOffsetY.Value); ((Transform)infectionRoot).localRotation = ((Transform)sprintMeterRect).localRotation; ((Transform)infectionRoot).localScale = ((Transform)sprintMeterRect).localScale; } private static Vector2 GetVanillaOuterRingOffset(RectTransform sprintMeterRect) { //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_000c: 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_0040: Unknown result type (might be due to invalid IL or missing references) Vector2 rectReferenceSize = GetRectReferenceSize(sprintMeterRect); float num = Mathf.Max(28f, Mathf.Abs(rectReferenceSize.x) * 0.08f); float num2 = 0f - Mathf.Max(18f, Mathf.Abs(rectReferenceSize.y) * 0.1f); return new Vector2(num, num2); } private static void CopySprintMeterImageStyle(Image source, Image target, Color color) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null)) { target.sprite = source.sprite; target.overrideSprite = source.overrideSprite; ((Graphic)target).material = ((Graphic)source).material; target.type = source.type; target.fillMethod = source.fillMethod; target.fillOrigin = source.fillOrigin; target.fillClockwise = source.fillClockwise; target.fillCenter = source.fillCenter; target.preserveAspect = source.preserveAspect; target.pixelsPerUnitMultiplier = source.pixelsPerUnitMultiplier; ((Graphic)target).color = color; ((Graphic)target).raycastTarget = false; } } private static void ApplyVanillaRingFillAmount(Image target, float fillAmount) { if (!((Object)(object)target == (Object)null)) { target.type = (Type)3; target.fillAmount = Mathf.Clamp01(fillAmount); ((Graphic)target).raycastTarget = false; } } private static void StretchToParent(RectTransform rectTransform) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.pivot = new Vector2(0.5f, 0.5f); rectTransform.anchoredPosition = Vector2.zero; rectTransform.sizeDelta = Vector2.zero; rectTransform.offsetMin = Vector2.zero; rectTransform.offsetMax = Vector2.zero; } private void LogVanillaSprintMeterDiagnostics(Image sprintMeterImage, RectTransform sprintMeterRect) { //IL_00c8: 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_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) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) if (ShouldLogDiagnostics() && !loggedVanillaSprintMeterDiagnostics) { loggedVanillaSprintMeterDiagnostics = true; string text = (((Object)(object)sprintMeterImage.sprite != (Object)null) ? ((Object)sprintMeterImage.sprite).name : ""); string text2 = (((Object)(object)sprintMeterImage.overrideSprite != (Object)null) ? ((Object)sprintMeterImage.overrideSprite).name : ""); string text3 = (((Object)(object)((Graphic)sprintMeterImage).material != (Object)null) ? ((Object)((Graphic)sprintMeterImage).material).name : ""); ManualLogSource obj = logger; string[] obj2 = new string[30] { "Original sprint meter UI found: path=", GetHierarchyPath((Transform)(object)sprintMeterRect), ", sprite=", text, ", overrideSprite=", text2, ", material=", text3, ", type=", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null }; Type type = sprintMeterImage.type; obj2[9] = ((object)(Type)(ref type)).ToString(); obj2[10] = ", fillMethod="; FillMethod fillMethod = sprintMeterImage.fillMethod; obj2[11] = ((object)(FillMethod)(ref fillMethod)).ToString(); obj2[12] = ", fillOrigin="; obj2[13] = sprintMeterImage.fillOrigin.ToString(); obj2[14] = ", fillClockwise="; obj2[15] = sprintMeterImage.fillClockwise.ToString(); obj2[16] = ", fillAmount="; obj2[17] = sprintMeterImage.fillAmount.ToString(); obj2[18] = ", anchorMin="; Vector2 val = sprintMeterRect.anchorMin; obj2[19] = ((object)(Vector2)(ref val)).ToString(); obj2[20] = ", anchorMax="; val = sprintMeterRect.anchorMax; obj2[21] = ((object)(Vector2)(ref val)).ToString(); obj2[22] = ", pivot="; val = sprintMeterRect.pivot; obj2[23] = ((object)(Vector2)(ref val)).ToString(); obj2[24] = ", sizeDelta="; val = sprintMeterRect.sizeDelta; obj2[25] = ((object)(Vector2)(ref val)).ToString(); obj2[26] = ", anchoredPosition="; val = sprintMeterRect.anchoredPosition; obj2[27] = ((object)(Vector2)(ref val)).ToString(); obj2[28] = ", localRotation="; Vector3 localEulerAngles = ((Transform)sprintMeterRect).localEulerAngles; obj2[29] = ((object)(Vector3)(ref localEulerAngles)).ToString(); obj.LogInfo((object)string.Concat(obj2)); } } private void ResetSceneCachesIfHudManagerChanged() { HUDManager instance = HUDManager.Instance; StartOfRound instance2 = StartOfRound.Instance; if (!((Object)(object)cachedHudManagerInstance == (Object)(object)instance) || !((Object)(object)cachedStartOfRoundInstance == (Object)(object)instance2)) { cachedHudManagerInstance = instance; cachedStartOfRoundInstance = instance2; ClearCachedSceneReferences(); dataProvider.ResetCadaverGrowthCache(); DestroyInfectionUI(); } } private static void ClearCachedSceneReferences() { cachedTerminal = null; cachedNativeHudElementTransform = null; cachedNativeHudParentFallback = null; cachedVanillaWarningRoot = null; cachedNativeHudState = default(NativeHudState); nextTerminalLookupTime = 0f; nextNativeHudElementLookupTime = 0f; nextNativeHudParentFallbackLookupTime = 0f; nextVanillaWarningRootLookupTime = 0f; nextNativeHudStateRefreshTime = 0f; } private void DestroyInfectionUI() { //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) RestoreVanillaWarningTextOffset(); if ((Object)(object)infectionRoot != (Object)null) { Object.Destroy((Object)(object)((Component)infectionRoot).gameObject); } canvasGroup = null; infectionRoot = null; panelBackground = null; topLine = null; infectionBackground = null; infectionBar = null; infectionText = null; vanillaSprintMeterReference = null; RestoreOriginalWeightCounter(); if ((Object)(object)vanillaWeightTextRoot != (Object)null) { Object.Destroy((Object)(object)((Component)vanillaWeightTextRoot).gameObject); } if ((Object)(object)vanillaInfectionTextRoot != (Object)null) { Object.Destroy((Object)(object)((Component)vanillaInfectionTextRoot).gameObject); } if ((Object)(object)vanillaInfectionValueTextRoot != (Object)null) { Object.Destroy((Object)(object)((Component)vanillaInfectionValueTextRoot).gameObject); } vanillaWeightTextRoot = null; vanillaWeightTextCanvasGroup = null; vanillaInfectionTextRoot = null; vanillaInfectionTextCanvasGroup = null; vanillaInfectionValueTextRoot = null; vanillaInfectionValueTextCanvasGroup = null; lastVanillaWeightText = string.Empty; lastVanillaInfectionText = string.Empty; lastAppliedVanillaWeightText = string.Empty; lastAppliedVanillaInfectionText = string.Empty; hasAppliedVanillaWeightText = false; hasAppliedVanillaInfectionText = false; hasClearedVanillaInfectionValueText = false; lastAppliedVanillaWeightSlot = VanillaArcTextSlot.WeightStaminaUpper; lastAppliedVanillaWeightRootSize = Vector2.zero; lastAppliedVanillaInfectionRootSize = Vector2.zero; hasVanillaLayoutSignature = false; loggedMissingVanillaWarningRoot = false; hasActiveHudStyle = false; lastVisibleState = false; lastRenderedInfectionFillAmount = -1f; lastRenderedInfectionPercent = -1; lastRenderedInfectionLabel = string.Empty; currentHudAlpha = 1f; StopHudIntroAlphaSampling(); layoutDirty = true; hudStyleDirty = true; loggedMissingNativeHudParent = false; loggedNativeHudParentFallback = false; loggedMissingSprintMeter = false; loggedVanillaSprintMeterDiagnostics = false; } private void HideForCompatibility() { dataProvider.ResetCadaverGrowthCache(); RestoreVanillaWarningTextOffset(); RestoreOriginalWeightCounter(); if ((Object)(object)infectionRoot != (Object)null && ((Component)infectionRoot).gameObject.activeSelf) { ((Component)infectionRoot).gameObject.SetActive(false); } if ((Object)(object)vanillaWeightTextRoot != (Object)null && ((Component)vanillaWeightTextRoot).gameObject.activeSelf) { ((Component)vanillaWeightTextRoot).gameObject.SetActive(false); } if ((Object)(object)vanillaInfectionTextRoot != (Object)null && ((Component)vanillaInfectionTextRoot).gameObject.activeSelf) { ((Component)vanillaInfectionTextRoot).gameObject.SetActive(false); } if ((Object)(object)vanillaInfectionValueTextRoot != (Object)null && ((Component)vanillaInfectionValueTextRoot).gameObject.activeSelf) { ((Component)vanillaInfectionValueTextRoot).gameObject.SetActive(false); } lastVisibleState = false; lastRenderedInfectionFillAmount = -1f; lastRenderedInfectionPercent = -1; lastRenderedInfectionLabel = string.Empty; hasAppliedVanillaWeightText = false; hasAppliedVanillaInfectionText = false; hasClearedVanillaInfectionValueText = false; StopHudIntroAlphaSampling(); layoutDirty = true; } private void RefreshLayoutIfNeeded(PlayerControllerB player) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_032b: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) NativeHudState nativeHudState = GetNativeHudState(); float num = (nativeHudState.IsValid ? nativeHudState.Alpha : 1f); currentHudAlpha = Mathf.MoveTowards(currentHudAlpha, num, Time.unscaledDeltaTime * 12f); float num2 = currentHudAlpha; num2 *= GetHudIntroAlphaMultiplier(nativeHudState); ApplyHudAlpha(num2); if (activeHudStyle == HudStyle.VanillaStaminaRing) { RefreshVanillaStaminaRingLayout(player); return; } ApplyNativeHudElementRotation(); if (layoutDirty) { layoutDirty = false; Vector2 effectiveRootSize = GetEffectiveRootSize(); Vector2 val = infectionRoot.sizeDelta - effectiveRootSize; if (((Vector2)(ref val)).sqrMagnitude > 0.0001f) { infectionRoot.sizeDelta = effectiveRootSize; ((Graphic)panelBackground).rectTransform.sizeDelta = effectiveRootSize; } Vector2 anchorMin = layout.GetAnchorMin(); val = infectionRoot.anchorMin - anchorMin; if (((Vector2)(ref val)).sqrMagnitude > 0.0001f) { infectionRoot.anchorMin = anchorMin; } Vector2 anchorMax = layout.GetAnchorMax(); val = infectionRoot.anchorMax - anchorMax; if (((Vector2)(ref val)).sqrMagnitude > 0.0001f) { infectionRoot.anchorMax = anchorMax; } Vector2 pivot = layout.GetPivot(); val = infectionRoot.pivot - pivot; if (((Vector2)(ref val)).sqrMagnitude > 0.0001f) { infectionRoot.pivot = pivot; } ((Behaviour)panelBackground).enabled = ModConfig.ShowPanelBackground.Value; ((Graphic)panelBackground).color = new Color(0.1f, 0.02f, 0.02f, Mathf.Clamp01(ModConfig.PanelBackgroundAlpha.Value)); Vector2 val2 = AlignVector2(layout.GetAnchoredPosition()); val = infectionRoot.anchoredPosition - val2; if (((Vector2)(ref val)).sqrMagnitude > 0.0001f) { infectionRoot.anchoredPosition = val2; } Vector2 effectiveBarSize = GetEffectiveBarSize(); val = ((Graphic)infectionBackground).rectTransform.sizeDelta - effectiveBarSize; if (((Vector2)(ref val)).sqrMagnitude > 0.0001f) { ((Graphic)infectionBackground).rectTransform.sizeDelta = effectiveBarSize; ((Graphic)topLine).rectTransform.sizeDelta = effectiveBarSize; } RectTransform rectTransform = ((Graphic)infectionBar).rectTransform; val = rectTransform.sizeDelta - Vector2.zero; if (((Vector2)(ref val)).sqrMagnitude > 0.0001f) { rectTransform.sizeDelta = Vector2.zero; } val = rectTransform.offsetMin - Vector2.zero; if (((Vector2)(ref val)).sqrMagnitude > 0.0001f) { rectTransform.offsetMin = Vector2.zero; } val = rectTransform.offsetMax - Vector2.zero; if (((Vector2)(ref val)).sqrMagnitude > 0.0001f) { rectTransform.offsetMax = Vector2.zero; } RectTransform rectTransform2 = ((Graphic)infectionText).rectTransform; Vector2 val3 = AlignVector2(new Vector2(ModConfig.TextOffsetX.Value, ModConfig.TextOffsetY.Value)); val = rectTransform2.anchoredPosition - val3; if (((Vector2)(ref val)).sqrMagnitude > 0.0001f) { rectTransform2.anchoredPosition = val3; } if (infectionText.fontSize != ModConfig.TextFontSize.Value) { infectionText.fontSize = ModConfig.TextFontSize.Value; } Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(effectiveRootSize.x - 16f, 18f); val = rectTransform2.sizeDelta - val4; if (((Vector2)(ref val)).sqrMagnitude > 0.0001f) { rectTransform2.sizeDelta = val4; } } } private void ApplyHudAlpha(float alpha) { float alpha2 = Mathf.Clamp01(alpha); canvasGroup.alpha = alpha2; if ((Object)(object)vanillaWeightTextCanvasGroup != (Object)null) { vanillaWeightTextCanvasGroup.alpha = alpha2; } if ((Object)(object)vanillaInfectionTextCanvasGroup != (Object)null) { vanillaInfectionTextCanvasGroup.alpha = alpha2; } if ((Object)(object)vanillaInfectionValueTextCanvasGroup != (Object)null) { vanillaInfectionValueTextCanvasGroup.alpha = alpha2; } } private void StartHudIntroAlphaSampling(RectTransform sourceRect) { hudIntroAlphaSampleSource = sourceRect; hudIntroAlphaSamplingActive = (Object)(object)sourceRect != (Object)null; hudIntroAlphaSampleUntilTime = (hudIntroAlphaSamplingActive ? (Time.unscaledTime + 4f) : 0f); } private void StopHudIntroAlphaSampling() { hudIntroAlphaSampleSource = null; hudIntroAlphaSamplingActive = false; hudIntroAlphaSampleUntilTime = 0f; } private float GetHudIntroAlphaMultiplier(NativeHudState nativeHudState) { if (!hudIntroAlphaSamplingActive) { return 1f; } if (Time.unscaledTime > hudIntroAlphaSampleUntilTime) { StopHudIntroAlphaSampling(); return 1f; } if (!nativeHudState.IsValid || nativeHudState.Alpha < 0.999f) { return 1f; } if ((Object)(object)hudIntroAlphaSampleSource == (Object)null) { StopHudIntroAlphaSampling(); return 1f; } return SampleInheritedCanvasGroupAlpha(hudIntroAlphaSampleSource); } private static float SampleInheritedCanvasGroupAlpha(RectTransform sourceRect) { if ((Object)(object)sourceRect == (Object)null) { return 1f; } float num = 1f; bool flag = false; Transform val = (Transform)(object)sourceRect; while ((Object)(object)val != (Object)null) { CanvasGroup component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { num *= Mathf.Clamp01(component.alpha); flag = true; if (component.ignoreParentGroups) { break; } } val = val.parent; } if (!flag) { return 1f; } return Mathf.Clamp01(num); } private void SubscribeLayoutConfigEvents() { if (!layoutConfigEventsSubscribed && ModConfig.UiWidth != null) { ModConfig.HudStyleMode.SettingChanged += OnLayoutConfigChanged; ModConfig.UiWidth.SettingChanged += OnLayoutConfigChanged; ModConfig.UiHeight.SettingChanged += OnLayoutConfigChanged; ModConfig.AnchorPreset.SettingChanged += OnLayoutConfigChanged; ModConfig.PositionOffsetX.SettingChanged += OnLayoutConfigChanged; ModConfig.PositionOffsetY.SettingChanged += OnLayoutConfigChanged; ModConfig.TextOffsetX.SettingChanged += OnLayoutConfigChanged; ModConfig.TextOffsetY.SettingChanged += OnLayoutConfigChanged; ModConfig.TextFontSize.SettingChanged += OnLayoutConfigChanged; ModConfig.ShowPanelBackground.SettingChanged += OnLayoutConfigChanged; ModConfig.PanelBackgroundAlpha.SettingChanged += OnLayoutConfigChanged; ModConfig.ReduceAliasing.SettingChanged += OnLayoutConfigChanged; ModConfig.VanillaRingScale.SettingChanged += OnLayoutConfigChanged; ModConfig.VanillaRingOffsetX.SettingChanged += OnLayoutConfigChanged; ModConfig.VanillaRingOffsetY.SettingChanged += OnLayoutConfigChanged; ModConfig.VanillaWarningTextOffsetEnabled.SettingChanged += OnLayoutConfigChanged; ModConfig.VanillaWarningTextOffsetX.SettingChanged += OnLayoutConfigChanged; ModConfig.VanillaWarningTextOffsetY.SettingChanged += OnLayoutConfigChanged; ModConfig.DebugVanillaHudLiveLayoutRefresh.SettingChanged += OnLayoutConfigChanged; layoutConfigEventsSubscribed = true; } } private void UnsubscribeLayoutConfigEvents() { if (layoutConfigEventsSubscribed && ModConfig.UiWidth != null) { ModConfig.HudStyleMode.SettingChanged -= OnLayoutConfigChanged; ModConfig.UiWidth.SettingChanged -= OnLayoutConfigChanged; ModConfig.UiHeight.SettingChanged -= OnLayoutConfigChanged; ModConfig.AnchorPreset.SettingChanged -= OnLayoutConfigChanged; ModConfig.PositionOffsetX.SettingChanged -= OnLayoutConfigChanged; ModConfig.PositionOffsetY.SettingChanged -= OnLayoutConfigChanged; ModConfig.TextOffsetX.SettingChanged -= OnLayoutConfigChanged; ModConfig.TextOffsetY.SettingChanged -= OnLayoutConfigChanged; ModConfig.TextFontSize.SettingChanged -= OnLayoutConfigChanged; ModConfig.ShowPanelBackground.SettingChanged -= OnLayoutConfigChanged; ModConfig.PanelBackgroundAlpha.SettingChanged -= OnLayoutConfigChanged; ModConfig.ReduceAliasing.SettingChanged -= OnLayoutConfigChanged; ModConfig.VanillaRingScale.SettingChanged -= OnLayoutConfigChanged; ModConfig.VanillaRingOffsetX.SettingChanged -= OnLayoutConfigChanged; ModConfig.VanillaRingOffsetY.SettingChanged -= OnLayoutConfigChanged; ModConfig.VanillaWarningTextOffsetEnabled.SettingChanged -= OnLayoutConfigChanged; ModConfig.VanillaWarningTextOffsetX.SettingChanged -= OnLayoutConfigChanged; ModConfig.VanillaWarningTextOffsetY.SettingChanged -= OnLayoutConfigChanged; ModConfig.DebugVanillaHudLiveLayoutRefresh.SettingChanged -= OnLayoutConfigChanged; layoutConfigEventsSubscribed = false; } } private void OnLayoutConfigChanged(object sender, EventArgs args) { layoutDirty = true; hudStyleDirty = true; } private void UpdateInfection(PlayerControllerB player) { if (!ModConfig.InfectionBarEnabled.Value) { SetInfectionVisible(shouldShow: false); ApplyOrRestoreVanillaWarningTextOffset(infectionRingVisible: false); } else { if ((Object)(object)infectionRoot == (Object)null || (Object)(object)infectionBar == (Object)null || ((Object)(object)infectionText == (Object)null && (Object)(object)vanillaInfectionTextRoot == (Object)null)) { return; } if (!CanShowInfectionForPlayer(player)) { SetInfectionVisible(shouldShow: false); ApplyOrRestoreVanillaWarningTextOffset(infectionRingVisible: false); return; } float infectionNormalized = GetInfectionNormalized(player); bool flag = ShouldShowInfectionBar(player, infectionNormalized); SetInfectionVisible(flag); ApplyOrRestoreVanillaWarningTextOffset(flag); if (flag) { ApplyInfectionFillAmount(infectionNormalized); int num = Mathf.RoundToInt(infectionNormalized * 100f); string infectionLabel = GetInfectionLabel(); if (lastRenderedInfectionPercent != num || !string.Equals(lastRenderedInfectionLabel, infectionLabel, StringComparison.Ordinal)) { string text = FormatInfectionText(infectionLabel, num); SetInfectionText(text); lastRenderedInfectionPercent = num; lastRenderedInfectionLabel = infectionLabel; } if (activeHudStyle == HudStyle.VanillaStaminaRing) { UpdateVanillaWeightText(); } } } } private string FormatInfectionText(string infectionLabel, int infectionPercent) { return infectionLabel + " " + infectionPercent + "%"; } private void ApplyInfectionFillAmount(float infectionNormalized) { float num = Mathf.Clamp01(infectionNormalized); float num2 = ((activeHudStyle == HudStyle.VanillaStaminaRing) ? VanillaRingFillMapping.MapInfectionToVisibleFill(num) : num); if (!(Mathf.Abs(lastRenderedInfectionFillAmount - num) <= 0.0001f) || !(Mathf.Abs(infectionBar.fillAmount - num2) <= 0.0001f)) { if (activeHudStyle == HudStyle.VanillaStaminaRing) { ApplyVanillaRingFillAmount(infectionBar, num2); } else { infectionBar.fillAmount = num2; } lastRenderedInfectionFillAmount = num; } } private void SetInfectionText(string text) { if ((Object)(object)infectionText != (Object)null) { infectionText.text = text; } lastVanillaInfectionText = text; ApplyVanillaInfectionTextSegments(); } private bool ShouldShowInfectionBar(PlayerControllerB player, float infectionNormalized) { if (!ModConfig.InfectionBarEnabled.Value) { return false; } if (!CanShowInfectionForPlayer(player)) { return false; } if (ModConfig.InfectionBarAlwaysVisible.Value) { return true; } return infectionNormalized > 0f; } private static bool CanShowInfectionForPlayer(PlayerControllerB player) { if ((Object)(object)player != (Object)null && !player.isPlayerDead) { return player.isPlayerControlled; } return false; } private static NativeHudState GetNativeHudState() { HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { cachedNativeHudState = default(NativeHudState); nextNativeHudStateRefreshTime = 0f; return default(NativeHudState); } if (Time.unscaledTime < nextNativeHudStateRefreshTime && cachedNativeHudState.IsValid) { return cachedNativeHudState; } cachedNativeHudState = ReadNativeHudState(instance); nextNativeHudStateRefreshTime = Time.unscaledTime + 0.1f; return cachedNativeHudState; } private static NativeHudState ReadNativeHudState(HUDManager hudManager) { if (IsTerminalInUse(hudManager)) { return new NativeHudState(Mathf.Clamp01(ModConfig.TerminalFadeAlpha.Value), isValid: true); } if (hudHudHiddenField == null) { hudHudHiddenField = typeof(HUDManager).GetField("hudHidden", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } bool flag = default(bool); int num; if (hudHudHiddenField != null) { object value = hudHudHiddenField.GetValue(hudManager); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return new NativeHudState(0f, isValid: true); } return new NativeHudState(1f, isValid: true); } private static bool IsTerminalInUse(HUDManager hudManager) { Terminal val = ResolveTerminal(hudManager); if ((Object)(object)val == (Object)null) { return false; } if (terminalInUseField == null) { terminalInUseField = typeof(Terminal).GetField("terminalInUse", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } bool flag = default(bool); int num; if (terminalInUseField != null) { object value = terminalInUseField.GetValue(val); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static Terminal ResolveTerminal(HUDManager hudManager) { if (hudTerminalScriptField == null) { hudTerminalScriptField = typeof(HUDManager).GetField("terminalScript", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } object? obj = hudTerminalScriptField?.GetValue(hudManager); Terminal val = (Terminal)((obj is Terminal) ? obj : null); if ((Object)(object)val != (Object)null) { cachedTerminal = val; return val; } if ((Object)(object)cachedTerminal != (Object)null) { return cachedTerminal; } if (Time.unscaledTime < nextTerminalLookupTime) { return null; } nextTerminalLookupTime = Time.unscaledTime + 1f; cachedTerminal = Object.FindObjectOfType(); return cachedTerminal; } private static HUDElement GetHudElementFieldValue(HUDManager hudManager, ref FieldInfo cache, string fieldName) { if (cache == null) { cache = typeof(HUDManager).GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } object? obj = cache?.GetValue(hudManager); return (HUDElement)((obj is HUDElement) ? obj : null); } private RectTransform GetNativeHudParentTransform() { HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { return null; } Transform obj = ResolveNativeHudElementTransform(); Transform obj2 = ((obj != null) ? obj.parent : null); RectTransform val = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null); if ((Object)(object)val != (Object)null) { return val; } if (hudContainerField == null) { hudContainerField = typeof(HUDManager).GetField("HUDContainer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } object? obj3 = hudContainerField?.GetValue(instance); GameObject val2 = (GameObject)((obj3 is GameObject) ? obj3 : null); if (val2 != null) { RectTransform component = val2.GetComponent(); if ((Object)(object)component != (Object)null) { return component; } } HUDElement hudElementFieldValue = GetHudElementFieldValue(instance, ref hudPlayerInfoField, "PlayerInfo"); if ((Object)(object)hudElementFieldValue?.canvasGroup != (Object)null) { Transform parent = ((Component)hudElementFieldValue.canvasGroup).transform.parent; RectTransform val3 = (RectTransform)(object)((parent is RectTransform) ? parent : null); if ((Object)(object)val3 != (Object)null) { return val3; } } RectTransform val4 = ResolveNativeHudParentFallback(); if ((Object)(object)val4 != (Object)null && ShouldLogDiagnostics() && !loggedNativeHudParentFallback) { logger.LogWarning((object)("Using scene fallback native HUD parent for infection bar: " + GetHierarchyPath((Transform)(object)val4))); loggedNativeHudParentFallback = true; } return val4; } private static RectTransform ResolveNativeHudParentFallback() { if ((Object)(object)cachedNativeHudParentFallback != (Object)null) { return cachedNativeHudParentFallback; } if (Time.unscaledTime < nextNativeHudParentFallbackLookupTime) { return null; } nextNativeHudParentFallbackLookupTime = Time.unscaledTime + 1f; GameObject val = GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD"); RectTransform val2 = default(RectTransform); if ((Object)(object)val != (Object)null && val.TryGetComponent(ref val2)) { cachedNativeHudParentFallback = val2; return cachedNativeHudParentFallback; } Canvas[] array = Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { Transform obj = ((Component)array[i]).transform.Find("IngamePlayerHUD"); RectTransform val3 = (RectTransform)(object)((obj is RectTransform) ? obj : null); if (val3 != null) { cachedNativeHudParentFallback = val3; return cachedNativeHudParentFallback; } } return null; } private static string GetHierarchyPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return ""; } string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } private static bool ShouldLogDiagnostics() { return ModConfig.DebugLogging?.Value ?? false; } private void ApplyNativeHudElementRotation() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)infectionRoot == (Object)null)) { Quaternion val = Quaternion.identity; if (TryGetNativeHudElementRotation(out var rotation)) { val = rotation; } if (((Transform)infectionRoot).localRotation != val) { ((Transform)infectionRoot).localRotation = val; } } } private bool TryGetNativeHudElementRotation(out Quaternion rotation) { //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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) rotation = Quaternion.identity; Transform val = ResolveNativeHudElementTransform(); if ((Object)(object)val == (Object)null) { return false; } Transform parent = ((Transform)infectionRoot).parent; if ((Object)(object)parent != (Object)null && (Object)(object)val.parent != (Object)(object)parent) { rotation = Quaternion.Inverse(parent.rotation) * val.rotation; } else { rotation = val.localRotation; } return true; } private static Transform ResolveNativeHudElementTransform() { if ((Object)(object)cachedNativeHudElementTransform != (Object)null) { return cachedNativeHudElementTransform; } if (Time.unscaledTime < nextNativeHudElementLookupTime) { return null; } nextNativeHudElementLookupTime = Time.unscaledTime + 1f; HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { return null; } if (hudElementsField == null) { hudElementsField = typeof(HUDManager).GetField("HUDElements", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (hudElementsField?.GetValue(instance) is HUDElement[] array && array.Length > 2 && (Object)(object)array[2]?.canvasGroup != (Object)null) { cachedNativeHudElementTransform = ((Component)array[2].canvasGroup).transform; return cachedNativeHudElementTransform; } HUDElement hudElementFieldValue = GetHudElementFieldValue(instance, ref hudPlayerInfoField, "PlayerInfo"); if ((Object)(object)hudElementFieldValue?.canvasGroup != (Object)null) { cachedNativeHudElementTransform = ((Component)hudElementFieldValue.canvasGroup).transform; } return cachedNativeHudElementTransform; } private string GetInfectionLabel() { if (Time.unscaledTime >= nextInfectionLabelRefreshTime) { string b = DetermineInfectionLabel(); if (!string.Equals(cachedInfectionLabel, b, StringComparison.Ordinal)) { cachedInfectionLabel = b; } nextInfectionLabelRefreshTime = Time.unscaledTime + 5f; } return cachedInfectionLabel; } private string DetermineInfectionLabel() { return languageHelper.DetermineInfectionLabel(); } private float GetInfectionNormalized(PlayerControllerB player) { if (dataProvider.TryGetInfectionNormalized(player, out var infectionNormalized)) { return infectionNormalized; } return 0f; } private void SetInfectionVisible(bool shouldShow) { if ((Object)(object)infectionRoot == (Object)null) { return; } bool flag = activeHudStyle == HudStyle.VanillaStaminaRing && ModConfig.InfectionBarEnabled.Value; if (lastVisibleState != shouldShow || (!((Object)(object)vanillaWeightTextRoot == (Object)null) && ((Component)vanillaWeightTextRoot).gameObject.activeSelf != flag) || (!((Object)(object)vanillaInfectionTextRoot == (Object)null) && ((Component)vanillaInfectionTextRoot).gameObject.activeSelf != shouldShow)) { ((Component)infectionRoot).gameObject.SetActive(shouldShow); if (activeHudStyle == HudStyle.VanillaStaminaRing) { SetOriginalWeightCounterHidden(flag); } if ((Object)(object)vanillaWeightTextRoot != (Object)null) { ((Component)vanillaWeightTextRoot).gameObject.SetActive(flag); } if ((Object)(object)vanillaInfectionTextRoot != (Object)null) { ((Component)vanillaInfectionTextRoot).gameObject.SetActive(shouldShow); } if ((Object)(object)vanillaInfectionValueTextRoot != (Object)null) { ((Component)vanillaInfectionValueTextRoot).gameObject.SetActive(false); } lastVisibleState = shouldShow; if (activeHudStyle == HudStyle.VanillaStaminaRing) { layoutDirty = true; hasAppliedVanillaWeightText = false; } if (!shouldShow) { lastRenderedInfectionFillAmount = -1f; lastRenderedInfectionPercent = -1; } } } private static RectTransform CreateRect(string name, Transform parent, Vector2 size, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_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) GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(parent, false); RectTransform component = val.GetComponent(); component.anchorMin = anchorMin; component.anchorMax = anchorMax; component.pivot = pivot; component.sizeDelta = size; return component; } private Vector2 GetEffectiveRootSize() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_002c: Unknown result type (might be due to invalid IL or missing references) Vector2 rootSize = layout.GetRootSize(); if (ModConfig.ReduceAliasing.Value) { rootSize.x = Mathf.Round(rootSize.x); rootSize.y = Mathf.Round(rootSize.y); } return rootSize; } private Vector2 GetEffectiveBarSize() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0031: Unknown result type (might be due to invalid IL or missing references) Vector2 barSize = layout.GetBarSize(); if (ModConfig.ReduceAliasing.Value) { barSize.x = Mathf.Round(barSize.x); barSize.y = Mathf.Max(10f, Mathf.Round(barSize.y)); } return barSize; } private static Vector2 AlignVector2(Vector2 value) { //IL_000e: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (!ModConfig.ReduceAliasing.Value) { return value; } return new Vector2(Mathf.Round(value.x), Mathf.Round(value.y)); } private static Sprite GetPixelSprite() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown if ((Object)(object)pixelSprite != (Object)null) { return pixelSprite; } Texture2D val = new Texture2D(1, 1, (TextureFormat)5, false) { name = "IndependentCadaverInfectionBarPixel", hideFlags = (HideFlags)61, wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; val.SetPixel(0, 0, Color.white); val.Apply(); pixelSprite = Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f), 1f); ((Object)pixelSprite).hideFlags = (HideFlags)61; return pixelSprite; } } internal sealed class InfectionDataProvider { private const float SuccessfulCadaverGrowthLookupIntervalSeconds = 0.25f; private const float MissingCadaverGrowthLookupIntervalSeconds = 2f; private readonly ManualLogSource logger; private CadaverGrowthAI cachedCadaverGrowth; private float nextCadaverGrowthLookupTime; internal InfectionDataProvider(ManualLogSource logger) { this.logger = logger; } internal PlayerControllerB GetLocalPlayer() { return GameNetworkManager.Instance?.localPlayerController; } internal bool TryGetInfectionNormalized(PlayerControllerB player, out float infectionNormalized) { infectionNormalized = 0f; if ((Object)(object)player == (Object)null) { return false; } int playerId = (int)player.playerClientId; if (!TryReadInfectionMeter(ResolveCadaverGrowth(playerId), playerId, out infectionNormalized)) { return false; } return true; } private CadaverGrowthAI ResolveCadaverGrowth(int playerId) { if (CanReadInfectionMeter(cachedCadaverGrowth, playerId)) { return cachedCadaverGrowth; } if (Time.unscaledTime < nextCadaverGrowthLookupTime) { return cachedCadaverGrowth; } CadaverGrowthAI[] array = Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { if (CanReadInfectionMeter(array[i], playerId)) { cachedCadaverGrowth = array[i]; nextCadaverGrowthLookupTime = Time.unscaledTime + 0.25f; return cachedCadaverGrowth; } } cachedCadaverGrowth = ((array.Length != 0) ? array[0] : null); nextCadaverGrowthLookupTime = Time.unscaledTime + 2f; return cachedCadaverGrowth; } private static bool TryReadInfectionMeter(CadaverGrowthAI cadaverGrowth, int playerId, out float infectionNormalized) { infectionNormalized = 0f; if (!CanReadInfectionMeter(cadaverGrowth, playerId)) { return false; } infectionNormalized = Mathf.Clamp01(cadaverGrowth.playerInfections[playerId].infectionMeter); return true; } private static bool CanReadInfectionMeter(CadaverGrowthAI cadaverGrowth, int playerId) { if ((Object)(object)cadaverGrowth != (Object)null && cadaverGrowth.playerInfections != null && playerId >= 0) { return playerId < cadaverGrowth.playerInfections.Length; } return false; } internal void ResetCadaverGrowthCache() { if (!((Object)(object)cachedCadaverGrowth == (Object)null)) { if (ModConfig.DebugLogging.Value) { logger.LogDebug((object)"Resetting cached CadaverGrowthAI reference."); } cachedCadaverGrowth = null; nextCadaverGrowthLookupTime = 0f; } } } internal sealed class InfectionLayout { private enum AnchorPreset { BottomLeft, BottomCenter, BottomRight, Center, TopLeft, TopCenter, TopRight } internal Vector2 GetAnchoredPosition() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) return new Vector2(ModConfig.PositionOffsetX.Value, ModConfig.PositionOffsetY.Value); } internal Vector2 GetAnchorMin() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetAnchorVector(); } internal Vector2 GetAnchorMax() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetAnchorVector(); } internal Vector2 GetPivot() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetAnchorVector(); } internal Vector2 GetRootSize() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) return new Vector2(ModConfig.UiWidth.Value, ModConfig.UiHeight.Value); } internal Vector2 GetBarSize() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) return new Vector2(Mathf.Max(16f, ModConfig.UiWidth.Value - 20f), Mathf.Max(4f, ModConfig.UiHeight.Value - 26f)); } private Vector2 GetAnchorVector() { //IL_0035: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_0085: Unknown result type (might be due to invalid IL or missing references) return (Vector2)(ParseAnchorPreset() switch { AnchorPreset.BottomLeft => new Vector2(0f, 0f), AnchorPreset.BottomCenter => new Vector2(0.5f, 0f), AnchorPreset.BottomRight => new Vector2(1f, 0f), AnchorPreset.TopLeft => new Vector2(0f, 1f), AnchorPreset.TopCenter => new Vector2(0.5f, 1f), AnchorPreset.TopRight => new Vector2(1f, 1f), _ => new Vector2(0.5f, 0.5f), }); } private AnchorPreset ParseAnchorPreset() { if (Enum.TryParse((ModConfig.AnchorPreset.Value ?? string.Empty).Trim(), ignoreCase: true, out var result)) { return result; } return AnchorPreset.Center; } } internal sealed class LanguageHelper { private const string ChineseLocalizationPluginGuid = "cn.codex.v81testchn"; internal string GetInfectionLabel() { return DetermineInfectionLabel(); } internal string DetermineInfectionLabel() { string text = (ModConfig.LabelLanguageMode.Value ?? "Auto").Trim(); if (text.Equals("Chinese", StringComparison.OrdinalIgnoreCase)) { return "感染"; } if (text.Equals("English", StringComparison.OrdinalIgnoreCase)) { return "Infection"; } if (!ShouldUseChineseInfectionLabel()) { return "Infection"; } return "感染"; } internal bool ShouldUseChineseInfectionLabel() { try { if (Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey("cn.codex.v81testchn")) { return true; } } catch { } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { if (assemblies[i].GetName().Name.Equals("V81TestChn", StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } } [BepInPlugin("InfectionBar", "InfectionBar", "1.1.2")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "InfectionBar"; public const string PluginName = "InfectionBar"; public const string PluginVersion = "1.1.2"; internal static readonly bool EnableHudManagerTickFallback = true; private static GameObject controllerHost; private static Harmony harmony; private static ManualLogSource pluginLogger; private static bool loggedHudManagerStartPatch; private static bool loggedHudManagerUpdatePatch; private static bool loggedPlayerLateUpdatePatch; private static bool applicationQuitting; private InfectionBarController controller; private bool loggedFirstPluginUpdate; internal static InfectionBarController ActiveController { get; private set; } private void Awake() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); pluginLogger = ((BaseUnityPlugin)this).Logger; InfectionBarCompatibility.Initialize(((BaseUnityPlugin)this).Logger); ModConfig.Bind(((BaseUnityPlugin)this).Config); if ((Object)(object)controllerHost == (Object)null) { controllerHost = new GameObject("InfectionBarControllerHost"); Object.DontDestroyOnLoad((Object)(object)controllerHost); } controller = controllerHost.GetComponent(); if ((Object)(object)controller == (Object)null) { controller = controllerHost.AddComponent(); } controller.Initialize(((BaseUnityPlugin)this).Logger, new InfectionDataProvider(((BaseUnityPlugin)this).Logger), new InfectionLayout(), new LanguageHelper()); ActiveController = controller; if (EnableHudManagerTickFallback && harmony == null) { harmony = new Harmony("InfectionBar"); harmony.PatchAll(typeof(Plugin).Assembly); if (ModConfig.DebugLogging.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"HUDManager.Update tick fallback enabled."); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)"InfectionBar loaded."); } private void Update() { if (ModConfig.DebugLogging.Value && !loggedFirstPluginUpdate) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Update tick fallback reached for the first time."); loggedFirstPluginUpdate = true; } controller?.Tick(); } internal static void TickFromPatch(string source) { if (ModConfig.DebugLogging != null && ModConfig.DebugLogging.Value) { if (source == "HUDManager.Start" && !loggedHudManagerStartPatch) { ManualLogSource obj = pluginLogger; if (obj != null) { obj.LogInfo((object)"HUDManager.Start tick fallback reached for the first time."); } loggedHudManagerStartPatch = true; } else if (source == "HUDManager.Update" && !loggedHudManagerUpdatePatch) { ManualLogSource obj2 = pluginLogger; if (obj2 != null) { obj2.LogInfo((object)"HUDManager.Update tick fallback reached for the first time."); } loggedHudManagerUpdatePatch = true; } else if (source == "PlayerControllerB.LateUpdate" && !loggedPlayerLateUpdatePatch) { ManualLogSource obj3 = pluginLogger; if (obj3 != null) { obj3.LogInfo((object)"PlayerControllerB.LateUpdate tick fallback reached for the first time."); } loggedPlayerLateUpdatePatch = true; } } ActiveController?.Tick(); } private void OnApplicationQuit() { applicationQuitting = true; } private void OnDestroy() { if (!applicationQuitting) { if (ModConfig.DebugLogging != null && ModConfig.DebugLogging.Value) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Plugin OnDestroy reached before application quit; keeping controller and Harmony patches alive."); } return; } if ((Object)(object)ActiveController == (Object)(object)controller) { ActiveController = null; } controller?.Shutdown(); controller = null; if ((Object)(object)controllerHost != (Object)null) { Object.Destroy((Object)(object)controllerHost); controllerHost = null; } if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } pluginLogger = null; loggedHudManagerStartPatch = false; loggedHudManagerUpdatePatch = false; loggedPlayerLateUpdatePatch = false; applicationQuitting = false; } } [HarmonyPatch(typeof(HUDManager), "Start")] internal static class HudManagerStartPatch { private static void Postfix() { Plugin.TickFromPatch("HUDManager.Start"); } } [HarmonyPatch(typeof(HUDManager), "Update")] internal static class HudManagerUpdatePatch { private static void Postfix() { if (Plugin.EnableHudManagerTickFallback) { Plugin.TickFromPatch("HUDManager.Update"); } } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] internal static class PlayerControllerLateUpdatePatch { private static void Postfix() { Plugin.TickFromPatch("PlayerControllerB.LateUpdate"); } } internal enum VanillaArcTextTrack { StaminaWeightUpper, InfectionWeightInner, InfectionLabelOuter } internal struct VanillaArcGlyphLayout { internal readonly char Character; internal readonly float Angle; internal readonly float Radius; internal readonly float StrokeInnerRadius; internal readonly float StrokeOuterRadius; internal readonly float LocalX; internal readonly float LocalY; internal readonly float RotationZ; internal readonly float FontScale; internal VanillaArcGlyphLayout(char character, float angle, float radius, float strokeInnerRadius, float strokeOuterRadius, float localX, float localY, float rotationZ, float fontScale) { Character = character; Angle = angle; Radius = radius; StrokeInnerRadius = strokeInnerRadius; StrokeOuterRadius = strokeOuterRadius; LocalX = localX; LocalY = localY; RotationZ = rotationZ; FontScale = fontScale; } } internal static class VanillaArcTextLayout { private struct TrackSettings { internal readonly float CenterAngle; internal readonly float MinAngleSpan; internal readonly float MaxAngleSpan; internal readonly float AdvanceScale; internal readonly float InnerClearance; internal readonly float OuterClearance; internal readonly float FontScale; internal readonly bool InsideStroke; internal readonly float RotationMin; internal readonly float RotationMax; internal readonly float FixedFirstGlyphAngle; internal readonly float RotationProgressStrength; internal readonly float SmoothRotationStart; internal readonly float SmoothRotationEnd; internal readonly float BaselineHandleScale; internal readonly int BaselineFitDegree; internal readonly float RotationMaxStep; internal readonly float RotationMaxPositiveStep; internal TrackSettings(float centerAngle, float minAngleSpan, float maxAngleSpan, float advanceScale, float innerClearance, float outerClearance, float fontScale, bool insideStroke, float rotationMin, float rotationMax, float fixedFirstGlyphAngle = float.NaN, float rotationProgressStrength = 0f, float smoothRotationStart = float.NaN, float smoothRotationEnd = float.NaN, float baselineHandleScale = 0.42f, int baselineFitDegree = 0, float rotationMaxStep = 0f, float rotationMaxPositiveStep = -1f) { CenterAngle = centerAngle; MinAngleSpan = minAngleSpan; MaxAngleSpan = maxAngleSpan; AdvanceScale = advanceScale; InnerClearance = innerClearance; OuterClearance = outerClearance; FontScale = fontScale; InsideStroke = insideStroke; RotationMin = rotationMin; RotationMax = rotationMax; FixedFirstGlyphAngle = fixedFirstGlyphAngle; RotationProgressStrength = rotationProgressStrength; SmoothRotationStart = smoothRotationStart; SmoothRotationEnd = smoothRotationEnd; BaselineHandleScale = baselineHandleScale; BaselineFitDegree = baselineFitDegree; RotationMaxStep = rotationMaxStep; RotationMaxPositiveStep = rotationMaxPositiveStep; } } private struct Point { internal readonly float X; internal readonly float Y; internal Point(float x, float y) { X = x; Y = y; } } private struct SmoothBaseline { internal readonly Point P0; internal readonly Point P1; internal readonly Point P2; internal readonly Point P3; internal SmoothBaseline(Point p0, Point p1, Point p2, Point p3) { P0 = p0; P1 = p1; P2 = p2; P3 = p3; } } private struct FittedBaseline { internal readonly double[] Coefficients; internal readonly int Degree; internal readonly float XCenter; internal readonly float XScale; internal FittedBaseline(double[] coefficients, int degree, float xCenter, float xScale) { Coefficients = coefficients; Degree = degree; XCenter = xCenter; XScale = xScale; } } private const float SpriteSize = 326f; private static readonly float[] ArcAngles = new float[43] { -162.5f, -157.5f, -152.5f, -147.5f, -142.5f, -137.5f, -132.5f, -127.5f, -122.5f, -117.5f, -112.5f, -107.5f, -102.5f, -97.5f, -92.5f, -87.5f, -82.5f, -77.5f, -72.5f, -67.5f, -62.5f, -57.5f, -52.5f, -47.5f, -42.5f, -37.5f, -32.5f, -27.5f, -22.5f, -17.5f, -12.5f, -7.5f, -2.5f, 2.5f, 7.5f, 17.5f, 22.5f, 27.5f, 32.5f, 37.5f, 42.5f, 47.5f, 52.5f }; private static readonly float[] ArcInnerRadii = new float[43] { 148.3f, 146.4f, 155.9f, 153.8f, 159.1f, 157.7f, 154.7f, 144.9f, 145.9f, 140.7f, 134f, 125.9f, 122.8f, 118f, 115.8f, 108.8f, 106.8f, 104f, 97.1f, 100.4f, 98.6f, 97.8f, 97.4f, 97.7f, 98.4f, 96.5f, 100.6f, 102.2f, 104.1f, 107.9f, 111.2f, 114.8f, 119.9f, 125.5f, 129f, 144f, 150.1f, 155.9f, 158f, 165f, 165.2f, 166.8f, 164.5f }; private static readonly float[] ArcOuterRadii = new float[43] { 152.1f, 158.5f, 161.1f, 165.2f, 165.5f, 165.5f, 164.1f, 160.9f, 163.2f, 150.6f, 145.2f, 140.9f, 133.5f, 128.2f, 123.9f, 117.6f, 115.1f, 112.2f, 110.8f, 112.3f, 106.7f, 105.3f, 105.1f, 105.4f, 106.2f, 109.9f, 108.1f, 110.3f, 113f, 116.4f, 120.8f, 127.6f, 130.5f, 135.8f, 139.3f, 154.7f, 161f, 167.2f, 169.6f, 171.7f, 173.9f, 171.2f, 168.6f }; private const float Deg2Rad = MathF.PI / 180f; private const float Rad2Deg = 57.29578f; private const int BezierLengthSamples = 48; internal static VanillaArcGlyphLayout[] Build(string text, VanillaArcTextTrack track, float rootWidth, float rootHeight) { string text2 = text ?? string.Empty; if (text2.Length == 0) { return Array.Empty(); } if (ContainsCjk(text2)) { return VanillaChineseArcTextLayout.Build(text2, track, rootWidth, rootHeight); } TrackSettings trackSettings = GetTrackSettings(track, text2); float[] array = BuildGlyphAdvances(text2); float num = Sum(array) * trackSettings.AdvanceScale; float trackRadius = GetTrackRadius(trackSettings.CenterAngle, trackSettings); float num2 = num / Math.Max(1f, trackRadius) * 57.29578f; float num3 = Clamp(num2, trackSettings.MinAngleSpan, trackSettings.MaxAngleSpan); float num4 = ((num2 > 0.0001f) ? (num3 / num2) : 1f); float num5 = (0f - num3) * 0.5f; if (!float.IsNaN(trackSettings.FixedFirstGlyphAngle)) { float num6 = array[0] * trackSettings.AdvanceScale * 0.5f / Math.Max(1f, trackRadius) * 57.29578f * num4; num5 = trackSettings.CenterAngle - trackSettings.FixedFirstGlyphAngle - num6; } float num7 = 0f; float[] array2 = new float[text2.Length]; float[] array3 = new float[text2.Length]; for (int i = 0; i < text2.Length; i++) { float num8 = array[i] * trackSettings.AdvanceScale; array3[i] = ((num > 0.0001f) ? ((num7 + num8 * 0.5f) / num) : 0f); float num9 = num5 + (num7 + num8 * 0.5f) / Math.Max(1f, trackRadius) * 57.29578f * num4; array2[i] = trackSettings.CenterAngle - num9; num7 += num8; } VanillaArcGlyphLayout[] array4 = new VanillaArcGlyphLayout[text2.Length]; float firstAngle = array2[0]; float lastAngle = array2[^1]; Point[] array5 = null; float[] array6 = null; SmoothBaseline baseline; bool flag = TryCreateSmoothBaseline(firstAngle, lastAngle, trackSettings, rootWidth, rootHeight, out baseline); if (flag) { float[] progresses = BuildSmoothArcLengthProgresses(baseline, array3); array5 = BuildSmoothBaselinePoints(progresses, baseline); array6 = BuildSmoothBaselineRotations(progresses, baseline, trackSettings); } else { flag = TryCreateFittedBaseline(array2, trackSettings, rootWidth, rootHeight, out var points, out var baseline2); if (flag) { array5 = BuildFittedBaselinePoints(points, baseline2); array6 = BuildBaselineRotations(array5, trackSettings); } } for (int j = 0; j < text2.Length; j++) { float num10 = array2[j]; float arcRadius = GetArcRadius(num10, ArcInnerRadii); float arcRadius2 = GetArcRadius(num10, ArcOuterRadii); float trackRadius2 = GetTrackRadius(num10, trackSettings); float localX; float localY; float rotationZ; if (flag) { Point point = array5[j]; localX = point.X; localY = point.Y; rotationZ = array6[j]; } else { float num11 = num10 * (MathF.PI / 180f); localX = (float)Math.Cos(num11) * trackRadius2 * (Math.Abs(rootWidth) / 326f); localY = (float)Math.Sin(num11) * trackRadius2 * (Math.Abs(rootHeight) / 326f); rotationZ = GetGlyphRotation(num10, firstAngle, lastAngle, trackSettings); } array4[j] = new VanillaArcGlyphLayout(text2[j], num10, trackRadius2, arcRadius, arcRadius2, localX, localY, rotationZ, trackSettings.FontScale); } return array4; } private static TrackSettings GetTrackSettings(VanillaArcTextTrack track, string text) { bool flag = ContainsCjk(text); switch (track) { case VanillaArcTextTrack.StaminaWeightUpper: case VanillaArcTextTrack.InfectionWeightInner: if (!flag) { return new TrackSettings(50f, 9f, 28f, 22f, 0f, 22.5f, 0.4f, insideStroke: false, -46f, -28f, 53.7f, 0f, -37f, -42f, 0.32f, 0, 1.6f, 0.8f); } return new TrackSettings(45f, 8f, 16f, 22f, 0f, 22.5f, 0.4f, insideStroke: false, -46f, -28f, 48.8f, 0f, -37f, -42f, 0.32f, 0, 1.6f, 0.8f); case VanillaArcTextTrack.InfectionLabelOuter: if (!flag) { return new TrackSettings(37f, 24f, 39f, 22f, 0f, 46f, 0.44f, insideStroke: false, -74f, -28f, float.NaN, 0f, -37f, -65f); } return new TrackSettings(40f, 19f, 27f, 28f, 0f, 44f, 0.5f, insideStroke: false, -62f, -38f, float.NaN, 0f, float.NaN, float.NaN, 0.42f, 1); default: if (!flag) { return new TrackSettings(50f, 9f, 28f, 22f, 0f, 22.5f, 0.4f, insideStroke: false, -46f, -28f, 53.7f, 0f, -37f, -42f, 0.32f, 0, 1.6f, 0.8f); } return new TrackSettings(45f, 8f, 16f, 22f, 0f, 22.5f, 0.4f, insideStroke: false, -46f, -28f, 48.8f, 0f, -37f, -42f, 0.32f, 0, 1.6f, 0.8f); } } private static bool ContainsCjk(string text) { foreach (char c in text) { if ((c >= '㐀' && c <= '\u9fff') || (c >= '豈' && c <= '\ufaff')) { return true; } } return false; } private static float[] BuildGlyphAdvances(string text) { float[] array = new float[text.Length]; for (int i = 0; i < text.Length; i++) { array[i] = GetGlyphAdvanceWeight(text, i); } return array; } private static float GetGlyphAdvanceWeight(string text, int index) { char c = text[index]; if (char.IsWhiteSpace(c)) { if (index + 2 < text.Length && text[index + 1] == 'l' && text[index + 2] == 'b') { return 0.72f; } return 0.38f; } if (c == 'l' && index + 1 < text.Length && text[index + 1] == 'b') { return 0.76f; } if (c == 'b' && index > 0 && text[index - 1] == 'l') { return 0.75f; } if (c >= '0' && c <= '9') { if (index + 1 < text.Length && text[index + 1] == '%') { return 1.05f; } return 0.58f; } if (c == '%' && index > 0 && text[index - 1] >= '0' && text[index - 1] <= '9') { return 1.65f; } if (c == '%' || c == '.') { return 0.52f; } if (c == 'i' || c == 'l' || c == 'I') { return 0.44f; } if (c == 'f' || c == 't' || c == 'r') { return 0.48f; } if (c == 'm' || c == 'w' || c == 'M' || c == 'W') { return 0.78f; } if (c < '\u0080') { return 0.6f; } return 1f; } private static float Sum(float[] values) { float num = 0f; for (int i = 0; i < values.Length; i++) { num += values[i]; } return num; } private static float GetTrackRadius(float angle, TrackSettings settings) { float arcRadius = GetArcRadius(angle, ArcInnerRadii); float arcRadius2 = GetArcRadius(angle, ArcOuterRadii); if (!settings.InsideStroke) { return arcRadius2 + settings.OuterClearance; } return Math.Max(0f, arcRadius - settings.InnerClearance); } private static float GetArcRadius(float angle, float[] radii) { if (angle <= ArcAngles[0]) { return radii[0]; } int num = ArcAngles.Length - 1; if (angle >= ArcAngles[num]) { return radii[num]; } for (int i = 0; i < num; i++) { float num2 = ArcAngles[i]; float num3 = ArcAngles[i + 1]; if (!(angle < num2) && !(angle > num3)) { float t = (angle - num2) / (num3 - num2); return Lerp(radii[i], radii[i + 1], t); } } return radii[num]; } private static float GetTangentRotation(float angle, float radius, TrackSettings settings) { float angle2 = angle + 1.2f; float angle3 = angle - 1.2f; Point point = GetPoint(angle2, GetTrackRadius(angle2, settings)); Point point2 = GetPoint(angle3, GetTrackRadius(angle3, settings)); return Clamp((float)(Math.Atan2(point2.Y - point.Y, point2.X - point.X) * 57.295780181884766), settings.RotationMin, settings.RotationMax); } private static bool TryCreateFittedBaseline(float[] angles, TrackSettings settings, float rootWidth, float rootHeight, out Point[] points, out FittedBaseline baseline) { points = null; baseline = default(FittedBaseline); if (settings.BaselineFitDegree <= 0 || angles.Length < 2) { return false; } points = new Point[angles.Length]; float num = float.MaxValue; float num2 = float.MinValue; for (int i = 0; i < angles.Length; i++) { points[i] = GetScaledTrackPoint(angles[i], settings, rootWidth, rootHeight); num = Math.Min(num, points[i].X); num2 = Math.Max(num2, points[i].X); } float num3 = (num + num2) * 0.5f; float num4 = Math.Max(1f, (num2 - num) * 0.5f); int num5 = Math.Min(settings.BaselineFitDegree, points.Length - 1); int num6 = num5 + 1; double[,] array = new double[num6, num6]; double[] array2 = new double[num6]; for (int j = 0; j < points.Length; j++) { double num7 = (points[j].X - num3) / num4; double[] array3 = new double[num6 * 2 - 1]; array3[0] = 1.0; for (int k = 1; k < array3.Length; k++) { array3[k] = array3[k - 1] * num7; } for (int l = 0; l < num6; l++) { array2[l] += (double)points[j].Y * array3[l]; for (int m = 0; m < num6; m++) { array[l, m] += array3[l + m]; } } } double[] array4 = SolveLinearSystem(array, array2, num6); if (array4 == null) { return false; } baseline = new FittedBaseline(array4, num5, num3, num4); return true; } private static double[] SolveLinearSystem(double[,] matrix, double[] rhs, int size) { for (int i = 0; i < size; i++) { int num = i; double num2 = Math.Abs(matrix[i, i]); for (int j = i + 1; j < size; j++) { double num3 = Math.Abs(matrix[j, i]); if (num3 > num2) { num2 = num3; num = j; } } if (num2 < 1E-07) { return null; } if (num != i) { for (int k = i; k < size; k++) { double num4 = matrix[i, k]; matrix[i, k] = matrix[num, k]; matrix[num, k] = num4; } double num5 = rhs[i]; rhs[i] = rhs[num]; rhs[num] = num5; } double num6 = matrix[i, i]; for (int l = i; l < size; l++) { matrix[i, l] /= num6; } rhs[i] /= num6; for (int m = 0; m < size; m++) { if (m != i) { double num7 = matrix[m, i]; for (int n = i; n < size; n++) { matrix[m, n] -= num7 * matrix[i, n]; } rhs[m] -= num7 * rhs[i]; } } } return rhs; } private static float EvaluatePolynomial(FittedBaseline baseline, float x) { double num = (x - baseline.XCenter) / baseline.XScale; double num2 = 0.0; for (int num3 = baseline.Degree; num3 >= 0; num3--) { num2 = num2 * num + baseline.Coefficients[num3]; } return (float)num2; } private static Point[] BuildFittedBaselinePoints(Point[] rawPoints, FittedBaseline baseline) { Point[] array = new Point[rawPoints.Length]; for (int i = 0; i < rawPoints.Length; i++) { array[i] = new Point(rawPoints[i].X, EvaluatePolynomial(baseline, rawPoints[i].X)); } return array; } private static Point[] BuildSmoothBaselinePoints(float[] progresses, SmoothBaseline baseline) { Point[] array = new Point[progresses.Length]; for (int i = 0; i < progresses.Length; i++) { array[i] = GetBezierPoint(baseline, progresses[i]); } return array; } private static float[] BuildSmoothBaselineRotations(float[] progresses, SmoothBaseline baseline, TrackSettings settings) { float[] array = new float[progresses.Length]; for (int i = 0; i < progresses.Length; i++) { Point bezierDerivative = GetBezierDerivative(baseline, progresses[i]); array[i] = Clamp((float)(Math.Atan2(bezierDerivative.Y, bezierDerivative.X) * 57.295780181884766), settings.RotationMin, settings.RotationMax); } NormalizeBaselineRotations(array, settings); return array; } private static float[] BuildSmoothArcLengthProgresses(SmoothBaseline baseline, float[] layoutProgresses) { float[] array = BuildBezierLengthSamples(baseline); float num = array[^1]; float[] array2 = new float[layoutProgresses.Length]; for (int i = 0; i < layoutProgresses.Length; i++) { array2[i] = GetProgressAtLength(array, num * Clamp01(layoutProgresses[i])); } return array2; } private static float[] BuildBezierLengthSamples(SmoothBaseline baseline) { float[] array = new float[49]; Point a = GetBezierPoint(baseline, 0f); array[0] = 0f; for (int i = 1; i <= 48; i++) { float progress = (float)i / 48f; Point bezierPoint = GetBezierPoint(baseline, progress); array[i] = array[i - 1] + Distance(a, bezierPoint); a = bezierPoint; } return array; } private static float GetProgressAtLength(float[] sampleLengths, float targetLength) { if (targetLength <= 0f) { return 0f; } float num = sampleLengths[^1]; if (targetLength >= num) { return 1f; } for (int i = 1; i < sampleLengths.Length; i++) { if (!(sampleLengths[i] < targetLength)) { float num2 = sampleLengths[i] - sampleLengths[i - 1]; float num3 = ((num2 > 0.0001f) ? ((targetLength - sampleLengths[i - 1]) / num2) : 0f); return ((float)(i - 1) + num3) / 48f; } } return 1f; } private static float[] BuildBaselineRotations(Point[] points, TrackSettings settings) { float[] array = new float[points.Length]; for (int i = 0; i < points.Length; i++) { Point point = ((i == 0) ? points[i] : points[i - 1]); Point point2 = ((i == points.Length - 1) ? points[i] : points[i + 1]); if (i > 0 && i < points.Length - 1) { point = points[i - 1]; point2 = points[i + 1]; } array[i] = Clamp((float)(Math.Atan2(point2.Y - point.Y, point2.X - point.X) * 57.295780181884766), settings.RotationMin, settings.RotationMax); } NormalizeBaselineRotations(array, settings); return array; } private static void NormalizeBaselineRotations(float[] rotations, TrackSettings settings) { if (rotations.Length < 2 || (settings.RotationMaxStep <= 0f && settings.RotationMaxPositiveStep < 0f)) { return; } for (int i = 1; i < rotations.Length; i++) { float num = rotations[i - 1]; if (settings.RotationMaxPositiveStep >= 0f && rotations[i] > num + settings.RotationMaxPositiveStep) { rotations[i] = num + settings.RotationMaxPositiveStep; } if (settings.RotationMaxStep > 0f && rotations[i] < num - settings.RotationMaxStep) { rotations[i] = num - settings.RotationMaxStep; } rotations[i] = Clamp(rotations[i], settings.RotationMin, settings.RotationMax); } } private static bool TryCreateSmoothBaseline(float firstAngle, float lastAngle, TrackSettings settings, float rootWidth, float rootHeight, out SmoothBaseline baseline) { baseline = default(SmoothBaseline); if (float.IsNaN(settings.SmoothRotationStart) || float.IsNaN(settings.SmoothRotationEnd)) { return false; } Point scaledTrackPoint = GetScaledTrackPoint(firstAngle, settings, rootWidth, rootHeight); Point scaledTrackPoint2 = GetScaledTrackPoint(lastAngle, settings, rootWidth, rootHeight); float num = Distance(scaledTrackPoint, scaledTrackPoint2); if (num < 0.001f) { return false; } float scale = num * settings.BaselineHandleScale; Point direction = GetDirection(settings.SmoothRotationStart); Point direction2 = GetDirection(settings.SmoothRotationEnd); baseline = new SmoothBaseline(scaledTrackPoint, Add(scaledTrackPoint, Multiply(direction, scale)), Subtract(scaledTrackPoint2, Multiply(direction2, scale)), scaledTrackPoint2); return true; } private static Point GetScaledTrackPoint(float angle, TrackSettings settings, float rootWidth, float rootHeight) { float trackRadius = GetTrackRadius(angle, settings); float num = angle * (MathF.PI / 180f); return new Point((float)Math.Cos(num) * trackRadius * (Math.Abs(rootWidth) / 326f), (float)Math.Sin(num) * trackRadius * (Math.Abs(rootHeight) / 326f)); } private static Point GetBezierPoint(SmoothBaseline baseline, float progress) { float num = Clamp01(progress); float num2 = 1f - num; float num3 = num2 * num2; float num4 = num * num; return new Point(num3 * num2 * baseline.P0.X + 3f * num3 * num * baseline.P1.X + 3f * num2 * num4 * baseline.P2.X + num4 * num * baseline.P3.X, num3 * num2 * baseline.P0.Y + 3f * num3 * num * baseline.P1.Y + 3f * num2 * num4 * baseline.P2.Y + num4 * num * baseline.P3.Y); } private static Point GetBezierDerivative(SmoothBaseline baseline, float progress) { float num = Clamp01(progress); float num2 = 1f - num; return new Point(3f * num2 * num2 * (baseline.P1.X - baseline.P0.X) + 6f * num2 * num * (baseline.P2.X - baseline.P1.X) + 3f * num * num * (baseline.P3.X - baseline.P2.X), 3f * num2 * num2 * (baseline.P1.Y - baseline.P0.Y) + 6f * num2 * num * (baseline.P2.Y - baseline.P1.Y) + 3f * num * num * (baseline.P3.Y - baseline.P2.Y)); } private static Point GetDirection(float angle) { float num = angle * (MathF.PI / 180f); return new Point((float)Math.Cos(num), (float)Math.Sin(num)); } private static float Distance(Point a, Point b) { float num = b.X - a.X; float num2 = b.Y - a.Y; return (float)Math.Sqrt(num * num + num2 * num2); } private static Point Add(Point a, Point b) { return new Point(a.X + b.X, a.Y + b.Y); } private static Point Subtract(Point a, Point b) { return new Point(a.X - b.X, a.Y - b.Y); } private static Point Multiply(Point point, float scale) { return new Point(point.X * scale, point.Y * scale); } private static float GetGlyphRotation(float angle, float firstAngle, float lastAngle, TrackSettings settings) { if (!float.IsNaN(settings.SmoothRotationStart) && !float.IsNaN(settings.SmoothRotationEnd)) { float t = SmoothStep(GetArcProgress(angle, firstAngle, lastAngle)); return Clamp(Lerp(settings.SmoothRotationStart, settings.SmoothRotationEnd, t), settings.RotationMin, settings.RotationMax); } float num = GetTangentRotation(angle, GetTrackRadius(angle, settings), settings); if (!float.IsNaN(settings.FixedFirstGlyphAngle) && settings.RotationProgressStrength > 0f) { num -= Math.Max(0f, settings.FixedFirstGlyphAngle - angle) * settings.RotationProgressStrength; num = Clamp(num, settings.RotationMin, settings.RotationMax); } return num; } private static float GetArcProgress(float angle, float firstAngle, float lastAngle) { float num = firstAngle - lastAngle; if (Math.Abs(num) < 0.0001f) { return 0f; } return Clamp01((firstAngle - angle) / num); } private static float SmoothStep(float value) { float num = Clamp01(value); return num * num * (3f - 2f * num); } private static Point GetPoint(float angle, float radius) { float num = angle * (MathF.PI / 180f); return new Point((float)Math.Cos(num) * radius, (float)Math.Sin(num) * radius); } private static float Lerp(float a, float b, float t) { return a + (b - a) * Clamp01(t); } private static float Clamp01(float value) { return Clamp(value, 0f, 1f); } private static float Clamp(float value, float min, float max) { if (value < min) { return min; } if (!(value > max)) { return value; } return max; } } internal static class VanillaChineseArcTextLayout { private struct ChineseTrackSettings { internal readonly float CenterAngle; internal readonly float MinAngleSpan; internal readonly float MaxAngleSpan; internal readonly float AdvanceScale; internal readonly float OuterClearance; internal readonly float FontScale; internal readonly float FixedFirstGlyphAngle; internal readonly float RotationMin; internal readonly float RotationMax; internal readonly float SmoothRotationStart; internal readonly float SmoothRotationEnd; internal readonly float BaselineHandleScale; internal readonly float RotationMaxStep; internal readonly float RotationMaxPositiveStep; internal ChineseTrackSettings(float centerAngle, float minAngleSpan, float maxAngleSpan, float advanceScale, float outerClearance, float fontScale, float fixedFirstGlyphAngle, float rotationMin, float rotationMax, float smoothRotationStart, float smoothRotationEnd, float baselineHandleScale, float rotationMaxStep, float rotationMaxPositiveStep) { CenterAngle = centerAngle; MinAngleSpan = minAngleSpan; MaxAngleSpan = maxAngleSpan; AdvanceScale = advanceScale; OuterClearance = outerClearance; FontScale = fontScale; FixedFirstGlyphAngle = fixedFirstGlyphAngle; RotationMin = rotationMin; RotationMax = rotationMax; SmoothRotationStart = smoothRotationStart; SmoothRotationEnd = smoothRotationEnd; BaselineHandleScale = baselineHandleScale; RotationMaxStep = rotationMaxStep; RotationMaxPositiveStep = rotationMaxPositiveStep; } } private struct Point { internal readonly float X; internal readonly float Y; internal Point(float x, float y) { X = x; Y = y; } } private struct SmoothBaseline { internal readonly Point P0; internal readonly Point P1; internal readonly Point P2; internal readonly Point P3; internal SmoothBaseline(Point p0, Point p1, Point p2, Point p3) { P0 = p0; P1 = p1; P2 = p2; P3 = p3; } } private const float SpriteSize = 326f; private static readonly float[] ArcAngles = new float[43] { -162.5f, -157.5f, -152.5f, -147.5f, -142.5f, -137.5f, -132.5f, -127.5f, -122.5f, -117.5f, -112.5f, -107.5f, -102.5f, -97.5f, -92.5f, -87.5f, -82.5f, -77.5f, -72.5f, -67.5f, -62.5f, -57.5f, -52.5f, -47.5f, -42.5f, -37.5f, -32.5f, -27.5f, -22.5f, -17.5f, -12.5f, -7.5f, -2.5f, 2.5f, 7.5f, 17.5f, 22.5f, 27.5f, 32.5f, 37.5f, 42.5f, 47.5f, 52.5f }; private static readonly float[] ArcInnerRadii = new float[43] { 148.3f, 146.4f, 155.9f, 153.8f, 159.1f, 157.7f, 154.7f, 144.9f, 145.9f, 140.7f, 134f, 125.9f, 122.8f, 118f, 115.8f, 108.8f, 106.8f, 104f, 97.1f, 100.4f, 98.6f, 97.8f, 97.4f, 97.7f, 98.4f, 96.5f, 100.6f, 102.2f, 104.1f, 107.9f, 111.2f, 114.8f, 119.9f, 125.5f, 129f, 144f, 150.1f, 155.9f, 158f, 165f, 165.2f, 166.8f, 164.5f }; private static readonly float[] ArcOuterRadii = new float[43] { 152.1f, 158.5f, 161.1f, 165.2f, 165.5f, 165.5f, 164.1f, 160.9f, 163.2f, 150.6f, 145.2f, 140.9f, 133.5f, 128.2f, 123.9f, 117.6f, 115.1f, 112.2f, 110.8f, 112.3f, 106.7f, 105.3f, 105.1f, 105.4f, 106.2f, 109.9f, 108.1f, 110.3f, 113f, 116.4f, 120.8f, 127.6f, 130.5f, 135.8f, 139.3f, 154.7f, 161f, 167.2f, 169.6f, 171.7f, 173.9f, 171.2f, 168.6f }; private const float Deg2Rad = MathF.PI / 180f; private const float Rad2Deg = 57.29578f; private const int BezierLengthSamples = 48; internal static VanillaArcGlyphLayout[] Build(string text, VanillaArcTextTrack track, float rootWidth, float rootHeight) { string text2 = text ?? string.Empty; if (text2.Length == 0) { return Array.Empty(); } ChineseTrackSettings trackSettings = GetTrackSettings(track); float[] array = BuildGlyphAdvances(text2); float num = Sum(array) * trackSettings.AdvanceScale; float trackRadius = GetTrackRadius(trackSettings.CenterAngle, trackSettings); float num2 = num / Math.Max(1f, trackRadius) * 57.29578f; float num3 = Clamp(num2, trackSettings.MinAngleSpan, trackSettings.MaxAngleSpan); float num4 = ((num2 > 0.0001f) ? (num3 / num2) : 1f); float num5 = (0f - num3) * 0.5f; if (!float.IsNaN(trackSettings.FixedFirstGlyphAngle)) { float num6 = array[0] * trackSettings.AdvanceScale * 0.5f / Math.Max(1f, trackRadius) * 57.29578f * num4; num5 = trackSettings.CenterAngle - trackSettings.FixedFirstGlyphAngle - num6; } float num7 = 0f; float[] array2 = new float[text2.Length]; float[] array3 = new float[text2.Length]; for (int i = 0; i < text2.Length; i++) { float num8 = array[i] * trackSettings.AdvanceScale; array3[i] = ((num > 0.0001f) ? ((num7 + num8 * 0.5f) / num) : 0f); float num9 = num5 + (num7 + num8 * 0.5f) / Math.Max(1f, trackRadius) * 57.29578f * num4; array2[i] = trackSettings.CenterAngle - num9; num7 += num8; } float firstAngle = array2[0]; float lastAngle = array2[^1]; SmoothBaseline baseline = CreateSmoothBaseline(firstAngle, lastAngle, trackSettings, rootWidth, rootHeight); float[] array4 = BuildArcLengthProgresses(baseline, array3); VanillaArcGlyphLayout[] array5 = new VanillaArcGlyphLayout[text2.Length]; for (int j = 0; j < text2.Length; j++) { float angle = array2[j]; Point bezierPoint = GetBezierPoint(baseline, array4[j]); Point bezierDerivative = GetBezierDerivative(baseline, array4[j]); float rotationZ = Clamp((float)(Math.Atan2(bezierDerivative.Y, bezierDerivative.X) * 57.295780181884766), trackSettings.RotationMin, trackSettings.RotationMax); array5[j] = new VanillaArcGlyphLayout(text2[j], angle, GetTrackRadius(angle, trackSettings), GetArcRadius(angle, ArcInnerRadii), GetArcRadius(angle, ArcOuterRadii), bezierPoint.X, bezierPoint.Y, rotationZ, trackSettings.FontScale); } NormalizeRotations(array5, trackSettings); return array5; } private static ChineseTrackSettings GetTrackSettings(VanillaArcTextTrack track) { if ((uint)track > 1u && track == VanillaArcTextTrack.InfectionLabelOuter) { return new ChineseTrackSettings(40f, 21f, 29f, 23f, 48f, 0.48f, float.NaN, -64f, -36f, -40f, -56f, 0.4f, 5f, 0.4f); } return new ChineseTrackSettings(45f, 10f, 18f, 22f, 22.5f, 0.4f, 48.8f, -48f, -30f, -36f, -42f, 0.36f, 2f, 0.8f); } private static float[] BuildGlyphAdvances(string text) { float[] array = new float[text.Length]; for (int i = 0; i < text.Length; i++) { array[i] = GetGlyphAdvance(text[i]); } return array; } private static float GetGlyphAdvance(char character) { if (char.IsWhiteSpace(character)) { return 0.58f; } if (character >= '0' && character <= '9') { return 0.76f; } if (character == '%' || character == '.') { return 0.78f; } if (IsCjk(character)) { return 1.16f; } return 0.8f; } private static bool IsCjk(char character) { if (character < '㐀' || character > '\u9fff') { if (character >= '豈') { return character <= '\ufaff'; } return false; } return true; } private static SmoothBaseline CreateSmoothBaseline(float firstAngle, float lastAngle, ChineseTrackSettings settings, float rootWidth, float rootHeight) { Point scaledTrackPoint = GetScaledTrackPoint(firstAngle, settings, rootWidth, rootHeight); Point scaledTrackPoint2 = GetScaledTrackPoint(lastAngle, settings, rootWidth, rootHeight); float scale = Math.Max(0.001f, Distance(scaledTrackPoint, scaledTrackPoint2)) * settings.BaselineHandleScale; Point direction = GetDirection(settings.SmoothRotationStart); Point direction2 = GetDirection(settings.SmoothRotationEnd); return new SmoothBaseline(scaledTrackPoint, Add(scaledTrackPoint, Multiply(direction, scale)), Subtract(scaledTrackPoint2, Multiply(direction2, scale)), scaledTrackPoint2); } private static float[] BuildArcLengthProgresses(SmoothBaseline baseline, float[] layoutProgresses) { float[] array = BuildBezierLengthSamples(baseline); float num = array[^1]; float[] array2 = new float[layoutProgresses.Length]; for (int i = 0; i < layoutProgresses.Length; i++) { array2[i] = GetProgressAtLength(array, num * Clamp01(layoutProgresses[i])); } return array2; } private static float[] BuildBezierLengthSamples(SmoothBaseline baseline) { float[] array = new float[49]; Point a = GetBezierPoint(baseline, 0f); array[0] = 0f; for (int i = 1; i <= 48; i++) { float progress = (float)i / 48f; Point bezierPoint = GetBezierPoint(baseline, progress); array[i] = array[i - 1] + Distance(a, bezierPoint); a = bezierPoint; } return array; } private static float GetProgressAtLength(float[] sampleLengths, float targetLength) { if (targetLength <= 0f) { return 0f; } float num = sampleLengths[^1]; if (targetLength >= num) { return 1f; } for (int i = 1; i < sampleLengths.Length; i++) { if (!(sampleLengths[i] < targetLength)) { float num2 = sampleLengths[i] - sampleLengths[i - 1]; float num3 = ((num2 > 0.0001f) ? ((targetLength - sampleLengths[i - 1]) / num2) : 0f); return ((float)(i - 1) + num3) / 48f; } } return 1f; } private static void NormalizeRotations(VanillaArcGlyphLayout[] glyphs, ChineseTrackSettings settings) { if (glyphs.Length < 2) { return; } float num = glyphs[0].RotationZ; for (int i = 1; i < glyphs.Length; i++) { float num2 = glyphs[i].RotationZ; if (settings.RotationMaxPositiveStep >= 0f && num2 > num + settings.RotationMaxPositiveStep) { num2 = num + settings.RotationMaxPositiveStep; } if (settings.RotationMaxStep > 0f && num2 < num - settings.RotationMaxStep) { num2 = num - settings.RotationMaxStep; } num2 = Clamp(num2, settings.RotationMin, settings.RotationMax); glyphs[i] = new VanillaArcGlyphLayout(glyphs[i].Character, glyphs[i].Angle, glyphs[i].Radius, glyphs[i].StrokeInnerRadius, glyphs[i].StrokeOuterRadius, glyphs[i].LocalX, glyphs[i].LocalY, num2, glyphs[i].FontScale); num = num2; } } private static float GetTrackRadius(float angle, ChineseTrackSettings settings) { return GetArcRadius(angle, ArcOuterRadii) + settings.OuterClearance; } private static Point GetScaledTrackPoint(float angle, ChineseTrackSettings settings, float rootWidth, float rootHeight) { float trackRadius = GetTrackRadius(angle, settings); float num = angle * (MathF.PI / 180f); return new Point((float)Math.Cos(num) * trackRadius * (Math.Abs(rootWidth) / 326f), (float)Math.Sin(num) * trackRadius * (Math.Abs(rootHeight) / 326f)); } private static float GetArcRadius(float angle, float[] radii) { if (angle <= ArcAngles[0]) { return radii[0]; } int num = ArcAngles.Length - 1; if (angle >= ArcAngles[num]) { return radii[num]; } for (int i = 1; i < ArcAngles.Length; i++) { if (!(angle > ArcAngles[i])) { float num2 = ArcAngles[i - 1]; float num3 = ArcAngles[i]; float t = (angle - num2) / (num3 - num2); return Lerp(radii[i - 1], radii[i], t); } } return radii[num]; } private static Point GetBezierPoint(SmoothBaseline baseline, float progress) { float num = Clamp01(progress); float num2 = 1f - num; float num3 = num2 * num2; float num4 = num * num; return new Point(num3 * num2 * baseline.P0.X + 3f * num3 * num * baseline.P1.X + 3f * num2 * num4 * baseline.P2.X + num4 * num * baseline.P3.X, num3 * num2 * baseline.P0.Y + 3f * num3 * num * baseline.P1.Y + 3f * num2 * num4 * baseline.P2.Y + num4 * num * baseline.P3.Y); } private static Point GetBezierDerivative(SmoothBaseline baseline, float progress) { float num = Clamp01(progress); float num2 = 1f - num; return new Point(3f * num2 * num2 * (baseline.P1.X - baseline.P0.X) + 6f * num2 * num * (baseline.P2.X - baseline.P1.X) + 3f * num * num * (baseline.P3.X - baseline.P2.X), 3f * num2 * num2 * (baseline.P1.Y - baseline.P0.Y) + 6f * num2 * num * (baseline.P2.Y - baseline.P1.Y) + 3f * num * num * (baseline.P3.Y - baseline.P2.Y)); } private static Point GetDirection(float angle) { float num = angle * (MathF.PI / 180f); return new Point((float)Math.Cos(num), (float)Math.Sin(num)); } private static float Sum(float[] values) { float num = 0f; for (int i = 0; i < values.Length; i++) { num += values[i]; } return num; } private static float Distance(Point a, Point b) { float num = b.X - a.X; float num2 = b.Y - a.Y; return (float)Math.Sqrt(num * num + num2 * num2); } private static Point Add(Point a, Point b) { return new Point(a.X + b.X, a.Y + b.Y); } private static Point Subtract(Point a, Point b) { return new Point(a.X - b.X, a.Y - b.Y); } private static Point Multiply(Point point, float scale) { return new Point(point.X * scale, point.Y * scale); } private static float Lerp(float a, float b, float t) { return a + (b - a) * Clamp01(t); } private static float Clamp01(float value) { return Clamp(value, 0f, 1f); } private static float Clamp(float value, float min, float max) { if (value < min) { return min; } if (!(value > max)) { return value; } return max; } } internal static class VanillaRingFillMapping { private const float VisibleArcStartFill = 0.3f; internal static float MapInfectionToVisibleFill(float infectionNormalized) { float num = Clamp01(infectionNormalized); if (num <= 0f) { return 0f; } return 0.3f + 0.7f * num; } private static float Clamp01(float value) { if (value < 0f) { return 0f; } return Math.Min(value, 1f); } } internal static class VanillaWarningTextOffsetCalculator { internal static void CalculateShiftedPosition(bool enabled, float originalX, float originalY, float offsetX, float offsetY, out float shiftedX, out float shiftedY) { shiftedX = (enabled ? (originalX + offsetX) : originalX); shiftedY = (enabled ? (originalY + offsetY) : originalY); } } }