Decompiled source of PlayersInfo v0.2.5

PlayersInfo.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DG.Tweening;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak.Afflictions;
using Photon.Pun;
using PlayersInfo.Helpers;
using PlayersInfo.MonoBehaviours;
using PlayersInfo.Patches;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("PlayersInfo")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("P R C")]
[assembly: AssemblyProduct("PlayersInfo")]
[assembly: AssemblyCopyright("Copyright © P R C 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ea6b8f7a-e2d5-4b3e-9025-f87255eeac89")]
[assembly: AssemblyFileVersion("0.2.5.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.5.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace PlayersInfo
{
	[BepInPlugin("com.players.info", "PlayersInfo", "0.2.5")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class PlayersInfoPlugin : BaseUnityPlugin
	{
		public enum HudAnchor
		{
			TopLeft,
			TopRight,
			BottomLeft,
			BottomRight
		}

		public enum TeammateSortMode
		{
			Stable,
			Distance
		}

		public enum SpectatorNearbyCenterMode
		{
			LocalCharacter,
			ObservedCharacter
		}

		public enum TeammateInventoryDisplayMode
		{
			Disabled,
			ContentsOnly,
			ContentsAndJetpackFuel
		}

		public enum AfflictionIconDisplayMode
		{
			ShowAll,
			HideTeammates,
			HideAll
		}

		public const string PluginGuid = "com.players.info";

		public const string PluginName = "PlayersInfo";

		public const string PluginVersion = "0.2.5";

		public static ConfigEntry<bool> CfgModEnabled;

		public static ConfigEntry<bool> CfgEnableStaminaBar;

		public static ConfigEntry<bool> CfgShowStaminaValue;

		public static ConfigEntry<bool> CfgShowExtraStaminaCap;

		public static ConfigEntry<AfflictionIconDisplayMode> CfgAfflictionIconDisplayMode;

		public static ConfigEntry<TeammateInventoryDisplayMode> CfgInventoryDisplayMode;

		public static ConfigEntry<HudAnchor> CfgAnchor;

		public static ConfigEntry<float> CfgOffsetX;

		public static ConfigEntry<float> CfgOffsetY;

		public static ConfigEntry<float> CfgNearbyRange;

		public static ConfigEntry<int> CfgMaxNearbyCount;

		public static ConfigEntry<TeammateSortMode> CfgTeammateSortMode;

		public static ConfigEntry<SpectatorNearbyCenterMode> CfgSpectatorNearbyCenter;

		public static ConfigEntry<bool> CfgRoundStamina;

		public static ConfigEntry<bool> CfgDebugLogging;

		private Harmony _harmony;

		private float _nextSafeTick;

		private const float SafeTickInterval = 1f;

		private const string DisplaySection = "Display";

		private const string AdvancedSection = "Advanced";

		private static readonly FieldInfo OrphanedEntriesField = typeof(ConfigFile).GetField("<OrphanedEntries>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			try
			{
				PluginLogger.Log = ((BaseUnityPlugin)this).Logger;
				LanguageHelper.IsChinese = LanguageHelper.DetectChineseLanguage();
				BindConfig();
				_harmony = new Harmony("com.players.info");
				_harmony.PatchAll();
				try
				{
					ModConfigLocalization.PatchDisplayNames(_harmony);
				}
				catch (Exception ex)
				{
					PluginLogger.ThrottleWarn("modconfig_patch", "ModConfig localization patch skipped: " + ex.Message);
				}
				LocalizedText.OnLangugageChanged = (Action)Delegate.Combine(LocalizedText.OnLangugageChanged, new Action(OnGameLanguageChanged));
				SceneManager.sceneLoaded += OnSceneLoaded;
				((MonoBehaviour)this).StartCoroutine(DeferredLanguageRefresh());
				if (CfgModEnabled.Value)
				{
					TeamRosterTracker.EnsureExists();
				}
				PluginLogger.Info("PlayersInfo v0.2.5 loaded. Lang=" + (LanguageHelper.IsChinese ? "zh" : "en"));
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("[{0}] Awake failed: {1}", "PlayersInfo", arg));
			}
		}

		private void BindConfig()
		{
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Expected O, but got Unknown
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Expected O, but got Unknown
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Expected O, but got Unknown
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Expected O, but got Unknown
			CfgModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", ReadLegacyValue("General", "Enabled", fallback: true), LanguageHelper.L("Master switch. Turn off to disable all features.", "总开关,关闭后全部功能失效。"));
			CfgEnableStaminaBar = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "EnableStaminaBar", ReadLegacyValue("Features", "EnableStaminaBar", fallback: true), LanguageHelper.L("Show teammate stamina bars (with extra stamina).", "显示队友体力条(含临时体力)。"));
			CfgShowStaminaValue = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowStaminaValue", ReadLegacyValue("Features", "ShowStaminaValue", fallback: true), LanguageHelper.L("Show numeric stamina value on the bar.", "在体力条右侧显示数值。"));
			CfgShowExtraStaminaCap = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowExtraStaminaCap", true, LanguageHelper.L("Show teammate extra stamina as current/cap. Turn off to show current only.", "队友额外体力显示为 当前/上限。关闭后只显示当前值。"));
			CfgAfflictionIconDisplayMode = ((BaseUnityPlugin)this).Config.Bind<AfflictionIconDisplayMode>("Display", "AfflictionIconDisplayMode", AfflictionIconDisplayMode.ShowAll, LanguageHelper.L("Choose whether status icons are shown for everyone, hidden for teammates, or hidden for everyone.", "选择不隐藏状态图标、隐藏队友状态图标,或隐藏所有人的状态图标。"));
			TeammateInventoryDisplayMode teammateInventoryDisplayMode = ReadInventoryDisplayMode();
			RemoveConfigEntry("Display", "EnableInventoryRow");
			RemoveConfigEntry("Features", "EnableInventoryRow");
			CfgInventoryDisplayMode = ((BaseUnityPlugin)this).Config.Bind<TeammateInventoryDisplayMode>("Display", "EnableInventoryRow", teammateInventoryDisplayMode, LanguageHelper.L("Choose whether teammate inventory is hidden, shows contents only, or also shows jetpack fuel.", "选择隐藏队友物品栏、仅显示物品内容,或同时显示喷气背包燃料。"));
			CfgAnchor = ((BaseUnityPlugin)this).Config.Bind<HudAnchor>("Display", "Anchor", ReadLegacyValue("Layout", "Anchor", HudAnchor.BottomLeft), LanguageHelper.L("HUD anchor corner on screen.", "HUD 屏幕锚点位置。"));
			CfgOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "OffsetX", ReadLegacyValue("Layout", "OffsetX", 0f), new ConfigDescription(LanguageHelper.L("Additional X offset in pixels.", "X 方向像素偏移。"), (AcceptableValueBase)(object)new AcceptableValueRange<float>(-800f, 800f), Array.Empty<object>()));
			CfgOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "OffsetY", ReadLegacyValue("Layout", "OffsetY", 0f), new ConfigDescription(LanguageHelper.L("Additional Y offset in pixels.", "Y 方向像素偏移。"), (AcceptableValueBase)(object)new AcceptableValueRange<float>(-800f, 800f), Array.Empty<object>()));
			CfgNearbyRange = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "NearbyRange", ReadLegacyValue("Nearby", "NearbyRange", 30f), new ConfigDescription(LanguageHelper.L("Max distance (meters) to show a teammate bar. 0 = unlimited.", "显示队友体力条的最大距离(米)。0 表示不限。"), (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), Array.Empty<object>()));
			CfgMaxNearbyCount = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "MaxNearbyCount", ReadLegacyValue("Nearby", "MaxNearbyCount", 3), new ConfigDescription(LanguageHelper.L("Max number of nearest teammates to show bars for.", "最多显示几个最近的队友体力条。"), (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 8), Array.Empty<object>()));
			CfgTeammateSortMode = ((BaseUnityPlugin)this).Config.Bind<TeammateSortMode>("Display", "TeammateSortMode", TeammateSortMode.Stable, LanguageHelper.L("Order teammate bars by first appearance, or by current distance.", "队友条按首次出现顺序或当前距离排序。"));
			CfgSpectatorNearbyCenter = ((BaseUnityPlugin)this).Config.Bind<SpectatorNearbyCenterMode>("Display", "SpectatorNearbyCenter", SpectatorNearbyCenterMode.ObservedCharacter, LanguageHelper.L("While spectating, use the local character or the observed character as the nearby-player center.", "观战时,选择以本机角色或被观看角色作为附近玩家中心。"));
			CfgRoundStamina = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "RoundStaminaValue", ReadLegacyValue("Features", "RoundStaminaValue", fallback: true), LanguageHelper.L("If true, round stamina numeric value to nearest integer; else 1 decimal.", "为 true 时体力数值四舍五入到整数,否则显示 1 位小数。"));
			CfgDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "DebugLogging", ReadLegacyValue("Diagnostics", "DebugLogging", fallback: false), LanguageHelper.L("Enable verbose diagnostic logs for distance, stamina, inventory, and cloned UI internals.", "启用详细诊断日志(距离、体力、物品栏和克隆 UI 内部状态)。"));
			ModConfigLocalization.ApplyLocalizedDescriptions();
			RemoveLegacyConfigEntries();
			MigrateDefaultHudAnchor();
			CfgModEnabled.SettingChanged += OnStructuralConfigChanged;
			CfgEnableStaminaBar.SettingChanged += OnStructuralConfigChanged;
			CfgShowStaminaValue.SettingChanged += OnStructuralConfigChanged;
			CfgInventoryDisplayMode.SettingChanged += OnStructuralConfigChanged;
			CfgAnchor.SettingChanged += OnLayoutConfigChanged;
			CfgOffsetX.SettingChanged += OnLayoutConfigChanged;
			CfgOffsetY.SettingChanged += OnLayoutConfigChanged;
			try
			{
				((BaseUnityPlugin)this).Config.Save();
			}
			catch
			{
			}
		}

		private TeammateInventoryDisplayMode ReadInventoryDisplayMode()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			try
			{
				ConfigDefinition val = new ConfigDefinition("Display", "EnableInventoryRow");
				ConfigEntry<TeammateInventoryDisplayMode> val2 = default(ConfigEntry<TeammateInventoryDisplayMode>);
				if (((BaseUnityPlugin)this).Config.TryGetEntry<TeammateInventoryDisplayMode>(val, ref val2))
				{
					return val2.Value;
				}
				ConfigEntry<bool> val3 = default(ConfigEntry<bool>);
				if (((BaseUnityPlugin)this).Config.TryGetEntry<bool>(val, ref val3))
				{
					return val3.Value ? TeammateInventoryDisplayMode.ContentsOnly : TeammateInventoryDisplayMode.Disabled;
				}
				if (OrphanedEntriesField != null && OrphanedEntriesField.GetValue(((BaseUnityPlugin)this).Config) is Dictionary<ConfigDefinition, string> dictionary && dictionary.TryGetValue(val, out var value))
				{
					if (Enum.TryParse<TeammateInventoryDisplayMode>(value, ignoreCase: true, out var result))
					{
						return result;
					}
					if (bool.TryParse(value, out var result2))
					{
						return result2 ? TeammateInventoryDisplayMode.ContentsOnly : TeammateInventoryDisplayMode.Disabled;
					}
				}
				return ReadLegacyValue("Features", "EnableInventoryRow", fallback: true) ? TeammateInventoryDisplayMode.ContentsOnly : TeammateInventoryDisplayMode.Disabled;
			}
			catch
			{
				return TeammateInventoryDisplayMode.ContentsOnly;
			}
		}

		private void MigrateDefaultHudAnchor()
		{
			if (CfgAnchor == null || CfgAnchor.Value != HudAnchor.TopLeft)
			{
				return;
			}
			CfgAnchor.Value = HudAnchor.BottomLeft;
			try
			{
				((BaseUnityPlugin)this).Config.Save();
				PluginLogger.Info("Migrated the default HUD anchor from TopLeft to BottomLeft.");
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleWarn("anchor_migrate_save", "HUD anchor migration save failed: " + ex.Message);
			}
		}

		private T ReadLegacyValue<T>(string section, string key, T fallback)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			try
			{
				ConfigEntry<T> val = default(ConfigEntry<T>);
				if (((BaseUnityPlugin)this).Config.TryGetEntry<T>(section, key, ref val))
				{
					return val.Value;
				}
				if (OrphanedEntriesField != null && OrphanedEntriesField.GetValue(((BaseUnityPlugin)this).Config) is Dictionary<ConfigDefinition, string> dictionary && dictionary.TryGetValue(new ConfigDefinition(section, key), out var value))
				{
					if (typeof(T).IsEnum)
					{
						return (T)Enum.Parse(typeof(T), value, ignoreCase: true);
					}
					return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture);
				}
			}
			catch
			{
			}
			return fallback;
		}

		private void RemoveLegacyConfigEntries()
		{
			if ((0u | (RemoveConfigEntry("General", "Enabled") ? 1u : 0u) | (RemoveConfigEntry("Features", "EnableStaminaBar") ? 1u : 0u) | (RemoveConfigEntry("Features", "ShowStaminaValue") ? 1u : 0u) | (RemoveConfigEntry("Features", "EnableInventoryRow") ? 1u : 0u) | (RemoveConfigEntry("Features", "RoundStaminaValue") ? 1u : 0u) | (RemoveConfigEntry("Layout", "Anchor") ? 1u : 0u) | (RemoveConfigEntry("Layout", "OffsetX") ? 1u : 0u) | (RemoveConfigEntry("Layout", "OffsetY") ? 1u : 0u) | (RemoveConfigEntry("Nearby", "NearbyRange") ? 1u : 0u) | (RemoveConfigEntry("Nearby", "MaxNearbyCount") ? 1u : 0u) | (RemoveConfigEntry("Diagnostics", "DebugLogging") ? 1u : 0u)) == 0)
			{
				return;
			}
			try
			{
				((BaseUnityPlugin)this).Config.Save();
				PluginLogger.Info("Migrated config sections to Display/Advanced.");
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleWarn("cfg_migrate_save", "Config migration save failed: " + ex.Message);
			}
		}

		private bool RemoveConfigEntry(string section, string key)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			try
			{
				ConfigDefinition val = new ConfigDefinition(section, key);
				bool result = false;
				if (((BaseUnityPlugin)this).Config.ContainsKey(val))
				{
					result = ((BaseUnityPlugin)this).Config.Remove(val);
				}
				if (OrphanedEntriesField != null && OrphanedEntriesField.GetValue(((BaseUnityPlugin)this).Config) is Dictionary<ConfigDefinition, string> dictionary && dictionary.Remove(val))
				{
					result = true;
				}
				return result;
			}
			catch
			{
				return false;
			}
		}

		private void OnStructuralConfigChanged(object sender, EventArgs e)
		{
			OnAnyConfigChanged();
		}

		private void OnLayoutConfigChanged(object sender, EventArgs e)
		{
			try
			{
				if ((Object)(object)TeammateBarsCoordinator.Instance != (Object)null)
				{
					TeammateBarsCoordinator.Instance.RefreshLayout();
				}
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleError("layout_changed", "HUD layout refresh failed: " + ex.Message);
			}
		}

		private void OnAnyConfigChanged()
		{
			try
			{
				if (!CfgModEnabled.Value)
				{
					if ((Object)(object)TeammateBarsCoordinator.Instance != (Object)null)
					{
						TeammateBarsCoordinator.Instance.ClearAll();
					}
					IconSpriteCache.Clear();
				}
				else
				{
					TeamRosterTracker tracker = TeamRosterTracker.EnsureExists();
					TeammateBarsCoordinator teammateBarsCoordinator = TeammateBarsCoordinator.EnsureExists();
					teammateBarsCoordinator.Init();
					teammateBarsCoordinator.AttachToTracker(tracker);
					teammateBarsCoordinator.OnConfigChanged();
				}
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleError("cfg_changed", "OnAnyConfigChanged failed: " + ex.Message);
			}
		}

		private IEnumerator DeferredLanguageRefresh()
		{
			yield return null;
			float deadline = Time.realtimeSinceStartup + 10f;
			while ((Object)(object)GUIManager.instance == (Object)null && Time.realtimeSinceStartup < deadline)
			{
				yield return null;
			}
			OnGameLanguageChanged();
		}

		private void OnGameLanguageChanged()
		{
			LanguageHelper.IsChinese = LanguageHelper.DetectChineseLanguage();
			ModConfigLocalization.ApplyLocalizedDescriptions();
			ModConfigLocalization.RefreshVisibleUi();
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			try
			{
				IconSpriteCache.Clear();
				if ((Object)(object)TeamRosterTracker.Instance != (Object)null)
				{
					TeamRosterTracker.Instance.ClearForSceneReload();
				}
				if ((Object)(object)TeammateBarsCoordinator.Instance != (Object)null)
				{
					TeammateBarsCoordinator.Instance.ClearAll();
				}
				LocalStaminaBarPatch.ResetForSceneReload();
				PluginLogger.ClearThrottle();
			}
			catch (Exception ex)
			{
				PluginLogger.Error("OnSceneLoaded cleanup failed: " + ex.Message);
			}
		}

		private void Update()
		{
			if (!(Time.unscaledTime < _nextSafeTick))
			{
				_nextSafeTick = Time.unscaledTime + 1f;
				SafeTick();
			}
		}

		private void SafeTick()
		{
			try
			{
				if (CfgModEnabled.Value && !((Object)(object)TeamRosterTracker.Instance == (Object)null) && (Object)(object)TeammateBarsCoordinator.Instance == (Object)null && (Object)(object)Character.localCharacter != (Object)null)
				{
					TeamRosterTracker instance = TeamRosterTracker.Instance;
					TeammateBarsCoordinator teammateBarsCoordinator = TeammateBarsCoordinator.EnsureExists();
					teammateBarsCoordinator.Init();
					teammateBarsCoordinator.AttachToTracker(instance);
					instance.RequestRescan();
					PluginLogger.ThrottleInfo("coord_fallback", "BarsCoordinator fallback-initialized in SafeTick.");
				}
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleError("safetick", "SafeTick failed: " + ex.Message);
			}
		}

		private void OnDestroy()
		{
			try
			{
				LocalizedText.OnLangugageChanged = (Action)Delegate.Remove(LocalizedText.OnLangugageChanged, new Action(OnGameLanguageChanged));
				ModConfigLocalization.Shutdown();
				SceneManager.sceneLoaded -= OnSceneLoaded;
				if (CfgModEnabled != null)
				{
					CfgModEnabled.SettingChanged -= OnStructuralConfigChanged;
				}
				if (CfgEnableStaminaBar != null)
				{
					CfgEnableStaminaBar.SettingChanged -= OnStructuralConfigChanged;
				}
				if (CfgShowStaminaValue != null)
				{
					CfgShowStaminaValue.SettingChanged -= OnStructuralConfigChanged;
				}
				if (CfgInventoryDisplayMode != null)
				{
					CfgInventoryDisplayMode.SettingChanged -= OnStructuralConfigChanged;
				}
				if (CfgAnchor != null)
				{
					CfgAnchor.SettingChanged -= OnLayoutConfigChanged;
				}
				if (CfgOffsetX != null)
				{
					CfgOffsetX.SettingChanged -= OnLayoutConfigChanged;
				}
				if (CfgOffsetY != null)
				{
					CfgOffsetY.SettingChanged -= OnLayoutConfigChanged;
				}
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
		}
	}
}
namespace PlayersInfo.Patches
{
	[HarmonyPatch(typeof(GUIManager), "Start")]
	internal static class GUIManagerReadyPatch
	{
		[HarmonyPostfix]
		private static void Postfix()
		{
			try
			{
				TeamRosterTracker teamRosterTracker = TeamRosterTracker.EnsureExists();
				TeammateBarsCoordinator teammateBarsCoordinator = TeammateBarsCoordinator.EnsureExists();
				teammateBarsCoordinator.Init();
				teammateBarsCoordinator.AttachToTracker(teamRosterTracker);
				teamRosterTracker.RequestRescan();
				PluginLogger.Info("Teammate bars initialized on GUIManager.Start");
			}
			catch (Exception ex)
			{
				PluginLogger.Error("GUIManagerReadyPatch failed: " + ex.Message);
			}
		}
	}
	[HarmonyPatch(typeof(StaminaBar), "Update")]
	internal static class LocalStaminaBarPatch
	{
		private static TMP_Text _staminaValueText;

		private static TMP_Text _extraValueText;

		private static TMP_Text _zeroStaminaHungerCountdownText;

		private static TMP_Text[] _afflictionTexts;

		private static StaminaBar _initedFor;

		private static float _nextValueRefreshTime;

		private static float _nextAfflictionRefreshTime;

		private static float _nextHungerCalculationTime;

		private static string _cachedHungerTime = string.Empty;

		private static Character _infiniteDisplayCharacter;

		private static bool _wasInfiniteStamina;

		private static float _frozenInfiniteStamina01;

		private const float ValueRefreshInterval = 0.25f;

		private const float AfflictionRefreshInterval = 0.5f;

		[HarmonyPostfix]
		private static void Postfix(StaminaBar __instance)
		{
			//IL_03b0: 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_03e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)__instance == (Object)null || (Object)(object)GUIManager.instance == (Object)null || (Object)(object)GUIManager.instance.bar == (Object)null || __instance != GUIManager.instance.bar)
				{
					return;
				}
				if (PlayersInfoPlugin.CfgModEnabled != null && !PlayersInfoPlugin.CfgModEnabled.Value)
				{
					SetLocalAfflictionIcons(__instance, visible: true);
					HideAll();
					ResetInfiniteStaminaDisplay();
					return;
				}
				if (_initedFor != __instance)
				{
					ResetForSceneReload();
				}
				EnsureInit(__instance);
				ApplyLocalAfflictionIconVisibility(__instance);
				bool flag = PlayersInfoPlugin.CfgShowStaminaValue == null || PlayersInfoPlugin.CfgShowStaminaValue.Value;
				Character observedOrLocal = DisplayCharacterHelper.GetObservedOrLocal();
				float num = 0f;
				float num2 = 0f;
				float maxStamina = 1f;
				bool infiniteStamina = false;
				try
				{
					if ((Object)(object)observedOrLocal != (Object)null && (Object)(object)observedOrLocal.data != (Object)null)
					{
						num = observedOrLocal.data.currentStamina;
						num2 = observedOrLocal.data.extraStamina;
						maxStamina = Mathf.Max(0f, observedOrLocal.GetMaxStamina());
						infiniteStamina = observedOrLocal.infiniteStam;
					}
				}
				catch
				{
				}
				bool flag2 = (Object)(object)observedOrLocal != (Object)null && (Object)(object)observedOrLocal.data != (Object)null && observedOrLocal.data.dead;
				float num3 = ResolveDisplayedMainStamina(observedOrLocal, num, maxStamina, infiniteStamina, flag2);
				CorrectOverflowingStaminaWidth(__instance, num3, num, maxStamina, infiniteStamina);
				bool flag3 = Time.unscaledTime >= _nextValueRefreshTime;
				if (flag3)
				{
					_nextValueRefreshTime = Time.unscaledTime + 0.25f;
				}
				if ((Object)(object)_staminaValueText != (Object)null)
				{
					if (flag3 && flag && (Object)(object)observedOrLocal != (Object)null && !flag2 && (Object)(object)__instance.staminaBar != (Object)null)
					{
						UpdateValueText(_staminaValueText, num3 * 100f, __instance.staminaBar.sizeDelta.x);
					}
					else if (!flag || (Object)(object)observedOrLocal == (Object)null || flag2)
					{
						SetActive(_staminaValueText, active: false);
					}
				}
				if (flag3 || flag2 || (Object)(object)observedOrLocal == (Object)null)
				{
					UpdateHungerCountdown(__instance, observedOrLocal, flag2, flag, num3);
				}
				if ((Object)(object)_extraValueText != (Object)null)
				{
					bool flag4 = (Object)(object)__instance.extraBar != (Object)null && ((Component)__instance.extraBar).gameObject.activeSelf;
					if (flag3 && flag && (Object)(object)observedOrLocal != (Object)null && !flag2 && flag4 && (Object)(object)__instance.extraBarStamina != (Object)null)
					{
						UpdateExtraValueText(_extraValueText, num2 * 100f, __instance.extraBarStamina.sizeDelta.x);
					}
					else if (!flag || (Object)(object)observedOrLocal == (Object)null || flag2 || !flag4)
					{
						SetActive(_extraValueText, active: false);
					}
				}
				bool num4 = Time.unscaledTime >= _nextAfflictionRefreshTime;
				if (num4)
				{
					_nextAfflictionRefreshTime = Time.unscaledTime + 0.5f;
				}
				if (!num4 || __instance.afflictions == null || _afflictionTexts == null)
				{
					return;
				}
				Character val = observedOrLocal;
				CharacterAfflictions ca = null;
				try
				{
					if ((Object)(object)val != (Object)null && val.refs != null)
					{
						ca = val.refs.afflictions;
					}
				}
				catch
				{
				}
				int num5 = Mathf.Min(__instance.afflictions.Length, _afflictionTexts.Length);
				for (int i = 0; i < num5; i++)
				{
					BarAffliction val2 = __instance.afflictions[i];
					TMP_Text val3 = _afflictionTexts[i];
					if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
					{
						continue;
					}
					float value = AfflictionValueHelper.GetValue(val, val2);
					if (flag && (Object)(object)val != (Object)null && !flag2 && value > 0.01f && val2.width > 18f)
					{
						string text = Mathf.Clamp(Mathf.RoundToInt(value * 100f), 0, 999).ToString();
						string text2 = AfflictionTimeHelper.FormatTime(AfflictionTimeHelper.GetReductionTimeRemaining(ca, val2.afflictionType));
						string text3 = (string.IsNullOrEmpty(text2) ? text : (text + "(" + text2 + ")"));
						if (val3.GetPreferredValues(text3).x > val2.width)
						{
							text3 = text;
						}
						if (val3.GetPreferredValues(text3).x <= val2.width)
						{
							if (val3.text != text3)
							{
								val3.text = text3;
							}
							SetActive(val3, active: true);
						}
						else
						{
							SetActive(val3, active: false);
						}
					}
					else
					{
						SetActive(val3, active: false);
					}
				}
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleError("local_bar_patch", "LocalStaminaBarPatch failed: " + ex.Message);
			}
		}

		public static void ResetForSceneReload()
		{
			_staminaValueText = null;
			_extraValueText = null;
			_zeroStaminaHungerCountdownText = null;
			_afflictionTexts = null;
			_initedFor = null;
			_nextValueRefreshTime = 0f;
			_nextAfflictionRefreshTime = 0f;
			_nextHungerCalculationTime = 0f;
			_cachedHungerTime = string.Empty;
			ResetInfiniteStaminaDisplay();
		}

		private static float ResolveDisplayedMainStamina(Character displayCharacter, float currentStamina, float maxStamina, bool infiniteStamina, bool displayDead)
		{
			if ((Object)(object)displayCharacter == (Object)null || displayDead)
			{
				ResetInfiniteStaminaDisplay();
				return 0f;
			}
			if (_infiniteDisplayCharacter != displayCharacter)
			{
				_infiniteDisplayCharacter = displayCharacter;
				_wasInfiniteStamina = false;
				_frozenInfiniteStamina01 = 0f;
			}
			float num = Mathf.Clamp(currentStamina, 0f, maxStamina);
			if (infiniteStamina)
			{
				if (!_wasInfiniteStamina)
				{
					_frozenInfiniteStamina01 = num;
				}
				_wasInfiniteStamina = true;
				return _frozenInfiniteStamina01;
			}
			_wasInfiniteStamina = false;
			_frozenInfiniteStamina01 = 0f;
			return num;
		}

		private static void CorrectOverflowingStaminaWidth(StaminaBar bar, float displayedStamina, float rawStamina, float maxStamina, bool infiniteStamina)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)bar == (Object)null) && !((Object)(object)bar.staminaBar == (Object)null) && !((Object)(object)bar.fullBar == (Object)null) && (infiniteStamina || !(rawStamina >= 0f) || !(rawStamina <= maxStamina + 0.0001f)))
			{
				float num = Mathf.Max(0f, displayedStamina * bar.fullBar.sizeDelta.x + bar.staminaBarOffset);
				Vector2 sizeDelta = bar.staminaBar.sizeDelta;
				if (!(Mathf.Abs(sizeDelta.x - num) < 0.01f))
				{
					sizeDelta.x = num;
					bar.staminaBar.sizeDelta = sizeDelta;
				}
			}
		}

		private static void ResetInfiniteStaminaDisplay()
		{
			_infiniteDisplayCharacter = null;
			_wasInfiniteStamina = false;
			_frozenInfiniteStamina01 = 0f;
		}

		private static void EnsureInit(StaminaBar bar)
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			if (_initedFor == bar && (Object)(object)_staminaValueText != (Object)null)
			{
				return;
			}
			try
			{
				if ((Object)(object)bar.staminaBar != (Object)null && (Object)(object)_staminaValueText == (Object)null)
				{
					_staminaValueText = AddStretchText(((Component)bar.staminaBar).gameObject, "PI_LocalStaminaValue", 20f, bold: false);
				}
				if ((Object)(object)bar.extraBarStamina != (Object)null && (Object)(object)_extraValueText == (Object)null)
				{
					_extraValueText = AddStretchText(((Component)bar.extraBarStamina).gameObject, "PI_LocalExtraStaminaValue", 20f, bold: false);
				}
				if ((Object)(object)bar.maxStaminaBar != (Object)null && (Object)(object)_zeroStaminaHungerCountdownText == (Object)null)
				{
					_zeroStaminaHungerCountdownText = AddStretchText(((Component)bar.maxStaminaBar).gameObject, "PI_LocalZeroStaminaHungerCountdown", 20f, bold: false);
					if ((Object)(object)_zeroStaminaHungerCountdownText != (Object)null)
					{
						((Graphic)_zeroStaminaHungerCountdownText).color = new Color(1f, 0.9f, 0.25f, 1f);
					}
				}
				if (bar.afflictions != null && _afflictionTexts == null)
				{
					_afflictionTexts = (TMP_Text[])(object)new TMP_Text[bar.afflictions.Length];
					for (int i = 0; i < bar.afflictions.Length; i++)
					{
						BarAffliction val = bar.afflictions[i];
						if (!((Object)(object)val == (Object)null))
						{
							_afflictionTexts[i] = AddStretchText(((Component)val).gameObject, "PI_LocalAffPct_" + i, 16f, bold: true);
						}
					}
				}
				_initedFor = bar;
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleWarn("local_bar_init", "LocalStaminaBarPatch.EnsureInit failed: " + ex.Message);
			}
		}

		private static void UpdateValueText(TMP_Text txt, float value01Mul100, float widthPx)
		{
			bool flag = true;
			try
			{
				flag = PlayersInfoPlugin.CfgRoundStamina == null || PlayersInfoPlugin.CfgRoundStamina.Value;
			}
			catch
			{
			}
			if (widthPx < 15f)
			{
				SetActive(txt, active: false);
				return;
			}
			if (flag || widthPx < 30f)
			{
				txt.text = Mathf.Round(value01Mul100).ToString();
			}
			else
			{
				txt.text = value01Mul100.ToString("F1");
			}
			SetActive(txt, active: true);
		}

		private static void UpdateExtraValueText(TMP_Text txt, float currentPercent, float widthPx)
		{
			if (widthPx < 15f)
			{
				SetActive(txt, active: false);
				return;
			}
			txt.text = Mathf.Clamp(Mathf.RoundToInt(currentPercent), 0, 100).ToString();
			SetActive(txt, active: true);
		}

		private static void UpdateHungerCountdown(StaminaBar bar, Character displayCharacter, bool displayDead, bool showValue, float displayedMainStamina)
		{
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			SetActive(_zeroStaminaHungerCountdownText, active: false);
			if ((Object)(object)_staminaValueText == (Object)null || (Object)(object)bar == (Object)null || (Object)(object)bar.staminaBar == (Object)null || !showValue || (Object)(object)displayCharacter == (Object)null || displayDead || !DisplayCharacterHelper.IsLocalDisplay(displayCharacter))
			{
				return;
			}
			if (Time.unscaledTime >= _nextHungerCalculationTime)
			{
				_nextHungerCalculationTime = Time.unscaledTime + 0.5f;
				float hungerTickTimeRemaining = AfflictionTimeHelper.GetHungerTickTimeRemaining(displayCharacter);
				_cachedHungerTime = ((hungerTickTimeRemaining > 0f) ? AfflictionTimeHelper.FormatTime(hungerTickTimeRemaining) : string.Empty);
			}
			if (string.IsNullOrEmpty(_cachedHungerTime))
			{
				return;
			}
			string text = "(" + _cachedHungerTime + ")";
			if (displayedMainStamina <= 0.005f)
			{
				if ((Object)(object)_zeroStaminaHungerCountdownText == (Object)null || (Object)(object)bar.maxStaminaBar == (Object)null || !((Component)bar.maxStaminaBar).gameObject.activeInHierarchy)
				{
					return;
				}
				float x = bar.maxStaminaBar.sizeDelta.x;
				float x2 = _zeroStaminaHungerCountdownText.GetPreferredValues(text).x;
				if (!(x <= 0f) && !(x2 > x))
				{
					if (_zeroStaminaHungerCountdownText.text != text)
					{
						_zeroStaminaHungerCountdownText.text = text;
					}
					SetActive(_zeroStaminaHungerCountdownText, active: true);
				}
				return;
			}
			float x3 = bar.staminaBar.sizeDelta.x;
			if (!((Component)_staminaValueText).gameObject.activeInHierarchy || !((Component)bar.staminaBar).gameObject.activeInHierarchy || x3 <= bar.minStaminaBarWidth)
			{
				return;
			}
			string text2 = " " + text;
			if (_staminaValueText.GetPreferredValues(_staminaValueText.text + text2).x <= x3)
			{
				string text3 = _staminaValueText.text + text2;
				if (_staminaValueText.text != text3)
				{
					_staminaValueText.text = text3;
				}
			}
		}

		private static void ApplyLocalAfflictionIconVisibility(StaminaBar bar)
		{
			bool visible = PlayersInfoPlugin.CfgAfflictionIconDisplayMode == null || PlayersInfoPlugin.CfgAfflictionIconDisplayMode.Value != PlayersInfoPlugin.AfflictionIconDisplayMode.HideAll;
			SetLocalAfflictionIcons(bar, visible);
		}

		private static void SetLocalAfflictionIcons(StaminaBar bar, bool visible)
		{
			if ((Object)(object)bar == (Object)null || bar.afflictions == null || (Object)(object)((Component)bar).transform.parent == (Object)null)
			{
				return;
			}
			Transform parent = ((Component)bar).transform.parent;
			for (int i = 0; i < bar.afflictions.Length; i++)
			{
				BarAffliction val = bar.afflictions[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.icon == (Object)null) && !((Object)(object)((Component)val).transform == (Object)null) && ((Component)val).transform.IsChildOf(parent) && ((Component)val.icon).transform.IsChildOf(parent) && !((Object)(object)((Component)val).GetComponentInParent<TeammateBarDriver>() != (Object)null) && !((Object)(object)((Component)val.icon).GetComponentInParent<TeammateBarDriver>() != (Object)null) && ((Behaviour)val.icon).enabled != visible)
				{
					((Behaviour)val.icon).enabled = visible;
				}
			}
		}

		private static void SetActive(TMP_Text txt, bool active)
		{
			if (!((Object)(object)txt == (Object)null) && (Object)(object)((Component)txt).gameObject != (Object)null && ((Component)txt).gameObject.activeSelf != active)
			{
				((Component)txt).gameObject.SetActive(active);
			}
		}

		private static void HideAll()
		{
			SetActive(_staminaValueText, active: false);
			SetActive(_extraValueText, active: false);
			SetActive(_zeroStaminaHungerCountdownText, active: false);
			if (_afflictionTexts != null)
			{
				for (int i = 0; i < _afflictionTexts.Length; i++)
				{
					SetActive(_afflictionTexts[i], active: false);
				}
			}
		}

		private static TMP_Text AddStretchText(GameObject host, string name, float fontSize, bool bold)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)host == (Object)null)
				{
					return null;
				}
				GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
				val.transform.SetParent(host.transform, false);
				RectTransform component = val.GetComponent<RectTransform>();
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.one;
				component.offsetMin = Vector2.zero;
				component.offsetMax = Vector2.zero;
				TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>();
				((TMP_Text)obj).font = FontHelper.GetChineseCapable();
				((TMP_Text)obj).fontSize = fontSize;
				((TMP_Text)obj).fontStyle = (FontStyles)0;
				((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
				((Graphic)obj).raycastTarget = false;
				((TMP_Text)obj).textWrappingMode = (TextWrappingModes)0;
				TmpOutlineHelper.Apply((TMP_Text)(object)obj, 0.08f, new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue));
				((TMP_Text)obj).text = string.Empty;
				((TMP_Text)obj).transform.localScale = Vector3.one;
				return (TMP_Text)(object)obj;
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleWarn("local_bar_text", "LocalStaminaBarPatch.AddStretchText failed: " + ex.Message);
				return null;
			}
		}
	}
}
namespace PlayersInfo.MonoBehaviours
{
	internal sealed class TeammateBarAffliction : MonoBehaviour
	{
		public STATUSTYPE afflictionType;

		public bool isPetrify;

		public RectTransform rtf;

		public Image icon;

		public float size;

		public float width
		{
			get
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)rtf != (Object)null))
				{
					return 0f;
				}
				return rtf.sizeDelta.x;
			}
			set
			{
				//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_001b: 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)
				if (!((Object)(object)rtf == (Object)null))
				{
					Vector2 sizeDelta = rtf.sizeDelta;
					if (!(Mathf.Abs(sizeDelta.x - value) < 0.01f))
					{
						sizeDelta.x = value;
						rtf.sizeDelta = sizeDelta;
					}
				}
			}
		}

		public void Initialize(BarAffliction source, Transform ownershipRoot)
		{
			//IL_000c: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)source == (Object)null))
			{
				afflictionType = source.afflictionType;
				isPetrify = source.isPetrify;
				rtf = (((Object)(object)source.rtf != (Object)null) ? source.rtf : ((Component)this).GetComponent<RectTransform>());
				icon = (((Object)(object)source.icon != (Object)null && (Object)(object)ownershipRoot != (Object)null && ((Component)source.icon).transform.IsChildOf(ownershipRoot)) ? source.icon : null);
				size = 0f;
				width = 0f;
				if ((Object)(object)icon != (Object)null)
				{
					((Component)icon).transform.localScale = Vector3.one;
				}
				ApplyConfiguredIconVisibility();
			}
		}

		public void ResetVisual()
		{
			size = 0f;
			width = 0f;
			if (((Component)this).gameObject.activeSelf)
			{
				((Component)this).gameObject.SetActive(false);
			}
		}

		public void UpdateVisual(Character target, float fullWidth, float minWidth)
		{
			ApplyConfiguredIconVisibility();
			if ((Object)(object)target == (Object)null || ((object)target).Equals((object?)null) || (Object)(object)target.data == (Object)null)
			{
				ResetVisual();
				return;
			}
			float num = (isPetrify ? Mathf.Clamp01((float)target.data.petrifyAmount / 100f) : GetStatus(target));
			size = Mathf.Max(0f, fullWidth * num);
			if (num <= 0.01f)
			{
				if (((Component)this).gameObject.activeSelf)
				{
					((Component)this).gameObject.SetActive(false);
				}
				width = 0f;
				return;
			}
			size = Mathf.Max(size, minWidth);
			if (!((Component)this).gameObject.activeSelf)
			{
				((Component)this).gameObject.SetActive(true);
			}
			width = Mathf.Lerp(width, size, Mathf.Clamp01(Time.deltaTime * 10f));
		}

		public void SyncVisualImmediate(Character target, float fullWidth, float minWidth)
		{
			ApplyConfiguredIconVisibility();
			if ((Object)(object)target == (Object)null || ((object)target).Equals((object?)null) || (Object)(object)target.data == (Object)null)
			{
				ResetVisual();
				return;
			}
			float num = (isPetrify ? Mathf.Clamp01((float)target.data.petrifyAmount / 100f) : GetStatus(target));
			if (num <= 0.01f)
			{
				ResetVisual();
				return;
			}
			size = Mathf.Max(fullWidth * num, minWidth);
			width = size;
			if (!((Component)this).gameObject.activeSelf)
			{
				((Component)this).gameObject.SetActive(true);
			}
		}

		private float GetStatus(Character target)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (target.refs == null || (Object)(object)target.refs.afflictions == (Object)null)
				{
					return 0f;
				}
				return Mathf.Clamp01(target.refs.afflictions.GetCurrentStatus(afflictionType));
			}
			catch
			{
				return 0f;
			}
		}

		private void ApplyConfiguredIconVisibility()
		{
			if (!((Object)(object)icon == (Object)null))
			{
				bool flag = PlayersInfoPlugin.CfgAfflictionIconDisplayMode == null || PlayersInfoPlugin.CfgAfflictionIconDisplayMode.Value == PlayersInfoPlugin.AfflictionIconDisplayMode.ShowAll;
				if (((Behaviour)icon).enabled != flag)
				{
					((Behaviour)icon).enabled = flag;
				}
			}
		}
	}
	internal class TeammateBarDriver : MonoBehaviour
	{
		public Character Target;

		public Image backing;

		public RectTransform fullBar;

		public RectTransform staminaBar;

		public Image staminaGlow;

		public Image extraStaminaGlow;

		public RectTransform maxStaminaBar;

		public RectTransform staminaBarOutline;

		public RectTransform staminaBarOutlineOverflowBar;

		public RectTransform extraBar;

		public RectTransform extraBarStamina;

		public RectTransform extraBarOutline;

		public Vector2 extraBarInitialSize = new Vector2(45f, 45f);

		public float staminaBarOffset;

		public float minStaminaBarWidth = 20f;

		public GameObject shield;

		public GameObject campfire;

		public Color defaultBackingColor;

		public Color outOfStaminaBackingColor;

		public TMP_Text nameLabel;

		public TMP_Text staminaValueText;

		public TMP_Text extraValueText;

		public TeammateBarAffliction[] afflictions;

		public TMP_Text[] afflictionTexts;

		public float minAfflictionWidth = 15f;

		public TeammateInventoryRow InventoryRow;

		private float desiredStaminaSize;

		private float desiredMaxStaminaSize;

		private float desiredExtraStaminaSize;

		private float cachedExtraStam;

		private float sinTime;

		private float TAU = (float)Math.PI * 2f;

		private bool outOfStamina;

		private bool _wasInfiniteStamina;

		private bool _hasReliableMainStamina;

		private float _lastReliableMainStamina01;

		private float _frozenInfiniteStamina01;

		private float _displayedMainStamina01;

		private float _nextExtraValLogTime;

		private int _lastStaminaShownInt = int.MinValue;

		private int _lastStaminaShownTenth = int.MinValue;

		private bool _lastStaminaWasFloat;

		private int _lastExtraShownInt = int.MinValue;

		private int _lastExtraCapShownInt = int.MinValue;

		private bool _lastExtraShownWithCap = true;

		private float _nextValueRefreshTime;

		private const float ValueRefreshInterval = 0.25f;

		private float _nextAfflictionTextRefreshTime;

		private const float AfflictionTextRefreshInterval = 0.5f;

		private float _nextIdentityRefreshTime;

		private float _nextDiagnosticLogTime;

		private bool _cachedInvincible;

		private float _nextInvincibleProbeTime;

		private bool _lastShieldActive;

		private bool _lastCampfireActive;

		private bool _hasShieldState;

		private bool _hasCampfireState;

		private static FieldInfo _fiIsInvincible;

		private static bool _fiResolved;

		private void OnEnable()
		{
			SyncTargetVisualsImmediate();
		}

		public void BindTarget(Character c)
		{
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			Target = c;
			desiredStaminaSize = 0f;
			desiredMaxStaminaSize = 0f;
			desiredExtraStaminaSize = 0f;
			cachedExtraStam = 0f;
			outOfStamina = false;
			ResetInfiniteStaminaDisplay();
			_cachedInvincible = false;
			_nextInvincibleProbeTime = 0f;
			_hasShieldState = false;
			_hasCampfireState = false;
			_lastStaminaShownInt = int.MinValue;
			_lastStaminaShownTenth = int.MinValue;
			_lastStaminaWasFloat = false;
			_lastExtraShownInt = int.MinValue;
			_lastExtraCapShownInt = int.MinValue;
			_lastExtraShownWithCap = true;
			_nextValueRefreshTime = 0f;
			_nextAfflictionTextRefreshTime = 0f;
			_nextIdentityRefreshTime = 0f;
			try
			{
				if ((Object)(object)extraBar != (Object)null)
				{
					ShortcutExtensions.DOKill((Component)(object)extraBar, false);
					extraBar.sizeDelta = Vector2.zero;
					((Component)extraBar).gameObject.SetActive(false);
				}
				if ((Object)(object)extraBarStamina != (Object)null)
				{
					ShortcutExtensions.DOKill((Component)(object)extraBarStamina, false);
					extraBarStamina.sizeDelta = new Vector2(6f, extraBarStamina.sizeDelta.y);
				}
				if ((Object)(object)extraBarOutline != (Object)null)
				{
					ShortcutExtensions.DOKill((Component)(object)extraBarOutline, false);
					extraBarOutline.sizeDelta = new Vector2(20f, extraBarOutline.sizeDelta.y);
				}
				cachedExtraStam = 0f;
				desiredExtraStaminaSize = 0f;
			}
			catch
			{
			}
			if (afflictions != null)
			{
				for (int i = 0; i < afflictions.Length; i++)
				{
					TeammateBarAffliction teammateBarAffliction = afflictions[i];
					if (!((Object)(object)teammateBarAffliction == (Object)null))
					{
						teammateBarAffliction.ResetVisual();
					}
				}
			}
			SyncTargetVisualsImmediate();
			if ((Object)(object)nameLabel != (Object)null && (Object)(object)c != (Object)null)
			{
				nameLabel.text = SafeGetName(c);
				if (c.refs != null && (Object)(object)c.refs.customization != (Object)null)
				{
					((Graphic)nameLabel).color = c.refs.customization.PlayerColor;
				}
			}
			if ((Object)(object)staminaValueText != (Object)null)
			{
				staminaValueText.text = string.Empty;
				if (((Component)staminaValueText).gameObject.activeSelf)
				{
					((Component)staminaValueText).gameObject.SetActive(false);
				}
			}
			if ((Object)(object)extraValueText != (Object)null)
			{
				extraValueText.text = string.Empty;
				if (((Component)extraValueText).gameObject.activeSelf)
				{
					((Component)extraValueText).gameObject.SetActive(false);
				}
			}
			if (afflictionTexts != null)
			{
				for (int j = 0; j < afflictionTexts.Length; j++)
				{
					TMP_Text val = afflictionTexts[j];
					if (!((Object)(object)val == (Object)null))
					{
						val.text = string.Empty;
						if (((Component)val).gameObject.activeSelf)
						{
							((Component)val).gameObject.SetActive(false);
						}
					}
				}
			}
			_nextDiagnosticLogTime = 0f;
			PluginLogger.Debug("[PI-DIAG][Bind] driver=" + ((Object)this).GetInstanceID() + " target=" + SafeGetName(c) + " rootSelf=" + ((Component)this).gameObject.activeSelf + " rootHierarchy=" + ((Component)this).gameObject.activeInHierarchy + " afflictions=" + ((afflictions != null) ? afflictions.Length : (-1)) + " texts=" + ((afflictionTexts != null) ? afflictionTexts.Length : (-1)));
		}

		private void Update()
		{
			try
			{
				DoUpdate();
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleError("bar_driver", "TeammateBarDriver Update failed: " + ex.Message);
			}
		}

		private void DoUpdate()
		{
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_047a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: 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)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: 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_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_079c: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_07fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0800: Unknown result type (might be due to invalid IL or missing references)
			//IL_082e: 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_01f5: 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_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0849: Unknown result type (might be due to invalid IL or missing references)
			//IL_084e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0856: Unknown result type (might be due to invalid IL or missing references)
			//IL_08b1: 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_08e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_063a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0671: Unknown result type (might be due to invalid IL or missing references)
			//IL_068c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Target == (Object)null || ((object)Target).Equals((object?)null) || (Object)(object)Target.data == (Object)null)
			{
				PluginLogger.ThrottleDebug("pi_diag_target_" + ((Object)this).GetInstanceID(), "[PI-DIAG][DriverSkip] driver=" + ((Object)this).GetInstanceID() + " reason=invalid-target", 2f);
				return;
			}
			if ((Object)(object)fullBar == (Object)null || (Object)(object)staminaBar == (Object)null)
			{
				PluginLogger.ThrottleDebug("pi_diag_bar_refs_" + ((Object)this).GetInstanceID(), "[PI-DIAG][DriverSkip] driver=" + ((Object)this).GetInstanceID() + " target=" + SafeGetName(Target) + " reason=missing-bar fullBar=" + ((Object)(object)fullBar != (Object)null) + " staminaBar=" + ((Object)(object)staminaBar != (Object)null), 2f);
				return;
			}
			if (Target.data.dead)
			{
				if (((Component)this).gameObject.activeSelf)
				{
					((Component)this).gameObject.SetActive(false);
				}
				return;
			}
			if ((Object)(object)nameLabel != (Object)null && Time.unscaledTime >= _nextIdentityRefreshTime)
			{
				_nextIdentityRefreshTime = Time.unscaledTime + 0.5f;
				string text = SafeGetName(Target);
				if (nameLabel.text != text)
				{
					nameLabel.text = text;
				}
				if (Target.refs != null && (Object)(object)Target.refs.customization != (Object)null)
				{
					Color playerColor = Target.refs.customization.PlayerColor;
					if (((Graphic)nameLabel).color != playerColor)
					{
						((Graphic)nameLabel).color = playerColor;
					}
				}
			}
			float x = fullBar.sizeDelta.x;
			float num;
			try
			{
				num = Mathf.Max(0f, Target.GetMaxStamina());
			}
			catch
			{
				num = 1f;
			}
			_displayedMainStamina01 = ResolveDisplayedMainStamina(Target.data.currentStamina, num, HasInfiniteStaminaEffect(Target));
			desiredStaminaSize = Mathf.Max(0f, _displayedMainStamina01 * x + staminaBarOffset);
			if (Target.data.currentStamina <= 0.005f)
			{
				if (!outOfStamina)
				{
					outOfStamina = true;
					OutOfStaminaPulse();
				}
			}
			else
			{
				outOfStamina = false;
			}
			float num2 = Time.deltaTime * 10f;
			Vector2 sizeDelta = staminaBar.sizeDelta;
			sizeDelta.x = Mathf.Lerp(sizeDelta.x, desiredStaminaSize, num2);
			staminaBar.sizeDelta = sizeDelta;
			if ((Object)(object)staminaGlow != (Object)null)
			{
				Color color = ((Graphic)staminaGlow).color;
				float num3 = Mathf.Clamp01((staminaBar.sizeDelta.x - desiredStaminaSize) * 0.5f);
				sinTime += num2 * num3;
				color.a = num3 * 0.4f - Mathf.Abs(Mathf.Sin(sinTime)) * 0.2f;
				((Graphic)staminaGlow).color = color;
			}
			desiredMaxStaminaSize = Mathf.Max(0f, num * x + staminaBarOffset);
			if ((Object)(object)maxStaminaBar != (Object)null)
			{
				Vector2 sizeDelta2 = maxStaminaBar.sizeDelta;
				sizeDelta2.x = Mathf.Lerp(sizeDelta2.x, desiredMaxStaminaSize, num2);
				maxStaminaBar.sizeDelta = sizeDelta2;
				SetActiveIfChanged(((Component)maxStaminaBar).gameObject, sizeDelta2.x > minStaminaBarWidth);
			}
			float num4 = 1f;
			try
			{
				if (Target.refs != null && (Object)(object)Target.refs.afflictions != (Object)null)
				{
					num4 = Target.refs.afflictions.statusSum;
				}
			}
			catch
			{
			}
			if ((Object)(object)staminaBarOutline != (Object)null)
			{
				Vector2 sizeDelta3 = staminaBarOutline.sizeDelta;
				float num5 = 14f + Mathf.Max(1f, num4) * x;
				if (Mathf.Abs(sizeDelta3.x - num5) > 0.01f)
				{
					sizeDelta3.x = num5;
					staminaBarOutline.sizeDelta = sizeDelta3;
				}
			}
			if ((Object)(object)staminaBarOutlineOverflowBar != (Object)null)
			{
				SetActiveIfChanged(((Component)staminaBarOutlineOverflowBar).gameObject, (double)num4 > 1.005);
			}
			SetActiveIfChanged(((Component)staminaBar).gameObject, staminaBar.sizeDelta.x > minStaminaBarWidth);
			if (afflictions != null && (Object)(object)Target.data != (Object)null)
			{
				CharacterAfflictions ca = null;
				try
				{
					ca = ((Target.refs != null) ? Target.refs.afflictions : null);
				}
				catch
				{
				}
				bool flag = Time.unscaledTime >= _nextAfflictionTextRefreshTime;
				if (flag)
				{
					_nextAfflictionTextRefreshTime = Time.unscaledTime + 0.5f;
				}
				for (int i = 0; i < afflictions.Length; i++)
				{
					TeammateBarAffliction teammateBarAffliction = afflictions[i];
					if ((Object)(object)teammateBarAffliction == (Object)null)
					{
						continue;
					}
					teammateBarAffliction.UpdateVisual(Target, x, minAfflictionWidth);
					float value = AfflictionValueHelper.GetValue(Target, teammateBarAffliction.afflictionType, teammateBarAffliction.isPetrify);
					if (!flag || afflictionTexts == null || i >= afflictionTexts.Length)
					{
						continue;
					}
					TMP_Text val = afflictionTexts[i];
					if (!((Object)(object)val != (Object)null))
					{
						continue;
					}
					if (value > 0.01f && teammateBarAffliction.width > 18f)
					{
						string text2 = Mathf.Clamp(Mathf.RoundToInt(value * 100f), 0, 999).ToString();
						string text3 = AfflictionTimeHelper.FormatTime(AfflictionTimeHelper.GetReductionTimeRemaining(ca, teammateBarAffliction.afflictionType));
						string text4 = (string.IsNullOrEmpty(text3) ? text2 : (text2 + "(" + text3 + ")"));
						if (val.GetPreferredValues(text4).x > teammateBarAffliction.width)
						{
							text4 = text2;
						}
						if (val.GetPreferredValues(text4).x <= teammateBarAffliction.width)
						{
							if (val.text != text4)
							{
								val.text = text4;
							}
							if (!((Component)val).gameObject.activeSelf)
							{
								((Component)val).gameObject.SetActive(true);
							}
						}
						else if (((Component)val).gameObject.activeSelf)
						{
							((Component)val).gameObject.SetActive(false);
						}
					}
					else if (((Component)val).gameObject.activeSelf)
					{
						((Component)val).gameObject.SetActive(false);
					}
				}
			}
			float num6 = (((Object)(object)Target.data != (Object)null) ? Target.data.extraStamina : 0f);
			bool flag2 = num6 > 0.001f;
			if ((Object)(object)extraBar != (Object)null)
			{
				if (flag2)
				{
					if (!((Component)extraBar).gameObject.activeSelf)
					{
						ShortcutExtensions.DOKill((Component)(object)extraBar, false);
						extraBar.sizeDelta = extraBarInitialSize;
						((Component)extraBar).gameObject.SetActive(true);
					}
					desiredExtraStaminaSize = Mathf.Max(0f, num6 * x);
					cachedExtraStam = Mathf.Lerp(cachedExtraStam, desiredExtraStaminaSize, num2);
					if ((Object)(object)extraBarOutline != (Object)null)
					{
						Vector2 sizeDelta4 = extraBarOutline.sizeDelta;
						sizeDelta4.x = Mathf.Lerp(sizeDelta4.x, Mathf.Max(20f, desiredExtraStaminaSize + 12f), num2);
						extraBarOutline.sizeDelta = sizeDelta4;
					}
					if ((Object)(object)extraStaminaGlow != (Object)null)
					{
						Color color2 = ((Graphic)extraStaminaGlow).color;
						float num7 = Mathf.Clamp01((extraBar.sizeDelta.x - desiredExtraStaminaSize) * 0.5f);
						sinTime += num2 * num7;
						color2.a = num7 * 0.4f - Mathf.Abs(Mathf.Sin(sinTime)) * 0.2f;
						((Graphic)extraStaminaGlow).color = color2;
					}
					if ((Object)(object)extraBarStamina != (Object)null)
					{
						extraBarStamina.sizeDelta = new Vector2(Mathf.Max(6f, cachedExtraStam), extraBarStamina.sizeDelta.y);
					}
				}
				else
				{
					if (((Component)extraBar).gameObject.activeSelf)
					{
						ShortcutExtensions.DOKill((Component)(object)extraBar, false);
						((Component)extraBar).gameObject.SetActive(false);
					}
					cachedExtraStam = 0f;
					desiredExtraStaminaSize = 0f;
				}
			}
			if ((Object)(object)shield != (Object)null)
			{
				if (Time.unscaledTime >= _nextInvincibleProbeTime)
				{
					_nextInvincibleProbeTime = Time.unscaledTime + 0.25f;
					try
					{
						_cachedInvincible = GetIsInvincible(Target.data);
					}
					catch
					{
						_cachedInvincible = false;
					}
				}
				if (!_hasShieldState || _lastShieldActive != _cachedInvincible)
				{
					try
					{
						shield.SetActive(_cachedInvincible);
					}
					catch
					{
					}
					_lastShieldActive = _cachedInvincible;
					_hasShieldState = true;
				}
			}
			if ((Object)(object)campfire != (Object)null)
			{
				try
				{
					bool flag3 = Target.refs != null && (Object)(object)Target.refs.afflictions != (Object)null && !Target.refs.afflictions.canGetHungry;
					if (!_hasCampfireState || _lastCampfireActive != flag3)
					{
						campfire.SetActive(flag3);
						_lastCampfireActive = flag3;
						_hasCampfireState = true;
					}
				}
				catch
				{
				}
			}
			if (sinTime > TAU)
			{
				sinTime -= TAU;
			}
			if (Time.unscaledTime >= _nextValueRefreshTime)
			{
				_nextValueRefreshTime = Time.unscaledTime + 0.25f;
				UpdateValueTexts();
			}
			if (Time.unscaledTime >= _nextDiagnosticLogTime)
			{
				_nextDiagnosticLogTime = Time.unscaledTime + 2f;
				LogRuntimeDiagnostics(x, num4);
			}
		}

		private void LogRuntimeDiagnostics(float fullWidth, float statusSum)
		{
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_033c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				CharacterAfflictions val = null;
				try
				{
					val = (((Object)(object)Target != (Object)null && Target.refs != null) ? Target.refs.afflictions : null);
				}
				catch
				{
				}
				StringBuilder stringBuilder = new StringBuilder(1536);
				stringBuilder.Append("[PI-DIAG][DriverState] driver=").Append(((Object)this).GetInstanceID()).Append(" target=")
					.Append(SafeGetName(Target))
					.Append(" rootSelf=")
					.Append(((Component)this).gameObject.activeSelf)
					.Append(" rootHierarchy=")
					.Append(((Component)this).gameObject.activeInHierarchy)
					.Append(" enabled=")
					.Append(((Behaviour)this).enabled)
					.Append(" dead=")
					.Append((Object)(object)Target != (Object)null && (Object)(object)Target.data != (Object)null && Target.data.dead)
					.Append(" refsAff=")
					.Append((Object)(object)val != (Object)null)
					.Append(" statusArray=")
					.Append(((Object)(object)val != (Object)null && val.currentStatuses != null) ? val.currentStatuses.Length : (-1))
					.Append(" statusSum=")
					.Append(statusSum.ToString("F3"))
					.Append(" currentStamina=")
					.Append(((Object)(object)Target != (Object)null && (Object)(object)Target.data != (Object)null) ? Target.data.currentStamina.ToString("F3") : "null")
					.Append(" fullWidth=")
					.Append(fullWidth.ToString("F1"))
					.Append(" staminaWidth=")
					.Append(((Object)(object)staminaBar != (Object)null) ? staminaBar.sizeDelta.x.ToString("F1") : "null")
					.Append(" staminaSelf=")
					.Append((Object)(object)staminaBar != (Object)null && ((Component)staminaBar).gameObject.activeSelf)
					.Append(" staminaHierarchy=")
					.Append((Object)(object)staminaBar != (Object)null && ((Component)staminaBar).gameObject.activeInHierarchy)
					.Append(" staminaText=")
					.Append(DescribeText(staminaValueText))
					.Append(" affCount=")
					.Append((afflictions != null) ? afflictions.Length : (-1))
					.Append(" textCount=")
					.Append((afflictionTexts != null) ? afflictionTexts.Length : (-1));
				if (afflictions != null)
				{
					for (int i = 0; i < afflictions.Length; i++)
					{
						TeammateBarAffliction teammateBarAffliction = afflictions[i];
						stringBuilder.Append(" | aff[").Append(i).Append("]=");
						if ((Object)(object)teammateBarAffliction == (Object)null)
						{
							stringBuilder.Append("null");
							continue;
						}
						float value = AfflictionValueHelper.GetValue(Target, teammateBarAffliction.afflictionType, teammateBarAffliction.isPetrify);
						stringBuilder.Append(teammateBarAffliction.afflictionType).Append(':').Append(value.ToString("F3"))
							.Append(" width=")
							.Append(teammateBarAffliction.width.ToString("F1"))
							.Append(" size=")
							.Append(teammateBarAffliction.size.ToString("F1"))
							.Append(" self=")
							.Append(((Component)teammateBarAffliction).gameObject.activeSelf)
							.Append(" hierarchy=")
							.Append(((Component)teammateBarAffliction).gameObject.activeInHierarchy)
							.Append(" rtf=")
							.Append((Object)(object)teammateBarAffliction.rtf != (Object)null)
							.Append(" text=")
							.Append((afflictionTexts != null && i < afflictionTexts.Length) ? DescribeText(afflictionTexts[i]) : "<missing>");
					}
				}
				PluginLogger.Debug(stringBuilder.ToString());
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleWarn("pi_diag_driver_" + ((Object)this).GetInstanceID(), "[PI-DIAG][DriverState] failed for driver=" + ((Object)this).GetInstanceID() + ": " + ex, 2f);
			}
		}

		private static string DescribeText(TMP_Text text)
		{
			if ((Object)(object)text == (Object)null)
			{
				return "<null>";
			}
			string text2;
			try
			{
				text2 = (string.IsNullOrEmpty(text.text) ? "<empty>" : text.text);
			}
			catch
			{
				text2 = "<invalid>";
			}
			try
			{
				return text2 + ",self=" + ((Component)text).gameObject.activeSelf + ",hierarchy=" + ((Component)text).gameObject.activeInHierarchy + ",enabled=" + ((Behaviour)text).enabled + ",font=" + (((Object)(object)text.font != (Object)null) ? ((Object)text.font).name : "null") + ",size=" + text.fontSize.ToString("F1");
			}
			catch
			{
				return text2 + ",state=<invalid>";
			}
		}

		private void HideValueTexts()
		{
			if ((Object)(object)staminaValueText != (Object)null)
			{
				if (staminaValueText.text != string.Empty)
				{
					staminaValueText.text = string.Empty;
				}
				if (((Component)staminaValueText).gameObject.activeSelf)
				{
					((Component)staminaValueText).gameObject.SetActive(false);
				}
			}
			if ((Object)(object)extraValueText != (Object)null)
			{
				if (extraValueText.text != string.Empty)
				{
					extraValueText.text = string.Empty;
				}
				if (((Component)extraValueText).gameObject.activeSelf)
				{
					((Component)extraValueText).gameObject.SetActive(false);
				}
			}
			if (afflictionTexts == null)
			{
				return;
			}
			for (int i = 0; i < afflictionTexts.Length; i++)
			{
				TMP_Text val = afflictionTexts[i];
				if (!((Object)(object)val == (Object)null))
				{
					if (val.text != string.Empty)
					{
						val.text = string.Empty;
					}
					if (((Component)val).gameObject.activeSelf)
					{
						((Component)val).gameObject.SetActive(false);
					}
				}
			}
		}

		private static void SetWidthImmediate(RectTransform rect, float width)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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)
			if (!((Object)(object)rect == (Object)null))
			{
				Vector2 sizeDelta = rect.sizeDelta;
				if (!(Mathf.Abs(sizeDelta.x - width) < 0.01f))
				{
					sizeDelta.x = Mathf.Max(0f, width);
					rect.sizeDelta = sizeDelta;
				}
			}
		}

		private void SyncTargetVisualsImmediate()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)Target == (Object)null || ((object)Target).Equals((object?)null) || (Object)(object)Target.data == (Object)null || (Object)(object)fullBar == (Object)null)
				{
					return;
				}
				float x = fullBar.sizeDelta.x;
				float num = Mathf.Max(0f, Target.GetMaxStamina());
				if (Target.data.dead)
				{
					ResetInfiniteStaminaDisplay();
					_displayedMainStamina01 = 0f;
				}
				else
				{
					_displayedMainStamina01 = ResolveDisplayedMainStamina(Target.data.currentStamina, num, HasInfiniteStaminaEffect(Target));
				}
				desiredStaminaSize = Mathf.Max(0f, _displayedMainStamina01 * x + staminaBarOffset);
				desiredMaxStaminaSize = Mathf.Max(0f, num * x + staminaBarOffset);
				desiredExtraStaminaSize = Mathf.Max(0f, Target.data.extraStamina * x);
				cachedExtraStam = desiredExtraStaminaSize;
				SetWidthImmediate(staminaBar, desiredStaminaSize);
				SetWidthImmediate(maxStaminaBar, desiredMaxStaminaSize);
				if (afflictions != null)
				{
					for (int i = 0; i < afflictions.Length; i++)
					{
						if ((Object)(object)afflictions[i] != (Object)null)
						{
							afflictions[i].SyncVisualImmediate(Target, x, minAfflictionWidth);
						}
					}
				}
				if (!((Object)(object)staminaBarOutline != (Object)null))
				{
					return;
				}
				float num2 = 1f;
				try
				{
					if (Target.refs != null && (Object)(object)Target.refs.afflictions != (Object)null)
					{
						num2 = Target.refs.afflictions.statusSum;
					}
				}
				catch
				{
				}
				SetWidthImmediate(staminaBarOutline, 14f + Mathf.Max(1f, num2) * x);
			}
			catch
			{
			}
		}

		private float ResolveDisplayedMainStamina(float rawStamina, float maxStamina, bool infiniteStamina)
		{
			float num = Mathf.Clamp(rawStamina, 0f, maxStamina);
			if (infiniteStamina)
			{
				if (!_wasInfiniteStamina)
				{
					_frozenInfiniteStamina01 = (_hasReliableMainStamina ? _lastReliableMainStamina01 : num);
					PluginLogger.Debug("[InfiniteStam] mate=" + SafeGetName(Target) + " start raw=" + rawStamina.ToString("F3") + " max=" + maxStamina.ToString("F3") + " frozen=" + _frozenInfiniteStamina01.ToString("F3") + " cached=" + _hasReliableMainStamina);
				}
				_wasInfiniteStamina = true;
				return _frozenInfiniteStamina01;
			}
			if (_wasInfiniteStamina)
			{
				PluginLogger.Debug("[InfiniteStam] mate=" + SafeGetName(Target) + " end raw=" + rawStamina.ToString("F3"));
			}
			_wasInfiniteStamina = false;
			_frozenInfiniteStamina01 = 0f;
			_lastReliableMainStamina01 = num;
			_hasReliableMainStamina = true;
			return num;
		}

		private void ResetInfiniteStaminaDisplay()
		{
			_wasInfiniteStamina = false;
			_hasReliableMainStamina = false;
			_lastReliableMainStamina01 = 0f;
			_frozenInfiniteStamina01 = 0f;
			_displayedMainStamina01 = 0f;
		}

		private static bool HasInfiniteStaminaEffect(Character target)
		{
			try
			{
				if ((Object)(object)target == (Object)null || ((object)target).Equals((object?)null))
				{
					return false;
				}
				if (target.infiniteStam)
				{
					return true;
				}
				if (target.refs == null || (Object)(object)target.refs.afflictions == (Object)null)
				{
					return false;
				}
				Affliction val = default(Affliction);
				return target.refs.afflictions.HasAfflictionType((AfflictionType)1, ref val);
			}
			catch
			{
				return false;
			}
		}

		private static void SetActiveIfChanged(GameObject target, bool active)
		{
			if ((Object)(object)target != (Object)null && target.activeSelf != active)
			{
				target.SetActive(active);
			}
		}

		private void UpdateValueTexts()
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: 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_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Target == (Object)null || (Object)(object)Target.data == (Object)null)
			{
				return;
			}
			bool flag = true;
			try
			{
				flag = PlayersInfoPlugin.CfgRoundStamina == null || PlayersInfoPlugin.CfgRoundStamina.Value;
			}
			catch
			{
			}
			float num = _displayedMainStamina01 * 100f;
			float num2 = Target.data.extraStamina * 100f;
			float num3 = ExtraStaminaValueHelper.GetCap01(Target) * 100f;
			bool flag2 = true;
			try
			{
				flag2 = PlayersInfoPlugin.CfgShowExtraStaminaCap == null || PlayersInfoPlugin.CfgShowExtraStaminaCap.Value;
			}
			catch
			{
			}
			if ((Object)(object)staminaValueText != (Object)null)
			{
				float num4 = (((Object)(object)fullBar != (Object)null) ? fullBar.sizeDelta.x : 0f);
				if (num4 < 15f)
				{
					if (((Component)staminaValueText).gameObject.activeSelf)
					{
						((Component)staminaValueText).gameObject.SetActive(false);
					}
				}
				else
				{
					if (!flag && !(num4 < 30f))
					{
						int num5 = Mathf.RoundToInt(num * 10f);
						if (num5 != _lastStaminaShownTenth || !_lastStaminaWasFloat)
						{
							staminaValueText.text = ((float)num5 / 10f).ToString("F1");
							_lastStaminaShownTenth = num5;
							_lastStaminaWasFloat = true;
						}
					}
					else
					{
						int num6 = Mathf.RoundToInt(num);
						if (num6 != _lastStaminaShownInt || _lastStaminaWasFloat)
						{
							staminaValueText.text = num6.ToString();
							_lastStaminaShownInt = num6;
							_lastStaminaWasFloat = false;
						}
					}
					if (!((Component)staminaValueText).gameObject.activeSelf)
					{
						((Component)staminaValueText).gameObject.SetActive(true);
					}
				}
			}
			if (!((Object)(object)extraValueText != (Object)null))
			{
				return;
			}
			int num7 = Mathf.Clamp(Mathf.RoundToInt(num2), 0, 100);
			int num8 = Mathf.Clamp(Mathf.RoundToInt(num3), 0, 100);
			if (num7 != _lastExtraShownInt || num8 != _lastExtraCapShownInt || flag2 != _lastExtraShownWithCap)
			{
				extraValueText.text = (flag2 ? (num7 + "/" + num8) : num7.ToString());
				_lastExtraShownInt = num7;
				_lastExtraCapShownInt = num8;
				_lastExtraShownWithCap = flag2;
				float num9 = extraValueText.GetPreferredValues(extraValueText.text).x + 6f;
				Vector2 sizeDelta = extraValueText.rectTransform.sizeDelta;
				if (Mathf.Abs(sizeDelta.x - num9) > 0.1f)
				{
					sizeDelta.x = num9;
					extraValueText.rectTransform.sizeDelta = sizeDelta;
				}
			}
			if (!((Component)extraValueText).gameObject.activeSelf)
			{
				((Component)extraValueText).gameObject.SetActive(true);
			}
			if (!PluginLogger.DebugEnabled || !(Time.unscaledTime >= _nextExtraValLogTime))
			{
				return;
			}
			_nextExtraValLogTime = Time.unscaledTime + 3f;
			try
			{
				float currentStamina = Target.data.currentStamina;
				float extraStamina = Target.data.extraStamina;
				string text = SafeGetName(Target);
				PluginLogger.Debug("[ExtraVal] mate=" + text + " rawExtra=" + extraStamina.ToString("F4") + " shown=" + extraValueText.text + " rawMain=" + currentStamina.ToString("F4"));
			}
			catch
			{
			}
		}

		private void OutOfStaminaPulse()
		{
			//IL_0017: 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)
			if ((Object)(object)backing == (Object)null)
			{
				return;
			}
			try
			{
				((Graphic)backing).color = outOfStaminaBackingColor;
				DOTweenModuleUI.DOColor(backing, defaultBackingColor, 0.5f);
			}
			catch
			{
			}
		}

		private static bool GetIsInvincible(CharacterData data)
		{
			if ((Object)(object)data == (Object)null)
			{
				return false;
			}
			if (!_fiResolved)
			{
				_fiResolved = true;
				try
				{
					_fiIsInvincible = typeof(CharacterData).GetField("isInvincible", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				catch
				{
				}
			}
			if (_fiIsInvincible == null)
			{
				return false;
			}
			try
			{
				return (bool)_fiIsInvincible.GetValue(data);
			}
			catch
			{
				return false;
			}
		}

		private static string SafeGetName(Character c)
		{
			if ((Object)(object)c == (Object)null)
			{
				return string.Empty;
			}
			try
			{
				if ((Object)(object)((MonoBehaviourPun)c).photonView != (Object)null && ((MonoBehaviourPun)c).photonView.Owner != null)
				{
					string nickName = ((MonoBehaviourPun)c).photonView.Owner.NickName;
					if (!string.IsNullOrEmpty(nickName))
					{
						return nickName;
					}
				}
			}
			catch
			{
			}
			try
			{
				return string.IsNullOrEmpty(c.characterName) ? ((Object)c).name : c.characterName;
			}
			catch
			{
				return "Player";
			}
		}
	}
	internal class TeammateBarsCoordinator : MonoBehaviour
	{
		private struct RetainedEntry
		{
			public Character ch;

			public float lostTime;
		}

		private readonly List<TeammateBarDriver> _pool = new List<TeammateBarDriver>();

		private readonly Dictionary<int, TeammateBarDriver> _driversByStableId = new Dictionary<int, TeammateBarDriver>();

		private readonly Dictionary<TeammateBarDriver, int> _stableIdByDriver = new Dictionary<TeammateBarDriver, int>();

		private readonly List<int> _driverCleanupScratch = new List<int>();

		private StaminaBar _origBar;

		private bool _layoutInitialized;

		private float _nextRefreshTime;

		private const float RefreshInterval = 0.25f;

		private float _nextDistLogTime;

		private float _nextDiagnosticLogTime;

		private const float ReorderDelay = 0.75f;

		private static readonly List<KeyValuePair<float, Character>> _scratch = new List<KeyValuePair<float, Character>>();

		private static readonly List<Character> s_visibleScratch = new List<Character>();

		private static readonly Dictionary<int, Character> s_visibleById = new Dictionary<int, Character>();

		private static readonly HashSet<int> s_seenStableIds = new HashSet<int>();

		private const float HysteresisMargin = 5f;

		private static readonly HashSet<int> s_displayOrderSet = new HashSet<int>();

		private static readonly HashSet<int> s_currentStableIds = new HashSet<int>();

		private const float RetainOnLossDelay = 1.5f;

		private static readonly Dictionary<int, RetainedEntry> s_retainedById = new Dictionary<int, RetainedEntry>();

		private static readonly Dictionary<int, int> s_viewIdToActor = new Dictionary<int, int>();

		private readonly List<int> _displayOrder = new List<int>();

		private readonly List<int> _pendingOrder = new List<int>();

		private readonly List<int> _stableOrderScratch = new List<int>();

		private float _pendingOrderSince = -1f;

		private static readonly Comparison<KeyValuePair<float, Character>> s_distCmp = (KeyValuePair<float, Character> a, KeyValuePair<float, Character> b) => a.Key.CompareTo(b.Key);

		public static TeammateBarsCoordinator Instance { get; private set; }

		public static TeammateBarsCoordinator EnsureExists()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance != (Object)null)
			{
				return Instance;
			}
			Instance = new GameObject("PlayersInfo.BarsCoordinator").AddComponent<TeammateBarsCoordinator>();
			return Instance;
		}

		private void OnDestroy()
		{
			if ((Object)(object)TeamRosterTracker.Instance != (Object)null)
			{
				TeamRosterTracker.Instance.OnRosterChanged -= HandleRosterChanged;
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		public void Init()
		{
			try
			{
				if ((Object)(object)GUIManager.instance == (Object)null || (Object)(object)GUIManager.instance.bar == (Object)null)
				{
					PluginLogger.ThrottleWarn("bars_init", "GUIManager.instance.bar not ready, skip init.");
					return;
				}
				if (_origBar != GUIManager.instance.bar)
				{
					_origBar = GUIManager.instance.bar;
					_layoutInitialized = false;
				}
				FixBarGroupOnce();
			}
			catch (Exception ex)
			{
				PluginLogger.Error("BarsCoordinator.Init failed: " + ex.Message);
			}
		}

		private void FixBarGroupOnce()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_layoutInitialized)
				{
					return;
				}
				Transform parent = ((Component)_origBar).transform.parent;
				RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
				if (!((Object)(object)val == (Object)null))
				{
					val.sizeDelta = new Vector2(600f, 600f);
					ApplyConfiguredAnchor(val);
					VerticalLayoutGroup component = ((Component)val).GetComponent<VerticalLayoutGroup>();
					if ((Object)(object)component != (Object)null)
					{
						((HorizontalOrVerticalLayoutGroup)component).spacing = 25f;
					}
					_layoutInitialized = true;
				}
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleWarn("fix_bargroup", "FixBarGroup failed: " + ex.Message);
			}
		}

		private void ConfigureLocalExtraBar()
		{
			//IL_010b: 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_0135: 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)
			try
			{
				if (!((Object)(object)_origBar == (Object)null) && !((Object)(object)_origBar.extraBar == (Object)null) && !((Object)(object)_origBar.fullBar == (Object)null))
				{
					RectTransform extraBar = _origBar.extraBar;
					PluginLogger.Debug("[LocalExtraLayout] extraParent=" + GetParentName(extraBar) + " outlineParent=" + GetParentName(_origBar.extraBarOutline) + " staminaParent=" + GetParentName(_origBar.extraBarStamina) + " iconParent=" + (((Object)(object)_origBar.extraStaminaIcon != (Object)null) ? GetParentName(((Graphic)_origBar.extraStaminaIcon).rectTransform) : "null"));
					if ((Object)(object)((Transform)extraBar).parent != (Object)(object)_origBar.fullBar)
					{
						((Transform)extraBar).SetParent((Transform)(object)_origBar.fullBar, false);
					}
					extraBar.anchorMin = new Vector2(0f, 0f);
					extraBar.anchorMax = new Vector2(0f, 0f);
					extraBar.pivot = new Vector2(0f, 1f);
					extraBar.anchoredPosition = new Vector2(0f, -2f);
					ConfigureLocalExtraChild(_origBar.extraBarOutline, extraBar);
					ConfigureLocalExtraChild(_origBar.extraBarStamina, extraBar);
				}
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleWarn("local_extra_layout", "ConfigureLocalExtraBar failed: " + ex.Message);
			}
		}

		private static void ConfigureLocalExtraChild(RectTransform child, RectTransform parent)
		{
			//IL_0034: 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_005e: 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)
			if (!((Object)(object)child == (Object)null) && !((Object)(object)parent == (Object)null))
			{
				if ((Object)(object)((Transform)child).parent != (Object)(object)parent)
				{
					((Transform)child).SetParent((Transform)(object)parent, false);
				}
				child.anchorMin = new Vector2(0f, 0f);
				child.anchorMax = new Vector2(0f, 1f);
				child.pivot = new Vector2(0f, 0.5f);
				child.anchoredPosition = Vector2.zero;
			}
		}

		private static string GetParentName(RectTransform child)
		{
			if ((Object)(object)child == (Object)null)
			{
				return "null";
			}
			if (!((Object)(object)((Transform)child).parent != (Object)null))
			{
				return "<root>";
			}
			return ((Object)((Transform)child).parent).name;
		}

		private static void ApplyConfiguredAnchor(RectTransform rt)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00c7: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: 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)
			//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_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			PlayersInfoPlugin.HudAnchor hudAnchor = ((PlayersInfoPlugin.CfgAnchor != null) ? PlayersInfoPlugin.CfgAnchor.Value : PlayersInfoPlugin.HudAnchor.BottomLeft);
			float num = ((PlayersInfoPlugin.CfgOffsetX != null) ? PlayersInfoPlugin.CfgOffsetX.Value : 0f);
			float num2 = ((PlayersInfoPlugin.CfgOffsetY != null) ? PlayersInfoPlugin.CfgOffsetY.Value : 0f);
			Vector2 val = default(Vector2);
			switch (hudAnchor)
			{
			case PlayersInfoPlugin.HudAnchor.TopRight:
				((Vector2)(ref val))..ctor(1f, 1f);
				rt.anchorMax = val;
				rt.anchorMin = val;
				rt.pivot = new Vector2(1f, 1f);
				rt.anchoredPosition = new Vector2(-20f + num, -20f + num2);
				break;
			case PlayersInfoPlugin.HudAnchor.BottomLeft:
				((Vector2)(ref val))..ctor(0f, 0f);
				rt.anchorMax = val;
				rt.anchorMin = val;
				rt.pivot = new Vector2(0f, 0f);
				rt.anchoredPosition = new Vector2(20f + num, 20f + num2);
				break;
			case PlayersInfoPlugin.HudAnchor.BottomRight:
				((Vector2)(ref val))..ctor(1f, 0f);
				rt.anchorMax = val;
				rt.anchorMin = val;
				rt.pivot = new Vector2(1f, 0f);
				rt.anchoredPosition = new Vector2(-20f + num, 20f + num2);
				break;
			default:
				((Vector2)(ref val))..ctor(0f, 1f);
				rt.anchorMax = val;
				rt.anchorMin = val;
				rt.pivot = new Vector2(0f, 1f);
				rt.anchoredPosition = new Vector2(20f + num, -20f + num2);
				break;
			}
		}

		public void AttachToTracker(TeamRosterTracker tracker)
		{
			if (!((Object)(object)tracker == (Object)null))
			{
				tracker.OnRosterChanged -= HandleRosterChanged;
				tracker.OnRosterChanged += HandleRosterChanged;
				_nextRefreshTime = 0f;
			}
		}

		private void HandleRosterChanged()
		{
			_nextRefreshTime = 0f;
		}

		private void Update()
		{
			if (Time.unscaledTime < _nextRefreshTime)
			{
				return;
			}
			_nextRefreshTime = Time.unscaledTime + 0.25f;
			try
			{
				RefreshNearby();
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleError("bars_refresh", "RefreshNearby failed: " + ex.Message);
			}
		}

		private void RefreshNearby()
		{
			//IL_0232: 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)
			if ((Object)(object)_origBar == (Object)null)
			{
				Init();
				if ((Object)(object)_origBar == (Object)null)
				{
					return;
				}
			}
			if (PlayersInfoPlugin.CfgModEnabled == null || !PlayersInfoPlugin.CfgModEnabled.Value || (PlayersInfoPlugin.CfgEnableStaminaBar != null && !PlayersInfoPlugin.CfgEnableStaminaBar.Value))
			{
				HideAll();
				return;
			}
			FixBarGroupOnce();
			TeamRosterTracker instance = TeamRosterTracker.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			Character observedOrLocal = DisplayCharacterHelper.GetObservedOrLocal();
			if ((Object)(object)localCharacter == (Object)null || ((object)localCharacter).Equals((object?)null) || (Object)(object)observedOrLocal == (Object)null || ((object)observedOrLocal).Equals((object?)null))
			{
				HideAll();
				return;
			}
			bool num = (Object)(object)observedOrLocal != (Object)(object)localCharacter;
			bool flag = PlayersInfoPlugin.CfgSpectatorNearbyCenter != null && PlayersInfoPlugin.CfgSpectatorNearbyCenter.Value == PlayersInfoPlugin.SpectatorNearbyCenterMode.LocalCharacter;
			Character val = ((num && flag) ? localCharacter : observedOrLocal);
			int num2 = ((PlayersInfoPlugin.CfgMaxNearbyCount != null) ? PlayersInfoPlugin.CfgMaxNearbyCount.Value : 3);
			float num3 = ((PlayersInfoPlugin.CfgNearbyRange != null) ? PlayersInfoPlugin.CfgNearbyRange.Value : 30f);
			if (num2 <= 0)
			{
				HideAll();
				return;
			}
			_scratch.Clear();
			s_visibleScratch.Clear();
			s_visibleById.Clear();
			s_seenStableIds.Clear();
			s_displayOrderSet.Clear();
			for (int i = 0; i < _displayOrder.Count; i++)
			{
				s_displayOrderSet.Add(_displayOrder[i]);
			}
			IReadOnlyList<Character> teammates = instance.Teammates;
			if (!TryGetDistancePosition(val, out var position))
			{
				HideAll();
				return;
			}
			s_currentStableIds.Clear();
			for (int j = 0; j < teammates.Count; j++)
			{
				Character val2 = teammates[j];
				if ((Object)(object)val2 == (Object)null || ((object)val2).Equals((object?)null) || (Object)(object)val2.data == (Object)null || (Object)(object)((MonoBehaviourPun)val2).photonView == (Object)null)
				{
					continue;
				}
				int stableCharacterId = GetStableCharacterId(val2);
				if (stableCharacterId == int.MinValue)
				{
					continue;
				}
				s_currentStableIds.Add(stableCharacterId);
				if (val2.data.dead)
				{
					s_retainedById.Remove(stableCharacterId);
				}
				else
				{
					if (((Object)(object)val2 == (Object)(object)observedOrLocal && !flag) || !TryGetDistancePosition(val2, out var position2))
					{
						continue;
					}
					float num4 = Vector3.Distance(position, position2);
					if (num3 > 0f)
					{
						float num5 = (s_displayOrderSet.Contains(stableCharacterId) ? (num3 + 5f) : num3);
						if (num4 > num5)
						{
							continue;
						}
					}
					_scratch.Add(new KeyValuePair<float, Character>(num4, val2));
				}
			}
			_scratch.Sort(s_distCmp);
			for (int k = 0; k < _scratch.Count; k++)
			{
				if (s_visibleScratch.Count >= num2)
				{
					break;
				}
				Character value = _scratch[k].Value;
				int stableCharacterId2 = GetStableCharacterId(value);
				if (stableCharacterId2 != int.MinValue && s_seenStableIds.Add(stableCharacterId2))
				{
					s_visibleScratch.Add(value);
					s_visibleById[stableCharacterId2] = value;
					s_retainedById[stableCharacterId2] = new RetainedEntry
					{
						ch = value,
						lostTime = -1f
					};
				}
			}
			float unscaledTime = Time.unscaledTime;
			for (int l = 0; l < _displayOrder.Count; l++)
			{
				int num6 = _displayOrder[l];
				if (s_visibleById.TryGetValue(num6, out var value2))
				{
					s_retainedById[num6] = new RetainedEntry
					{
						ch = value2,
						lostTime = -1f
					};
					continue;
				}
				if (s_currentStableIds.Contains(num6))
				{
					s_retainedById.Remove(num6);
					continue;
				}
				if (s_visibleScratch.Count >= num2)
				{
					s_retainedById.Remove(num6);
					continue;
				}
				Character val3 = null;
				if (s_retainedById.TryGetValue(num6, out var value3))
				{
					if (value3.lostTime < 0f)
					{
						value3.lostTime = unscaledTime;
						s_retainedById[num6] = value3;
					}
					if (unscaledTime - value3.lostTime <= 1.5f && (Object)(object)value3.ch != (Object)null && !((object)value3.ch).Equals((object?)null))
					{
						val3 = value3.ch;
					}
					else
					{
						s_retainedById.Remove(num6);
					}
				}
				else
				{
					for (int m = 0; m < teammates.Count; m++)
					{
						Character val4 = teammates[m];
						if (!((Object)(object)val4 == (Object)null) && !((object)val4).Equals((object?)null) && !((Object)(object)((MonoBehaviourPun)val4).photonView == (Object)null) && GetStableCharacterId(val4) == num6)
						{
							val3 = val4;
							s_retainedById[num6] = new RetainedEntry
							{
								ch = val4,
								lostTime = unscaledTime
							};
							break;
						}
					}
				}
				if ((Object)(object)val3 != (Object)null)
				{
					s_visibleScratch.Add(val3);
					s_visibleById[num6] = val3;
				}
			}
			ResolveDisplayOrder(s_visibleScratch);
			s_displayOrderSet.Clear();
			for (int n = 0; n < _displayOrder.Count; n++)
			{
				s_displayOrderSet.Add(_displayOrder[n]);
			}
			EnsureDriversForDisplayOrder(s_visibleById);
			ApplyDriverSiblingOrder();
			if (PluginLogger.DebugEnabled && Time.unscaledTime >= _nextDistLogTime)
			{
				_nextDistLogTime = Time.unscaledTime + 2f;
				try
				{
					StringBuilder stringBuilder = new StringBuilder();
					stringBuilder.Append("[Dist] local->mates(").Append(_scratch.Count).Append(", range=")
						.Append(num3.ToString("F0"))
						.Append("): ");
					for (int num7 = 0; num7 < _scratch.Count; num7++)
					{
						if (num7 > 0)
						{
							stringBuilder.Append(", ");
						}
						KeyValuePair<float, Character> keyValuePair = _scratch[num7];
						string value4 = (((Object)(object)keyValuePair.Value != (Object)null) ? (keyValuePair.Value.characterName ?? ((Object)keyValuePair.Value).name) : "?");
						stringBuilder.Append(value4).Append("=").Append(keyValuePair.Key.ToString("F1"))
							.Append("m");
					}
					PluginLogger.Debug(stringBuilder.ToString());
				}
				catch
				{
				}
			}
			CleanupUntrackedDrivers();
			for (int num8 = 0; num8 < _pool.Count; num8++)
			{
				TeammateBarDriver teammateBarDriver = _pool[num8];
				if ((Object)(object)teammateBarDriver == (Object)null)
				{
					continue;
				}
				int driverStableId = GetDriverStableId(teammateBarDriver);
				if (driverStableId != int.MinValue && s_displayOrderSet.Contains(driverStableId) && s_visibleById.TryGetValue(driverStableId, out var value5) && (Object)(object)value5 != (Object)null)
				{
					if (!((Component)teammateBarDriver).gameObject.activeSelf)
					{
						((Component)teammateBarDriver).gameObject.SetActive(true);
					}
					if ((Object)(object)teammateBarDriver.Target != (Object)(object)value5)
					{
						teammateBarDriver.BindTarget(value5);
					}
					if ((Object)(object)teammateBarDriver.InventoryRow != (Object)null)
					{
						teammateBarDriver.InventoryRow.Target = value5;
					}
				}
				else if (((Component)teammateBarDriver).gameObject.activeSelf)
				{
					((Component)teammateBarDriver).gameObject.SetActive(false);
				}
			}
			if (Time.unscaledTime >= _nextDiagnosticLogTime)
			{
				_nextDiagnosticLogTime = Time.unscaledTime + 2f;
				LogCoordinatorDiagnostics(instance.Teammates.Count, val, s_visibleScratch.Count);
			}
		}

		private void EnsureDriversForDisplayOrder(Dictionary<int, Character> visibleById)
		{
			for (int i = 0; i < _displayOrder.Count; i++)
			{
				int num = _displayOrder[i];
				if (!_driversByStableId.ContainsKey(num) && visibleById.TryGetValue(num, out var value) && !((Object)(object)value == (Object)null))
				{
					TeammateBarDriver teammateBarDriver = CreateBar();
					if (!((Object)(object)teammateBarDriver == (Object)null))
					{
						_driversByStableId[num] = teammateBarDriver;
						_stableIdByDriver[teammateBarDriver] = num;
						_pool.Add(teammateBarDriver);
						teammateBarDriver.BindTarget(value);
						PluginLogger.Debug("[PI-DIAG][DriverCreated] stableId=" + num + " driver=" + ((Object)teammateBarDriver).GetInstanceID() + " target=" + GetCharacterDebugName(value) + " rootSelf=" + ((Component)teammateBarDriver).gameObject.activeSelf + " rootHierarchy=" + ((Component)teammateBarDriver).gameObject.activeInHierarchy + " afflictions=" + ((teammateBarDriver.afflictions != null) ? teammateBarDriver.afflictions.Length : (-1)) + " texts=" + ((teammateBarDriver.afflictionTexts != null) ? teammateBarDriver.afflictionTexts.Length : (-1)));
					}
				}
			}
		}

		private void LogCoordinatorDiagnostics(int rosterCount, Character focus, int visibleCount)
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder(512);
				stringBuilder.Append("[PI-DIAG][Coordinator] roster=").Append(rosterCount).Append(" candidates=")
					.Append(_scratch.Count)
					.Append(" visible=")
					.Append(visibleCount)
					.Append(" order=")
					.Append(_displayOrder.Count)
					.Append(" pool=")
					.Append(_pool.Count)
					.Append(" focus=")
					.Append(GetCharacterDebugName(focus))
					.Append(" originalSelf=")
					.Append((Object)(object)_origBar != (Object)null && ((Component)_origBar).gameObject.activeSelf)
					.Append(" originalHierarchy=")
					.Append((Object)(object)_origBar != (Object)null && ((Component)_origBar).gameObject.activeInHierarchy);
				for (int i = 0; i < _pool.Count; i++)
				{
					TeammateBarDriver teammateBarDriver = _pool[i];
					if ((Object)(object)teammateBarDriver == (Object)null)
					{
						stringBuilder.Append(" | driver[").Append(i).Append("]=null");
					}
					else
					{
						stringBuilder.Append(" | driver[").Append(i).Append("] id=")
							.Append(((Object)teammateBarDriver).GetInstanceID())
							.Append(" stable=")
							.Append(GetDriverStableId(teammateBarDriver))
							.Append(" sibling=")
							.Append(((Component)teammateBarDriver).transform.GetSiblingIndex())
							.Append(" self=")
							.Append(((Component)teammateBarDriver).gameObject.activeSelf)
							.Append(" hierarchy=")
							.Append(((Component)teammateBarDriver).gameObject.activeInHierarchy)
							.Append(" enabled=")
							.Append(((Behaviour)teammateBarDriver).enabled)
							.Append(" target=")
							.Append(GetCharacterDebugName(teammateBarDriver.Target))
							.Append(" aff=")
							.Append((teammateBarDriver.afflictions != null) ? teammateBarDriver.afflictions.Length : (-1))
							.Append(" txt=")
							.Append((teammateBarDriver.afflictionTexts != null) ? teammateBarDriver.afflictionTexts.Length : (-1));
					}
				}
				PluginLogger.Debug(stringBuilder.ToString());
			}
			catch (Exception ex)
			{
				PluginLogger.ThrottleWarn("pi_diag_coordinator", "[PI-DIAG][Coordinator] failed: " + ex);
			}
		}

		private static string GetCharacterDebugName(Character character)
		{
			if ((Object)(object)character == (Object)null || ((object)character).Equals((object?)null))
			{
				return "<null>";
			}
			try
			{
				if ((Object)(object)((MonoBehaviourPun)character).photonView != (Object)null && ((MonoBehaviourPun)character).photonView.Owner != null && !string.IsNullOrEmpty(((MonoBehaviourPun)character).photonView.Owner.NickName))
				{
					return ((MonoBehaviourPun)character).photonView.Owner.NickName;
				}
			}
			catch
			{
			}
			try
			{
				return character.characterName ?? ((Object)character).name ?? "<unnamed>";
			}
			catch
			{
				return "<invalid>";
			}
		}

		private void ApplyDriverSiblingOrder()
		{
			int num = 0;
			for (int i = 0; i < _displayOrder.Count; i++)
			{
				if (_driversByStableId.TryGetValue(_displayOrder[i], out var value) && !((Object)(object)value == (Object)null))
				{
					if (((Component)value).transform.GetSiblingIndex() != num)
					{
						((Component)value).transform.SetSiblingIndex(num);
					}
					num++;
				}
			}
		}

		private int GetDriverStableId(TeammateBarDriver driver)
		{
			if ((Object)(object)driver == (Object)null)
			{
				return int.MinValue;
			}
			if (!_stableIdByDriver.TryGetValue(driver, out var value))
			{
				return int.MinValue;
			}
			return value;
		}

		private void CleanupUntrackedDrivers()
		{
			_driverCleanupScratch.Clear();
			foreach (KeyValuePair<int, TeammateBarDriver> item in _driversByStableId)
			{
				int key = item.Key;
				if (!s_currentStableIds.Contains(key) && !s_retainedById.ContainsKey(key))
				{
					_driverCleanupScratch.Add(key);
				}
			}
			for (int i = 0; i < _driverCleanupScratch.Count; i++)
			{
				int key2 = _driverCleanupScratch[i];
				if (!_driversByStableId.TryGetValue(key2, out var value))
				{
					continue;
				}
				_driversByStableId.Remove(key2);
				if ((Object)(object)value != (Object)null)
				{
					_stableIdByDriver.Remove(value);
					_pool.Remove(value);
					if ((Object)(object)((Component)value).gameObject != (Object)null && ((Component)value).gameObject.activeSelf)
					{
						((Component)value).gameObject.SetActive(false);
					}
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
			}
		}

		private void HideAll()
		{
			for (int i = 0; i < _pool.Count; i++)
			{
				TeammateBarDriver teammateBarDriver = _pool[i];
				if ((Object)(object)teammateBarDriver != (Object)null && (Object)(object)((Component)teammateBarDriver).gameObject != (Object)null && ((Component)teammateBarDriver).gameObject.activeSelf)
				{
					((Component)teammateBarDriver).gameObject.SetActive(false);
				}
			}
		}

		private TeammateBarDriver CreateBar()
		{
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0292: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid