Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Player Status Bars v0.1.0
BepInEx/plugins/PlayerStatusBars/PlayerStatusBars.dll
Decompiled 5 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 OtherPlayerStatusBars { internal sealed class CadaverGrowthInfectionProvider { private Type? cadaverGrowthType; private FieldInfo? playerInfectionsField; private FieldInfo? infectionMeterField; private Object? cachedCadaverGrowthInstance; private float nextFindTime; public bool TryGetNormalizedInfection(PlayerControllerB player, out float infectionMeter) { infectionMeter = 0f; if ((Object)(object)player == (Object)null) { return false; } if (!TryResolveCadaverGrowthInstance(out object instance)) { return false; } if (!(playerInfectionsField?.GetValue(instance) is Array array)) { return false; } int num = (int)player.playerClientId; if (num < 0 || num >= array.Length) { return false; } object value = array.GetValue(num); if (value == null || infectionMeterField == null) { return false; } if (!(infectionMeterField.GetValue(value) is float num2) || 1 == 0) { return false; } infectionMeter = Mathf.Clamp01(num2); return true; } private bool TryResolveCadaverGrowthInstance(out object instance) { instance = null; if (!TryResolveCadaverGrowthMetadata()) { return false; } if (cachedCadaverGrowthInstance == (Object)null && Time.unscaledTime >= nextFindTime) { nextFindTime = Time.unscaledTime + 1f; cachedCadaverGrowthInstance = Object.FindObjectOfType(cadaverGrowthType); } if (cachedCadaverGrowthInstance == (Object)null) { return false; } instance = cachedCadaverGrowthInstance; return true; } private bool TryResolveCadaverGrowthMetadata() { if (cadaverGrowthType != null && playerInfectionsField != null && infectionMeterField != null) { return true; } cadaverGrowthType = (from assembly in AppDomain.CurrentDomain.GetAssemblies() select assembly.GetType("CadaverGrowthAI", throwOnError: false)).FirstOrDefault((Type type) => type != null); if (cadaverGrowthType == null) { return false; } playerInfectionsField = cadaverGrowthType.GetField("playerInfections", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (playerInfectionsField == null) { return false; } Type type2 = cadaverGrowthType.GetNestedType("PlayerInfection", BindingFlags.Public | BindingFlags.NonPublic); if (type2 == null) { Type elementType = playerInfectionsField.FieldType.GetElementType(); type2 = elementType; } if (type2 == null) { return false; } infectionMeterField = type2.GetField("infectionMeter", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return infectionMeterField != null; } } internal static class MyPluginInfo { public const string PluginGuid = "Codex.OtherPlayerStatusBars"; public const string PluginName = "OtherPlayerStatusBars"; public const string PluginVersion = "0.1.0"; } internal sealed class PlayerStatusBarManager : MonoBehaviour { private readonly Dictionary<int, PlayerStatusBarView> trackedBars = new Dictionary<int, PlayerStatusBarView>(); private readonly HashSet<int> seenPlayerIds = new HashSet<int>(); private readonly List<int> staleIds = new List<int>(); private float nextRefreshTime; private void Update() { if (!Plugin.Settings.Enabled) { ClearBars(); } else if (!(Time.unscaledTime < nextRefreshTime)) { nextRefreshTime = Time.unscaledTime + 0.5f; RefreshBars(); } } private void RefreshBars() { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown StartOfRound instance = StartOfRound.Instance; PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : instance?.localPlayerController); if ((Object)(object)instance == (Object)null || (Object)(object)val == (Object)null || instance.allPlayerScripts == null) { ClearBars(); return; } if (ShouldSkipBarsInOrbit(instance)) { ClearBars(); return; } seenPlayerIds.Clear(); PlayerControllerB[] allPlayerScripts = instance.allPlayerScripts; foreach (PlayerControllerB val2 in allPlayerScripts) { if (!ShouldTrackPlayer(val2, val, allPlayerScripts)) { continue; } int num = (int)val2.playerClientId; seenPlayerIds.Add(num); if (!trackedBars.ContainsKey(num)) { GameObject val3 = new GameObject($"OtherPlayerStatusBar_{num}"); val3.transform.SetParent(((Component)this).transform, false); PlayerStatusBarView playerStatusBarView = val3.AddComponent<PlayerStatusBarView>(); if (!playerStatusBarView.Initialize(val2)) { Object.Destroy((Object)(object)val3); Plugin.Log.LogWarning((object)$"Failed to create player status bar for playerId={num}."); } else { trackedBars[num] = playerStatusBarView; } } } staleIds.Clear(); foreach (KeyValuePair<int, PlayerStatusBarView> trackedBar in trackedBars) { if (!seenPlayerIds.Contains(trackedBar.Key) || (Object)(object)trackedBar.Value == (Object)null || !trackedBar.Value.IsStillValid(val)) { staleIds.Add(trackedBar.Key); } } for (int j = 0; j < staleIds.Count; j++) { RemoveBar(staleIds[j]); } } private static bool ShouldTrackPlayer(PlayerControllerB player, PlayerControllerB localPlayer, PlayerControllerB[] allPlayers) { if ((Object)(object)player == (Object)null || (Object)(object)localPlayer == (Object)null) { return false; } if ((Object)(object)player == (Object)(object)localPlayer) { return false; } if (!player.isPlayerControlled || player.isPlayerDead) { return false; } if (player.health <= 0) { return false; } int num = (int)player.playerClientId; if (num < 0 || num >= allPlayers.Length || (Object)(object)allPlayers[num] != (Object)(object)player) { return false; } return ((Component)player).gameObject.activeInHierarchy; } private static bool ShouldSkipBarsInOrbit(StartOfRound startOfRound) { return Plugin.Settings.HideInOrbit && startOfRound.inShipPhase && !startOfRound.shipHasLanded; } private void RemoveBar(int playerId) { if (trackedBars.TryGetValue(playerId, out PlayerStatusBarView value)) { trackedBars.Remove(playerId); if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } } } private void ClearBars() { foreach (KeyValuePair<int, PlayerStatusBarView> trackedBar in trackedBars) { if ((Object)(object)trackedBar.Value != (Object)null) { Object.Destroy((Object)(object)((Component)trackedBar.Value).gameObject); } } trackedBars.Clear(); } private void OnDestroy() { ClearBars(); } private void OnEnable() { Plugin.Settings.SettingsChanged += HandleSettingsChanged; } private void OnDisable() { Plugin.Settings.SettingsChanged -= HandleSettingsChanged; } private void HandleSettingsChanged() { nextRefreshTime = 0f; } } internal sealed class PlayerStatusBarStrip : MonoBehaviour { internal enum StripType { Health, Infection } private const float Width = 172f; private const float Height = 20f; private bool visible = true; private string label = string.Empty; private float currentValue; private float maxValue = 1f; private bool renderAsPercent; private bool labelOnly; private StripType stripType; private RectTransform rectTransform = null; private Image backgroundImage = null; private Image fillImage = null; private TextMeshProUGUI text = null; private Outline border = null; private RectTransform fillRect = null; private bool dirty = true; private bool lastAppliedVisible = true; private float lastAppliedNormalized = -1f; private string lastAppliedText = string.Empty; private bool lastAppliedTextEnabled = true; private Color lastAppliedBackgroundColor = Color.clear; private Color lastAppliedFillColor = Color.clear; private Color lastAppliedBorderColor = Color.clear; private int lastAppliedSettingsRevision = -1; private bool hasFillColorOverride; private Color fillColorOverride; public void Initialize(StripType type) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00fd: 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_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: 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_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Expected O, but got Unknown //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) stripType = type; rectTransform = ((Component)this).gameObject.GetComponent<RectTransform>(); if ((Object)(object)rectTransform == (Object)null) { rectTransform = ((Component)this).gameObject.AddComponent<RectTransform>(); } rectTransform.sizeDelta = new Vector2(172f, 20f); rectTransform.anchorMin = new Vector2(0.5f, 0.5f); rectTransform.anchorMax = new Vector2(0.5f, 0.5f); rectTransform.pivot = new Vector2(0.5f, 0.5f); GameObject val = new GameObject("Background", new Type[3] { typeof(RectTransform), typeof(Image), typeof(Outline) }); val.transform.SetParent(((Component)this).transform, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; backgroundImage = val.GetComponent<Image>(); border = val.GetComponent<Outline>(); GameObject val2 = new GameObject("Fill", new Type[2] { typeof(RectTransform), typeof(Image) }); val2.transform.SetParent(val.transform, false); RectTransform component2 = val2.GetComponent<RectTransform>(); component2.anchorMin = new Vector2(0f, 0f); component2.anchorMax = new Vector2(0f, 1f); component2.pivot = new Vector2(0f, 0.5f); component2.offsetMin = new Vector2(1f, 1f); component2.offsetMax = new Vector2(-1f, -1f); fillImage = val2.GetComponent<Image>(); fillRect = component2; GameObject val3 = new GameObject("Text", new Type[2] { typeof(RectTransform), typeof(TextMeshProUGUI) }); val3.transform.SetParent(val.transform, false); RectTransform component3 = val3.GetComponent<RectTransform>(); component3.anchorMin = Vector2.zero; component3.anchorMax = Vector2.one; component3.offsetMin = new Vector2(6f, 1f); component3.offsetMax = new Vector2(-6f, -1f); text = val3.GetComponent<TextMeshProUGUI>(); ((TMP_Text)text).alignment = (TextAlignmentOptions)514; ((TMP_Text)text).fontSize = 12f; ((TMP_Text)text).enableWordWrapping = false; ((Graphic)text).color = Color.white; } public void SetDisplay(string displayLabel, float value, float max, bool showPercent) { float num = Mathf.Clamp(value, 0f, (max <= 0f) ? 1f : max); float num2 = Mathf.Max(max, 0.0001f); if (label == displayLabel && Mathf.Approximately(currentValue, num) && Mathf.Approximately(maxValue, num2) && renderAsPercent == showPercent && !labelOnly) { visible = true; return; } label = displayLabel; currentValue = num; maxValue = num2; renderAsPercent = showPercent; labelOnly = false; visible = true; dirty = true; } public void SetLabelOnly(string displayLabel, float fillValue, float max) { float num = Mathf.Clamp(fillValue, 0f, (max <= 0f) ? 1f : max); float num2 = Mathf.Max(max, 0.0001f); if (label == displayLabel && Mathf.Approximately(currentValue, num) && Mathf.Approximately(maxValue, num2) && labelOnly) { visible = true; return; } label = displayLabel; currentValue = num; maxValue = num2; renderAsPercent = false; labelOnly = true; visible = true; dirty = true; } public void SetVisible(bool isVisible) { if (visible != isVisible || ((Component)this).gameObject.activeSelf != isVisible) { visible = isVisible; ((Component)this).gameObject.SetActive(isVisible); dirty = true; } } public void SetFillColorOverride(bool enabled, Color color) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (hasFillColorOverride != enabled || (enabled && !(fillColorOverride == color))) { hasFillColorOverride = enabled; fillColorOverride = color; dirty = true; } } private void LateUpdate() { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)backgroundImage == (Object)null || (Object)(object)fillImage == (Object)null || (Object)(object)this.text == (Object)null || !visible) { return; } StatusBarConfig settings = Plugin.Settings; if (!dirty && settings.Revision == lastAppliedSettingsRevision) { return; } float num = Mathf.Clamp01(currentValue / maxValue); Color val = ((stripType == StripType.Health) ? settings.GetHealthFillColor() : settings.GetInfectionFillColor()); if (hasFillColorOverride) { val = fillColorOverride; } Color backgroundColor = settings.GetBackgroundColor(); Color borderColor = settings.GetBorderColor(); bool flag = ((stripType == StripType.Health) ? settings.ShowHealthText : settings.ShowInfectionText); string text = (labelOnly ? label : (renderAsPercent ? $"{label} {Mathf.RoundToInt(num * 100f)}%" : $"{label} {Mathf.RoundToInt(currentValue)}/{Mathf.RoundToInt(maxValue)}")); bool flag2 = backgroundColor != lastAppliedBackgroundColor || val != lastAppliedFillColor || borderColor != lastAppliedBorderColor; bool flag3 = !Mathf.Approximately(num, lastAppliedNormalized); bool flag4 = flag != lastAppliedTextEnabled; bool flag5 = text != lastAppliedText; bool flag6 = visible != lastAppliedVisible; if (dirty || flag2 || flag3 || flag4 || flag5 || flag6) { if (flag2) { ((Graphic)backgroundImage).color = backgroundColor; ((Shadow)border).effectColor = borderColor; ((Shadow)border).effectDistance = new Vector2(1f, -1f); ((Graphic)fillImage).color = val; lastAppliedBackgroundColor = backgroundColor; lastAppliedFillColor = val; lastAppliedBorderColor = borderColor; } if (dirty || flag3) { fillRect.SetSizeWithCurrentAnchors((Axis)0, Mathf.Lerp(0f, 170f, num)); lastAppliedNormalized = num; } if (dirty || flag4) { ((Behaviour)this.text).enabled = flag; lastAppliedTextEnabled = flag; } if (flag && (dirty || flag5)) { ((TMP_Text)this.text).text = text; lastAppliedText = text; } lastAppliedVisible = visible; lastAppliedSettingsRevision = settings.Revision; dirty = false; } } } internal sealed class PlayerStatusBarView : MonoBehaviour { private static readonly Color CriticalHealthBarColor = new Color(0.88f, 0.15f, 0.12f, 0.95f); private const float LowHealthRecoveryDisplayDelay = 15f; private const float LowHealthConfirmDelay = 0.5f; private const float InitialStateStabilizationDelay = 3f; private readonly CadaverGrowthInfectionProvider infectionProvider = new CadaverGrowthInfectionProvider(); private PlayerControllerB targetPlayer = null; private PlayerControllerB? localPlayer; private Transform? anchor; private PlayerStatusBarStrip healthStrip = null; private PlayerStatusBarStrip infectionStrip = null; private RectTransform healthStripRect = null; private RectTransform infectionStripRect = null; private Canvas worldCanvas = null; private RectTransform canvasRect = null; private int lastDisplayedHealth = int.MinValue; private int lastDisplayedInfectionPercent = int.MinValue; private bool wasHealthVisible; private bool wasInfectionVisible; private bool isLowHealthRecoveryTiming; private float lowHealthRecoveryTimer; private bool isLowHealthConfirming; private float lowHealthConfirmTimer; private string lastDisplayedHealthLabel = string.Empty; private bool lastCanvasEnabled = true; private float lastAppliedUiScale = -1f; private float lastAppliedHealthBarYOffset = float.NaN; private float lastAppliedInfectionBarYOffset = float.NaN; private float initializedAtTime; private bool suppressInitialStaleCriticalState; private bool hasCompletedInitialStateStabilization; private bool hasObservedStableNonCriticalState; public int PlayerId => ((Object)(object)targetPlayer != (Object)null) ? ((int)targetPlayer.playerClientId) : (-1); public bool Initialize(PlayerControllerB player) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) targetPlayer = player; anchor = ResolveAnchor(player); initializedAtTime = Time.unscaledTime; ((Component)this).gameObject.AddComponent<StatusBarBillboard>(); worldCanvas = ((Component)this).gameObject.AddComponent<Canvas>(); worldCanvas.renderMode = (RenderMode)2; worldCanvas.sortingOrder = 50; ((Component)this).gameObject.AddComponent<CanvasScaler>(); canvasRect = ((Component)worldCanvas).GetComponent<RectTransform>(); canvasRect.sizeDelta = new Vector2(220f, 84f); if (!TryCreateStrip("HealthStrip", out healthStrip)) { return false; } healthStripRect = ((Component)healthStrip).GetComponent<RectTransform>(); if (!TryCreateStrip("InfectionStrip", out infectionStrip)) { return false; } infectionStripRect = ((Component)infectionStrip).GetComponent<RectTransform>(); ((Object)this).name = $"PlayerStatusBar_{player.playerClientId}"; return true; } public bool IsStillValid(PlayerControllerB localPlayer) { if ((Object)(object)targetPlayer == (Object)null || (Object)(object)localPlayer == (Object)null) { return false; } if ((Object)(object)targetPlayer == (Object)(object)localPlayer || !targetPlayer.isPlayerControlled || targetPlayer.isPlayerDead) { return false; } return ((Component)targetPlayer).gameObject.activeInHierarchy; } private void LateUpdate() { //IL_009a: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_0300: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)targetPlayer == (Object)null) { return; } localPlayer = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : StartOfRound.Instance?.localPlayerController); bool flag = ShouldShowGroup(); if (anchor == null) { anchor = ResolveAnchor(targetPlayer); } float barSpacing = Plugin.Settings.BarSpacing; Vector3 val = (((Object)(object)anchor != (Object)null) ? anchor.position : ((Component)targetPlayer).transform.position); ((Component)this).transform.position = val + Vector3.up * (Plugin.Settings.HeadOffset + barSpacing * Plugin.Settings.UiScale); ApplyCanvasScale(Plugin.Settings.UiScale); SetCanvasEnabled(flag); if (!flag || !IsTargetReadyForDisplay()) { healthStrip.SetVisible(isVisible: false); infectionStrip.SetVisible(isVisible: false); wasHealthVisible = false; wasInfectionVisible = false; ResetLowHealthFallbackState(); ResetInitialStateStabilization(); return; } bool flag2 = ShouldShowForDistance(); ApplyStripLayoutOffsets(); int num = Mathf.Clamp(targetPlayer.health, 0, 100); bool criticallyInjured = targetPlayer.criticallyInjured; bool bleedingHeavily = targetPlayer.bleedingHeavily; bool flag3 = criticallyInjured || bleedingHeavily; UpdateInitialStateStabilization(flag3, num); bool flag4 = flag3 && !suppressInitialStaleCriticalState; int num2 = num; bool flag5 = false; if (!flag4 && num < 20 && !targetPlayer.isPlayerDead) { if (!isLowHealthRecoveryTiming) { if (!isLowHealthConfirming) { isLowHealthConfirming = true; lowHealthConfirmTimer = 0f; } else { lowHealthConfirmTimer += Time.unscaledDeltaTime; } if (lowHealthConfirmTimer >= 0.5f) { isLowHealthRecoveryTiming = true; lowHealthRecoveryTimer = 0f; isLowHealthConfirming = false; lowHealthConfirmTimer = 0f; } } else { lowHealthRecoveryTimer += Time.unscaledDeltaTime; } if (isLowHealthRecoveryTiming && lowHealthRecoveryTimer < 15f) { flag5 = true; } else if (isLowHealthRecoveryTiming) { num2 = 20; } } else if (isLowHealthRecoveryTiming || lowHealthRecoveryTimer > 0f || isLowHealthConfirming || lowHealthConfirmTimer > 0f) { ResetLowHealthFallbackState(); } bool flag6 = flag2; bool flag7 = flag4 || flag5; string text = (flag7 ? GetCriticalHealthLabel() : "HP"); healthStrip.SetFillColorOverride(flag7, CriticalHealthBarColor); if (flag6 && (!wasHealthVisible || num2 != lastDisplayedHealth || text != lastDisplayedHealthLabel)) { if (flag7) { healthStrip.SetLabelOnly(text, 100f, 100f); } else { healthStrip.SetDisplay(text, num2, 100f, showPercent: false); } lastDisplayedHealth = num2; lastDisplayedHealthLabel = text; } healthStrip.SetVisible(flag6); wasHealthVisible = flag6; float infectionMeter = 0f; bool flag8 = false; if (flag2) { flag8 = infectionProvider.TryGetNormalizedInfection(targetPlayer, out infectionMeter); } bool num3; if (Plugin.Settings.InfectionDisplayMode != 0) { if (!(flag2 && flag8)) { goto IL_0463; } num3 = infectionMeter > 0f; } else { num3 = flag2; } if (num3) { int num4 = Mathf.Clamp(Mathf.RoundToInt(infectionMeter * 100f), 0, 100); if (!wasInfectionVisible || num4 != lastDisplayedInfectionPercent) { infectionStrip.SetDisplay("INF", num4, 100f, showPercent: true); lastDisplayedInfectionPercent = num4; } infectionStrip.SetVisible(isVisible: true); wasInfectionVisible = true; return; } goto IL_0463; IL_0463: infectionStrip.SetVisible(isVisible: false); wasInfectionVisible = false; } private bool IsTargetReadyForDisplay() { return (Object)(object)targetPlayer != (Object)null && targetPlayer.isPlayerControlled && !targetPlayer.isPlayerDead && targetPlayer.health > 0; } private void ResetLowHealthFallbackState() { isLowHealthRecoveryTiming = false; lowHealthRecoveryTimer = 0f; isLowHealthConfirming = false; lowHealthConfirmTimer = 0f; } private static string GetCriticalHealthLabel() { return Plugin.UseChineseCriticalLabel ? "重伤" : "CRITICAL"; } private void UpdateInitialStateStabilization(bool rawCriticalState, int rawHealth) { if (!rawCriticalState) { hasObservedStableNonCriticalState = true; } if (!hasCompletedInitialStateStabilization) { float num = Time.unscaledTime - initializedAtTime; if (num <= 3f && !hasObservedStableNonCriticalState && rawCriticalState && rawHealth >= 20) { suppressInitialStaleCriticalState = true; } else if (num > 3f) { hasCompletedInitialStateStabilization = true; } } if (suppressInitialStaleCriticalState && (!rawCriticalState || rawHealth < 20 || targetPlayer.isPlayerDead)) { suppressInitialStaleCriticalState = false; } } private void ResetInitialStateStabilization() { initializedAtTime = Time.unscaledTime; suppressInitialStaleCriticalState = false; hasCompletedInitialStateStabilization = false; hasObservedStableNonCriticalState = false; } private void ApplyCanvasScale(float uiScale) { //IL_001a: 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) if (!Mathf.Approximately(lastAppliedUiScale, uiScale)) { ((Transform)canvasRect).localScale = Vector3.one * uiScale; lastAppliedUiScale = uiScale; } } private void ApplyStripLayoutOffsets() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) float healthBarYOffset = Plugin.Settings.HealthBarYOffset; if (!Mathf.Approximately(lastAppliedHealthBarYOffset, healthBarYOffset)) { healthStripRect.anchoredPosition = new Vector2(0f, healthBarYOffset); lastAppliedHealthBarYOffset = healthBarYOffset; } float infectionBarYOffset = Plugin.Settings.InfectionBarYOffset; if (!Mathf.Approximately(lastAppliedInfectionBarYOffset, infectionBarYOffset)) { infectionStripRect.anchoredPosition = new Vector2(0f, infectionBarYOffset); lastAppliedInfectionBarYOffset = infectionBarYOffset; } } private void SetCanvasEnabled(bool enabled) { if (lastCanvasEnabled != enabled || ((Behaviour)worldCanvas).enabled != enabled) { ((Behaviour)worldCanvas).enabled = enabled; lastCanvasEnabled = enabled; } } private bool TryCreateStrip(string stripName, out PlayerStatusBarStrip strip) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0044: 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) strip = null; GameObject val = new GameObject(stripName, new Type[1] { typeof(RectTransform) }); val.transform.SetParent(((Component)worldCanvas).transform, false); ((Object)val).name = stripName; val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; strip = val.AddComponent<PlayerStatusBarStrip>(); strip.Initialize((!(stripName == "HealthStrip")) ? PlayerStatusBarStrip.StripType.Infection : PlayerStatusBarStrip.StripType.Health); return true; } private bool ShouldShowForDistance() { //IL_0030: 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_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) if ((Object)(object)localPlayer == (Object)null) { return true; } float maxDistance = Plugin.Settings.MaxDistance; float num = maxDistance * maxDistance; Vector3 val = ((Component)localPlayer).transform.position - ((Component)targetPlayer).transform.position; return ((Vector3)(ref val)).sqrMagnitude <= num; } private bool ShouldShowGroup() { if (!Plugin.Settings.HideInOrbit) { return true; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return true; } return !instance.inShipPhase || instance.shipHasLanded; } private static Transform? ResolveAnchor(PlayerControllerB player) { if ((Object)(object)player.playerGlobalHead != (Object)null) { return player.playerGlobalHead; } if (player.bodyParts != null && player.bodyParts.Length != 0 && (Object)(object)player.bodyParts[0] != (Object)null) { return player.bodyParts[0]; } return ((Component)player).transform; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("Codex.OtherPlayerStatusBars", "OtherPlayerStatusBars", "0.1.0")] public sealed class Plugin : BaseUnityPlugin { internal static ManualLogSource Log { get; private set; } internal static StatusBarConfig Settings { get; private set; } internal static bool UseChineseCriticalLabel { get; private set; } private void Awake() { Log = ((BaseUnityPlugin)this).Logger; Settings = StatusBarConfig.Create(((BaseUnityPlugin)this).Config); UseChineseCriticalLabel = DetectChineseLocalizationMod(); TryRegisterLethalConfig(); ((Component)this).gameObject.AddComponent<PlayerStatusBarManager>(); ((BaseUnityPlugin)this).Config.Save(); Log.LogInfo((object)"OtherPlayerStatusBars loaded."); } private static bool DetectChineseLocalizationMod() { foreach (PluginInfo value4 in Chainloader.PluginInfos.Values) { string value = value4.Metadata.GUID ?? string.Empty; string value2 = value4.Metadata.Name ?? string.Empty; string value3 = value4.Location ?? string.Empty; if (LooksLikeChineseLocalization(value) || LooksLikeChineseLocalization(value2) || LooksLikeChineseLocalization(value3)) { return true; } } return false; } private static bool LooksLikeChineseLocalization(string value) { return Contains(value, "chinese") || Contains(value, "simplified_chinese") || Contains(value, "zh_cn") || Contains(value, "zh-cn") || Contains(value, "zh_hans") || Contains(value, "zh-hans") || Contains(value, "中文") || Contains(value, "汉化") || Contains(value, "FixGameTranslate"); } private static bool Contains(string value, string term) { return value.IndexOf(term, StringComparison.OrdinalIgnoreCase) >= 0; } private static void TryRegisterLethalConfig() { if (Type.GetType("LethalConfig.LethalConfigManager, LethalConfig", throwOnError: false) == null) { return; } try { StatusBarConfig.LethalConfigIntegration.Register(Settings); } catch (Exception arg) { Log.LogWarning((object)$"Failed to register LethalConfig items: {arg}"); } } } internal sealed class StatusBarBillboard : MonoBehaviour { private void LateUpdate() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_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_002d: 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_003a: 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_0057: 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_0059: Unknown result type (might be due to invalid IL or missing references) Camera val = ResolveViewCamera(); if (!((Object)(object)val == (Object)null)) { Vector3 forward = ((Component)val).transform.forward; Vector3 up = ((Component)val).transform.up; if (!(forward == Vector3.zero) && !(up == Vector3.zero)) { ((Component)this).transform.rotation = Quaternion.LookRotation(forward, up); } } } private static Camera? ResolveViewCamera() { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { return Camera.current; } PlayerControllerB localPlayerController = instance.localPlayerController; if ((Object)(object)localPlayerController != (Object)null && !localPlayerController.isPlayerDead) { return localPlayerController.gameplayCamera; } return ((Object)(object)instance.spectateCamera != (Object)null) ? instance.spectateCamera : Camera.current; } } internal sealed class StatusBarConfig { public enum InfectionBarDisplayMode { AlwaysVisible, ShowOnlyWhenInfected } public enum ColorPreset { Green, Red, Orange, Yellow, Blue, Cyan, White, Black, Slate } public static class LethalConfigIntegration { public static void Register(StatusBarConfig config) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //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_006f: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_009a: 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_00aa: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Expected O, but got Unknown //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Expected O, but got Unknown //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Expected O, but got Unknown //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown //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_01d3: Expected O, but got Unknown //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Expected O, but got Unknown //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_01f6: Expected O, but got Unknown //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Expected O, but got Unknown //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected O, but got Unknown //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Expected O, but got Unknown StatusBarConfig config2 = config; LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(config2.enabled, new BoolCheckBoxOptions { RequiresRestart = false })); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(config2.hideInOrbit, new BoolCheckBoxOptions { RequiresRestart = false })); ConfigEntry<float> maxDistance = config2.maxDistance; FloatSliderOptions val = new FloatSliderOptions(); ((BaseRangeOptions<float>)val).Min = 2f; ((BaseRangeOptions<float>)val).Max = 80f; ((BaseOptions)val).RequiresRestart = false; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(maxDistance, val)); ConfigEntry<float> headOffset = config2.headOffset; FloatSliderOptions val2 = new FloatSliderOptions(); ((BaseRangeOptions<float>)val2).Min = 0f; ((BaseRangeOptions<float>)val2).Max = 2f; ((BaseOptions)val2).RequiresRestart = false; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(headOffset, val2)); ConfigEntry<float> barSpacing = config2.barSpacing; FloatSliderOptions val3 = new FloatSliderOptions(); ((BaseRangeOptions<float>)val3).Min = 6f; ((BaseRangeOptions<float>)val3).Max = 48f; ((BaseOptions)val3).RequiresRestart = false; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(barSpacing, val3)); ConfigEntry<float> healthBarYOffset = config2.healthBarYOffset; FloatSliderOptions val4 = new FloatSliderOptions(); ((BaseRangeOptions<float>)val4).Min = -64f; ((BaseRangeOptions<float>)val4).Max = 64f; ((BaseOptions)val4).RequiresRestart = false; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(healthBarYOffset, val4)); ConfigEntry<float> infectionBarYOffset = config2.infectionBarYOffset; FloatSliderOptions val5 = new FloatSliderOptions(); ((BaseRangeOptions<float>)val5).Min = -64f; ((BaseRangeOptions<float>)val5).Max = 64f; ((BaseOptions)val5).RequiresRestart = false; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(infectionBarYOffset, val5)); ConfigEntry<float> uiScale = config2.uiScale; FloatSliderOptions val6 = new FloatSliderOptions(); ((BaseRangeOptions<float>)val6).Min = 0.003f; ((BaseRangeOptions<float>)val6).Max = 0.05f; ((BaseOptions)val6).RequiresRestart = false; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(uiScale, val6)); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(config2.showHealthText, new BoolCheckBoxOptions { RequiresRestart = false })); LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(config2.showInfectionText, new BoolCheckBoxOptions { RequiresRestart = false })); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)new EnumDropDownConfigItem<ColorPreset>(config2.healthColor, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)new EnumDropDownConfigItem<ColorPreset>(config2.infectionColor, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)new EnumDropDownConfigItem<ColorPreset>(config2.backgroundColor, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)(object)new EnumDropDownConfigItem<InfectionBarDisplayMode>(config2.infectionDisplayMode, false)); LethalConfigManager.AddConfigItem((BaseConfigItem)new GenericButtonConfigItem("General", "Refresh all player bars", "Forces all visible player bars to refresh on the next update.", "Refresh", (GenericButtonHandler)delegate { config2.NotifySettingsChanged(); })); } } private readonly ConfigEntry<bool> enabled; private readonly ConfigEntry<bool> hideInOrbit; private readonly ConfigEntry<float> maxDistance; private readonly ConfigEntry<float> headOffset; private readonly ConfigEntry<float> barSpacing; private readonly ConfigEntry<float> healthBarYOffset; private readonly ConfigEntry<float> infectionBarYOffset; private readonly ConfigEntry<float> uiScale; private readonly ConfigEntry<bool> showHealthText; private readonly ConfigEntry<bool> showInfectionText; private readonly ConfigEntry<ColorPreset> healthColor; private readonly ConfigEntry<ColorPreset> infectionColor; private readonly ConfigEntry<ColorPreset> backgroundColor; private readonly ConfigEntry<InfectionBarDisplayMode> infectionDisplayMode; public bool Enabled => enabled.Value; public float MaxDistance => maxDistance.Value; public float HeadOffset => headOffset.Value; public float BarSpacing => barSpacing.Value; public float HealthBarYOffset => healthBarYOffset.Value; public float InfectionBarYOffset => infectionBarYOffset.Value; public float UiScale => uiScale.Value; public bool HideInOrbit => hideInOrbit.Value; public bool ShowHealthText => showHealthText.Value; public bool ShowInfectionText => showInfectionText.Value; public InfectionBarDisplayMode InfectionDisplayMode => infectionDisplayMode.Value; public int Revision { get; private set; } public event Action? SettingsChanged; public static StatusBarConfig Create(ConfigFile configFile) { return new StatusBarConfig(configFile); } private StatusBarConfig(ConfigFile configFile) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Expected O, but got Unknown //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected O, but got Unknown enabled = configFile.Bind<bool>("General", "Enabled", true, "Enable other player status bars."); hideInOrbit = configFile.Bind<bool>("General", "Hide In Orbit", true, "Hide player status bars while the ship is still in orbit."); maxDistance = configFile.Bind<float>("General", "Max Display Distance", 18f, new ConfigDescription("Hide other player status bars beyond this distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 80f), Array.Empty<object>())); headOffset = configFile.Bind<float>("Layout", "Head Offset", 0.65f, new ConfigDescription("Vertical world-space offset above the player head anchor.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); barSpacing = configFile.Bind<float>("Layout", "Bar Spacing", 14f, new ConfigDescription("Vertical spacing between the health bar and infection bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(6f, 48f), Array.Empty<object>())); healthBarYOffset = configFile.Bind<float>("Layout", "Health Bar Y Offset", 0f, new ConfigDescription("Local UI Y offset for the health bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-64f, 64f), Array.Empty<object>())); infectionBarYOffset = configFile.Bind<float>("Layout", "Infection Bar Y Offset", 25f, new ConfigDescription("Local UI Y offset for the infection bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-64f, 64f), Array.Empty<object>())); uiScale = configFile.Bind<float>("Layout", "UI Scale", 0.0085f, new ConfigDescription("World-space scale of the player status bar canvas.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.003f, 0.05f), Array.Empty<object>())); showHealthText = configFile.Bind<bool>("Text", "Show Health Text", true, "Show health numbers on the health bar."); showInfectionText = configFile.Bind<bool>("Text", "Show Infection Text", true, "Show infection percentage on the infection bar."); healthColor = configFile.Bind<ColorPreset>("Colors", "Health Bar Color", ColorPreset.Green, "Fill color preset for the health bar."); infectionColor = configFile.Bind<ColorPreset>("Colors", "Infection Bar Color", ColorPreset.Orange, "Fill color preset for the infection bar."); backgroundColor = configFile.Bind<ColorPreset>("Colors", "Background Color", ColorPreset.Slate, "Background color preset for both bars."); infectionDisplayMode = configFile.Bind<InfectionBarDisplayMode>("General", "Infection Bar Display Mode", InfectionBarDisplayMode.ShowOnlyWhenInfected, "Always show the infection bar, or only show it when infection is above zero."); Subscribe<bool>(enabled); Subscribe<bool>(hideInOrbit); Subscribe<float>(maxDistance); Subscribe<float>(headOffset); Subscribe<float>(barSpacing); Subscribe<float>(healthBarYOffset); Subscribe<float>(infectionBarYOffset); Subscribe<float>(uiScale); Subscribe<bool>(showHealthText); Subscribe<bool>(showInfectionText); Subscribe<ColorPreset>(healthColor); Subscribe<ColorPreset>(infectionColor); Subscribe<ColorPreset>(backgroundColor); Subscribe<InfectionBarDisplayMode>(infectionDisplayMode); } public Color GetHealthFillColor() { //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_0019: Unknown result type (might be due to invalid IL or missing references) return ResolveColor(healthColor.Value, 0.95f); } public Color GetInfectionFillColor() { //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_0019: Unknown result type (might be due to invalid IL or missing references) return ResolveColor(infectionColor.Value, 0.95f); } public Color GetBackgroundColor() { //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_0019: Unknown result type (might be due to invalid IL or missing references) return ResolveColor(backgroundColor.Value, 0.78f); } public Color GetBorderColor() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_0027: Unknown result type (might be due to invalid IL or missing references) Color val = GetBackgroundColor(); val.a = 1f; return Color.Lerp(val, Color.white, 0.35f); } private void Subscribe<T>(ConfigEntry<T> entry) { entry.SettingChanged += delegate { NotifySettingsChanged(); }; } private void NotifySettingsChanged() { Revision++; this.SettingsChanged?.Invoke(); } private static Color ResolveColor(ColorPreset preset, float alpha) { //IL_0040: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_010e: 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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) if (1 == 0) { } Color val = (Color)(preset switch { ColorPreset.Green => new Color(0.18f, 0.86f, 0.32f, alpha), ColorPreset.Red => new Color(0.88f, 0.25f, 0.22f, alpha), ColorPreset.Orange => new Color(0.93f, 0.47f, 0.16f, alpha), ColorPreset.Yellow => new Color(0.95f, 0.82f, 0.18f, alpha), ColorPreset.Blue => new Color(0.28f, 0.58f, 0.92f, alpha), ColorPreset.Cyan => new Color(0.18f, 0.83f, 0.88f, alpha), ColorPreset.White => new Color(0.95f, 0.95f, 0.95f, alpha), ColorPreset.Black => new Color(0.08f, 0.08f, 0.08f, alpha), _ => new Color(0.12f, 0.15f, 0.2f, alpha), }); if (1 == 0) { } Color result = val; result.a = alpha; return result; } } }