Decompiled source of SquadUI v1.0.0

SquadUI.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using Agents;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using GameData;
using Gear;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Player;
using SNetwork;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SquadUI")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SquadUI")]
[assembly: AssemblyTitle("SquadUI")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 SquadUI
{
	public static class SquadUIArmor
	{
		private static readonly Dictionary<int, float> s_rel = new Dictionary<int, float>();

		public static void Set(int slot, float relative01)
		{
			try
			{
				if (slot < 0)
				{
					slot = PlayerManager.GetLocalPlayerSlotIndex();
				}
				if (slot >= 0)
				{
					s_rel[slot] = ((relative01 < 0f) ? 0f : ((relative01 > 1f) ? 1f : relative01));
				}
			}
			catch
			{
			}
		}

		public static void Clear(int slot)
		{
			try
			{
				s_rel.Remove(slot);
			}
			catch
			{
			}
		}

		public static void ClearAll()
		{
			try
			{
				s_rel.Clear();
			}
			catch
			{
			}
		}

		internal static bool TryGet(int slot, out float rel)
		{
			return s_rel.TryGetValue(slot, out rel);
		}
	}
	public class HudBehaviour : MonoBehaviour
	{
		private static int s_lastFrame = -1;

		private static bool s_tickLogged;

		private static bool s_guiLogged;

		private static float s_nextCapture;

		private static float s_warnAt = -999f;

		private static HudSkin s_skin;

		private static readonly List<MemberView> s_rows = new List<MemberView>();

		private static readonly List<float> s_rowH = new List<float>();

		private static float s_guiMs;

		private static int s_guiFrames;

		private static float s_nextPerfLog;

		private static bool s_offsetDirty;

		private static float s_offsetDirtyAt;

		private void Update()
		{
			OnTick();
		}

		internal static void OnTick()
		{
			try
			{
				int frameCount = Time.frameCount;
				if (frameCount == s_lastFrame)
				{
					return;
				}
				s_lastFrame = frameCount;
				if (!s_tickLogged)
				{
					s_tickLogged = true;
					Plugin.LogSource.LogInfo((object)"[hud] 数据采集已启动。");
				}
				HudSettings settings = Plugin.Settings;
				if (settings == null)
				{
					return;
				}
				HandleKeys(settings);
				if (settings.Enabled.Value)
				{
					float num = Mathf.Clamp(settings.UpdateHz.Value, 2f, 60f);
					float unscaledTime = Time.unscaledTime;
					if (unscaledTime >= s_nextCapture)
					{
						s_nextCapture = unscaledTime + 1f / num;
						SquadReader.Capture();
					}
				}
				PerfLog(settings);
			}
			catch (Exception e)
			{
				Warn("tick", e);
			}
		}

		private static void HandleKeys(HudSettings s)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string value = s.ToggleKey.Value;
				if (!string.IsNullOrEmpty(value) && Enum.TryParse<KeyCode>(value, ignoreCase: true, out KeyCode result) && Input.GetKeyDown(result))
				{
					s.Enabled.Value = !s.Enabled.Value;
					try
					{
						((ConfigEntryBase)s.Enabled).ConfigFile.Save();
					}
					catch
					{
					}
					Plugin.LogSource.LogInfo((object)("[hud] 小队面板 " + (s.Enabled.Value ? "开" : "关")));
				}
				if (!s.MoveWithArrows.Value || (!Input.GetKey((KeyCode)306) && !Input.GetKey((KeyCode)305)))
				{
					return;
				}
				float num = 0f;
				float num2 = 0f;
				if (Input.GetKey((KeyCode)276))
				{
					num -= 1f;
				}
				if (Input.GetKey((KeyCode)275))
				{
					num += 1f;
				}
				if (Input.GetKey((KeyCode)273))
				{
					num2 -= 1f;
				}
				if (Input.GetKey((KeyCode)274))
				{
					num2 += 1f;
				}
				if (num != 0f || num2 != 0f)
				{
					float num3 = Mathf.Max(20f, s.MoveSpeed.Value) * Time.unscaledDeltaTime;
					s.OffsetX.Value = Mathf.Clamp(s.OffsetX.Value + num * num3, -400f, 4000f);
					s.OffsetY.Value = Mathf.Clamp(s.OffsetY.Value + num2 * num3, -400f, 3000f);
					s_offsetDirty = true;
					s_offsetDirtyAt = Time.unscaledTime;
				}
				else if (s_offsetDirty && Time.unscaledTime - s_offsetDirtyAt > 1f)
				{
					s_offsetDirty = false;
					try
					{
						((ConfigEntryBase)s.OffsetX).ConfigFile.Save();
						return;
					}
					catch
					{
						return;
					}
				}
			}
			catch
			{
			}
		}

		private void OnGUI()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Invalid comparison between Unknown and I4
			try
			{
				if (!s_guiLogged)
				{
					s_guiLogged = true;
					Plugin.LogSource.LogInfo((object)"[hud] 界面绘制已启动。");
				}
				HudSettings settings = Plugin.Settings;
				if (settings == null)
				{
					return;
				}
				Event current = Event.current;
				if (current == null || (int)current.type == 7)
				{
					float realtimeSinceStartup = Time.realtimeSinceStartup;
					EnsureSkin(settings);
					GUI.depth = -1000;
					bool flag = SquadReader.InLevel && SquadReader.Members.Count > 0;
					if (settings.Enabled.Value && (flag || settings.AlwaysDraw.Value))
					{
						DrawSquadPanel(settings);
					}
					s_guiMs += (Time.realtimeSinceStartup - realtimeSinceStartup) * 1000f;
					s_guiFrames++;
				}
			}
			catch (Exception e)
			{
				Warn("gui", e);
			}
		}

		private static void DrawSquadPanel(HudSettings s)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: Expected O, but got Unknown
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Expected O, but got Unknown
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Expected O, but got Unknown
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_0585: Unknown result type (might be due to invalid IL or missing references)
			//IL_0587: Unknown result type (might be due to invalid IL or missing references)
			//IL_0589: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_060d: Unknown result type (might be due to invalid IL or missing references)
			//IL_060f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0611: Unknown result type (might be due to invalid IL or missing references)
			//IL_0682: Unknown result type (might be due to invalid IL or missing references)
			//IL_0684: Unknown result type (might be due to invalid IL or missing references)
			//IL_0686: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_071d: Unknown result type (might be due to invalid IL or missing references)
			//IL_071f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0721: Unknown result type (might be due to invalid IL or missing references)
			//IL_0724: Unknown result type (might be due to invalid IL or missing references)
			//IL_0726: Unknown result type (might be due to invalid IL or missing references)
			//IL_0797: Unknown result type (might be due to invalid IL or missing references)
			//IL_0799: Unknown result type (might be due to invalid IL or missing references)
			//IL_079b: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(s.SelfScale.Value, 0.6f, 2f);
			float num2 = s.SelfBarW.Value * num;
			float num3 = s.SelfBarH.Value * num;
			float num4 = s.SelfRowGap.Value * num;
			float num5 = s.SelfColGap.Value * num;
			float num6 = num3 + num4;
			float num7 = num6 * 4f - num4;
			Color fill = Colors.Parse(s.SelfColArmor.Value, new Color(0.24f, 0.48f, 0.84f));
			Color fill2 = Colors.Parse(s.SelfColInfection.Value, new Color(0.26f, 0.76f, 0.29f));
			Color fill3 = Colors.Parse(s.SelfColHealth.Value, new Color(0.84f, 0.25f, 0.23f));
			Color fill4 = Colors.Parse(s.SelfColStamina.Value, new Color(0.91f, 0.76f, 0.23f));
			Color fill5 = Colors.Parse(s.SelfColWeapon.Value, new Color(0.31f, 0.85f, 0.48f));
			Color fill6 = Colors.Parse(s.SelfColTool.Value, new Color(0.5f, 0.78f, 0.91f));
			Color warnCol = Colors.Parse(s.ColorAmmoEmpty.Value, new Color(0.88f, 0.27f, 0.23f, 1f));
			Color readyCol = Colors.Parse(s.ColorPhaseReady.Value, new Color(0.31f, 0.85f, 0.48f, 1f));
			Color fill7 = Colors.Parse(s.ColorMeleeCharge.Value, new Color(1f, 0.6f, 0.23f, 1f));
			Color bg = Colors.Parse(s.SelfBarBg.Value, new Color(1f, 1f, 1f, 0.95f));
			Color border = default(Color);
			((Color)(ref border))..ctor(1f, 1f, 1f, 0.35f);
			float num8 = s.SelfLabelW.Value * num;
			try
			{
				string[] array = new string[4] { "护甲 100%", "感染 100%", "血量 100%", "体力 100%" };
				float num9 = 0f;
				for (int i = 0; i < array.Length; i++)
				{
					float x = s_skin.Small.CalcSize(new GUIContent(array[i])).x;
					if (x > num9)
					{
						num9 = x;
					}
				}
				num8 += num9 + 8f;
			}
			catch
			{
			}
			float num10 = s.SelfNameW.Value * num;
			try
			{
				float num11 = 0f;
				for (int j = 0; j < SquadReader.Members.Count; j++)
				{
					MemberView memberView = SquadReader.Members[j];
					string text = ((memberView.Tool != null && !string.IsNullOrEmpty(memberView.Tool.Name)) ? ToolLabel(memberView.Tool.Name) : "工具");
					string[] array2 = new string[4]
					{
						"主武器 100%",
						"特殊武器 100%",
						text + " 100%",
						"蓄力 100%  0.0s"
					};
					for (int k = 0; k < array2.Length; k++)
					{
						float x2 = s_skin.Small.CalcSize(new GUIContent(array2[k])).x;
						if (x2 > num11)
						{
							num11 = x2;
						}
					}
				}
				num10 += num11 + 8f;
			}
			catch
			{
			}
			float num12 = 0f;
			try
			{
				for (int l = 0; l < SquadReader.Members.Count; l++)
				{
					string name = SquadReader.Members[l].Name;
					if (string.IsNullOrEmpty(name))
					{
						continue;
					}
					for (int m = 0; m < name.Length; m++)
					{
						float x3 = s_skin.Small.CalcSize(new GUIContent(name.Substring(m, 1))).x;
						if (x3 > num12)
						{
							num12 = x3;
						}
					}
				}
				num12 += 8f;
			}
			catch
			{
			}
			float value = s.OffsetX.Value;
			float num13 = s.OffsetY.Value;
			for (int n = 0; n < SquadReader.Members.Count; n++)
			{
				MemberView memberView2 = SquadReader.Members[n];
				if ((s.ShowSelf.Value || !memberView2.IsLocal) && (s.ShowDead.Value || memberView2.Alive))
				{
					float num14 = value + num12;
					float x4 = num14 + num2 + num8 + num5;
					s_skin.Small.normal.textColor = memberView2.Color;
					string text2 = (string.IsNullOrEmpty(memberView2.Name) ? "?" : memberView2.Name);
					float num15 = (float)s_skin.Small.fontSize + 8f;
					int num16 = Mathf.Max(1, Mathf.FloorToInt(num7 / num15));
					int num17 = Mathf.Min(text2.Length, num16);
					float num18 = num13 + Mathf.Max(0f, (num7 - (float)num17 * num15) * 0.5f);
					for (int num19 = 0; num19 < num17; num19++)
					{
						TextInBar(value, num18 + (float)num19 * num15, num12, num15, text2.Substring(num19, 1));
					}
					float rel = (memberView2.HasArmor ? memberView2.ArmorRel : 0f);
					SelfRow(num14, num13 + 0f * num6, num2, num3, num8, rel, fill, bg, border, "护甲", Pct01(rel), null);
					float rel2 = (memberView2.HasInfection ? memberView2.Infection : 0f);
					SelfRow(num14, num13 + 1f * num6, num2, num3, num8, rel2, fill2, bg, border, "感染", Pct01(rel2), null);
					float rel3 = (memberView2.HasDamage ? memberView2.HealthRel : 0f);
					SelfRow(num14, num13 + 2f * num6, num2, num3, num8, rel3, fill3, bg, border, "血量", Pct01(rel3), null);
					float rel4 = (memberView2.HasStamina ? memberView2.StaminaRel : 0f);
					string inner = (memberView2.HasStamina ? (Mathf.RoundToInt(memberView2.Bpm) + " ♥") : "--");
					SelfRow(num14, num13 + 3f * num6, num2, num3, num8, rel4, fill4, bg, border, "体力", memberView2.HasStamina ? Pct01(rel4) : "--", inner);
					WeaponRow(x4, num13 + 0f * num6, num2, num3, num10, memberView2.Standard, fill5, bg, border, isTool: false, warnCol, readyCol, "主武器");
					WeaponRow(x4, num13 + 1f * num6, num2, num3, num10, memberView2.Special, fill5, bg, border, isTool: false, warnCol, readyCol, "特殊武器");
					WeaponRow(x4, num13 + 2f * num6, num2, num3, num10, memberView2.Tool, fill6, bg, border, isTool: true, warnCol, readyCol, null);
					float meleeChargeRel = memberView2.MeleeChargeRel;
					string value2 = ((memberView2.MeleeChargeNeed > 0.01f) ? (Mathf.RoundToInt(Mathf.Clamp01(meleeChargeRel) * 100f) + "%  " + One(memberView2.MeleeChargeNeed) + "s") : "--");
					SelfRow(x4, num13 + 3f * num6, num2, num3, num10, meleeChargeRel, fill7, bg, border, "蓄力", value2, null);
					num13 += num7 + num4 * 2f;
				}
			}
		}

		private static void EnsureSkin(HudSettings s)
		{
			int num = Mathf.Clamp(s.BaseFontSize.Value, 8, 28);
			string text = s.FontName.Value ?? "";
			if (s_skin == null || !s_skin.Ready || s_skin.Size != num || !string.Equals(s_skin.FontName, text))
			{
				s_skin = HudSkin.Build(num, text);
			}
		}

		private static string Fit(string s, int max)
		{
			if (string.IsNullOrEmpty(s))
			{
				return "?";
			}
			if (s.Length <= max)
			{
				return s;
			}
			return s.Substring(0, Mathf.Max(1, max - 1)) + "~";
		}

		private static string Two(float v)
		{
			int num = Mathf.RoundToInt(v * 100f);
			return num / 100 + "." + num / 10 % 10 + num % 10;
		}

		private static void PerfLog(HudSettings s)
		{
			try
			{
				if (s != null && s.PerfLog.Value)
				{
					float unscaledTime = Time.unscaledTime;
					if (!(unscaledTime < s_nextPerfLog))
					{
						s_nextPerfLog = unscaledTime + 1f;
						float v = ((s_guiFrames > 0) ? (s_guiMs / (float)s_guiFrames) : 0f);
						Plugin.LogSource.LogInfo((object)("[perf] capture=" + Two(SquadReader.MsCapture) + "ms  scan峰值=" + Two(SquadReader.MsScanMax) + "ms  ongui=" + Two(v) + "ms/帧(" + s_guiFrames + "帧)  members=" + SquadReader.LastMemberCount + "  placed=" + SquadReader.PlacedCount));
						SquadReader.MsScanMax = 0f;
						s_guiMs = 0f;
						s_guiFrames = 0;
					}
				}
			}
			catch
			{
			}
		}

		private static string Pct01(float rel)
		{
			return Mathf.RoundToInt(Mathf.Clamp01(rel) * 100f) + "%";
		}

		private static string ToolLabel(string itemName)
		{
			if (string.IsNullOrEmpty(itemName))
			{
				return "--";
			}
			if (itemName.Contains("Optron"))
			{
				return "扫描";
			}
			if (itemName.Contains("Krieger"))
			{
				return "布雷";
			}
			if (itemName.Contains("Stalwart"))
			{
				return "胶沫";
			}
			if (itemName.Contains("SGB3"))
			{
				return "连发炮台";
			}
			if (itemName.Contains("Meduza"))
			{
				return "hel炮台";
			}
			if (itemName.Contains("51 RSG"))
			{
				return "狙击炮台";
			}
			if (itemName.Contains("B5 LFR"))
			{
				return "霰弹炮台";
			}
			return itemName;
		}

		private static void TextAt(float x, float y, float w, float h, string text)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			GUI.Label(new Rect(x, y, w, h), text, s_skin.Small);
		}

		private static void TextInBar(float x, float y, float w, float barH, string text)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)s_skin.Small.fontSize + 8f;
			GUI.Label(new Rect(x, y + (barH - num) * 0.5f, w, num), text, s_skin.Small);
		}

		private static void SelfRow(float x, float y, float w, float h, float labW, float rel, Color fill, Color bg, Color border, string label, string value, string inner)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			HudSkin.Bar(new Rect(x, y, w, h), rel, fill, bg, border);
			s_skin.Small.normal.textColor = new Color(0.05f, 0.05f, 0.06f, 1f);
			if (!string.IsNullOrEmpty(inner))
			{
				TextInBar(x + 4f, y, w - 8f, h, inner);
			}
			s_skin.Small.normal.textColor = fill;
			TextInBar(x + w + 6f, y, labW, h, label + " " + value);
		}

		private static void WeaponRow(float x, float y, float w, float h, float nameW, AmmoView a, Color fill, Color bg, Color border, bool isTool, Color warnCol, Color readyCol, string fixedName)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			float rel = a?.Rel ?? 0f;
			Color val = ((a != null && a.PhaseWarn) ? warnCol : ((a != null && a.PhaseReady) ? readyCol : fill));
			HudSkin.Bar(new Rect(x, y, w, h), rel, val, bg, border);
			string text = ((a != null) ? a.Text() : "--");
			if (isTool && text.StartsWith("炮台"))
			{
				int num = text.IndexOf(' ');
				if (num > 0)
				{
					text = text.Substring(num + 1);
				}
			}
			s_skin.Small.normal.textColor = new Color(0.05f, 0.05f, 0.06f, 1f);
			TextInBar(x + 4f, y, w - 8f, h, text);
			string text2 = ((a != null && !string.IsNullOrEmpty(a.Name)) ? a.Name : "");
			string text3 = ((!string.IsNullOrEmpty(fixedName)) ? fixedName : (isTool ? ToolLabel(text2) : ((text2.Length > 0) ? text2 : "--")));
			string text4 = "";
			if (a != null && a.Present)
			{
				if (!isTool)
				{
					text4 = "  " + Pct01(a.RelPercent);
				}
				else if (!a.NoAmmo && a.PackMax > 0)
				{
					text4 = "  " + Pct01(a.PackRel);
				}
			}
			s_skin.Small.normal.textColor = val;
			TextInBar(x + w + 6f, y, nameW, h, text3 + text4);
		}

		private static string One(float v)
		{
			int num = Mathf.RoundToInt(v * 10f);
			return num / 10 + "." + Mathf.Abs(num % 10);
		}

		private static void Warn(string where, Exception e)
		{
			float unscaledTime = Time.unscaledTime;
			if (unscaledTime - s_warnAt < 5f)
			{
				return;
			}
			s_warnAt = unscaledTime;
			try
			{
				Plugin.LogSource.LogWarning((object)("[hud] " + where + " failed: " + e.GetType().Name + ": " + e.Message));
			}
			catch
			{
			}
		}
	}
	public sealed class HudSettings
	{
		public ConfigEntry<bool> Enabled;

		public ConfigEntry<bool> AlwaysDraw;

		public ConfigEntry<float> UpdateHz;

		public ConfigEntry<bool> ProbeLog;

		public ConfigEntry<bool> AmmoDump;

		public ConfigEntry<bool> PerfLog;

		public ConfigEntry<bool> RemoteScannerPhase;

		public ConfigEntry<string> ToggleKey;

		public ConfigEntry<bool> MoveWithArrows;

		public ConfigEntry<float> MoveSpeed;

		public ConfigEntry<float> SelfX;

		public ConfigEntry<float> SelfY;

		public ConfigEntry<float> SelfScale;

		public ConfigEntry<float> SelfBarW;

		public ConfigEntry<float> SelfBarH;

		public ConfigEntry<float> SelfRowGap;

		public ConfigEntry<float> SelfLabelW;

		public ConfigEntry<float> SelfColGap;

		public ConfigEntry<float> SelfNameW;

		public ConfigEntry<string> SelfColArmor;

		public ConfigEntry<string> SelfColInfection;

		public ConfigEntry<string> SelfColHealth;

		public ConfigEntry<string> SelfColStamina;

		public ConfigEntry<string> SelfColWeapon;

		public ConfigEntry<string> SelfColTool;

		public ConfigEntry<string> SelfBarBg;

		public ConfigEntry<string> Anchor;

		public ConfigEntry<float> OffsetX;

		public ConfigEntry<float> OffsetY;

		public ConfigEntry<float> Scale;

		public ConfigEntry<float> Opacity;

		public ConfigEntry<float> PanelWidth;

		public ConfigEntry<string> FontName;

		public ConfigEntry<int> BaseFontSize;

		public ConfigEntry<bool> ShowSelf;

		public ConfigEntry<bool> ShowDead;

		public ConfigEntry<bool> ShowHealth;

		public ConfigEntry<bool> ShowInfection;

		public ConfigEntry<bool> ShowStamina;

		public ConfigEntry<bool> ShowHeartbeat;

		public ConfigEntry<bool> ShowAmmo;

		public ConfigEntry<bool> ShowSelfDetail;

		public ConfigEntry<bool> ShowMelee;

		public ConfigEntry<bool> ShowCarry;

		public ConfigEntry<bool> ShowPocket;

		public ConfigEntry<string> ColorPanel;

		public ConfigEntry<string> ColorText;

		public ConfigEntry<string> ColorHealthGood;

		public ConfigEntry<string> ColorHealthBad;

		public ConfigEntry<string> ColorStamina;

		public ConfigEntry<string> ColorInfection;

		public ConfigEntry<string> ColorAmmo;

		public ConfigEntry<string> ColorAmmoEmpty;

		public ConfigEntry<string> ColorMeleeCharge;

		public ConfigEntry<string> ColorPhaseReady;

		private static ConfigDescription Choice(params string[] values)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			return new ConfigDescription("", (AcceptableValueBase)(object)new AcceptableValueList<string>(values), Array.Empty<object>());
		}

		public static HudSettings Bind(ConfigFile cfg)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Expected O, but got Unknown
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Expected O, but got Unknown
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Expected O, but got Unknown
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Expected O, but got Unknown
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Expected O, but got Unknown
			HudSettings hudSettings = new HudSettings();
			hudSettings.Enabled = cfg.Bind<bool>("1-General", "Enabled", true, "总开关。");
			hudSettings.AlwaysDraw = cfg.Bind<bool>("1-General", "AlwaysDraw", true, "没有关卡数据时也显示面板(例如在标题界面)。进关卡后不影响显示。");
			hudSettings.UpdateHz = cfg.Bind<float>("1-General", "UpdateHz", 15f, new ConfigDescription("每秒采集多少次队友数据。15 足够顺滑且几乎无开销。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 60f), Array.Empty<object>()));
			hudSettings.ProbeLog = cfg.Bind<bool>("1-General", "ProbeLog", false, "详细日志:每秒把读取到的队友数据写一行到 BepInEx 日志。");
			hudSettings.AmmoDump = cfg.Bind<bool>("1-General", "AmmoDump", false, "详细日志:每秒输出各槽位的弹药字段(AmmoInPack/AmmoMaxCap/BulletsInPack/CostOfBullet/GetClassAmmoInPackAbs…)。用来校正工具弹药口径,确认后我会关掉默认值。");
			hudSettings.Anchor = cfg.Bind<string>("2-Layout", "Anchor", "BottomRight", new ConfigDescription("状态栏吸附在屏幕哪个角。", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[4] { "TopLeft", "TopRight", "BottomLeft", "BottomRight" }), Array.Empty<object>()));
			hudSettings.OffsetX = cfg.Bind<float>("2-Layout", "OffsetX", 18f, new ConfigDescription("距屏幕边缘的水平像素。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1200f), Array.Empty<object>()));
			hudSettings.OffsetY = cfg.Bind<float>("2-Layout", "OffsetY", 150f, new ConfigDescription("距屏幕边缘的垂直像素(底部吸附时是离底距离)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1200f), Array.Empty<object>()));
			hudSettings.Scale = cfg.Bind<float>("2-Layout", "Scale", 1f, new ConfigDescription("整体缩放。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.6f, 2.5f), Array.Empty<object>()));
			hudSettings.Opacity = cfg.Bind<float>("2-Layout", "Opacity", 0.85f, new ConfigDescription("面板背景不透明度(文字不受影响)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			hudSettings.PanelWidth = cfg.Bind<float>("2-Layout", "PanelWidth", 470f, new ConfigDescription("面板宽度(未缩放像素)。", (AcceptableValueBase)(object)new AcceptableValueRange<float>(300f, 900f), Array.Empty<object>()));
			hudSettings.FontName = cfg.Bind<string>("2-Layout", "FontName", "Microsoft YaHei", "IMGUI 动态字体名;留空则用游戏默认字体(默认字体不含中文)。");
			hudSettings.BaseFontSize = cfg.Bind<int>("2-Layout", "BaseFontSize", 13, new ConfigDescription("基准字号。", (AcceptableValueBase)(object)new AcceptableValueRange<int>(8, 28), Array.Empty<object>()));
			hudSettings.ShowSelf = cfg.Bind<bool>("3-Content", "ShowSelf", true, "状态栏里是否也显示自己。");
			hudSettings.ShowDead = cfg.Bind<bool>("3-Content", "ShowDead", true, "是否显示已阵亡的队友。");
			hudSettings.ShowHealth = cfg.Bind<bool>("3-Content", "ShowHealth", true, "显示血量条。");
			hudSettings.ShowInfection = cfg.Bind<bool>("3-Content", "ShowInfection", true, "显示感染度。");
			hudSettings.ShowStamina = cfg.Bind<bool>("3-Content", "ShowStamina", true, "显示体力(心跳)条。");
			hudSettings.ShowHeartbeat = cfg.Bind<bool>("3-Content", "ShowHeartbeat", true, "在体力条上显示估算心跳 BPM。");
			hudSettings.ShowAmmo = cfg.Bind<bool>("3-Content", "ShowAmmo", true, "显示主武器/特殊武器/工具弹药(弹匣/备弹)。");
			hudSettings.ShowSelfDetail = cfg.Bind<bool>("3-Content", "ShowSelfDetail", true, "显示自己的近战武器与随身资源包详情块。");
			hudSettings.ShowMelee = cfg.Bind<bool>("3-Content", "ShowMelee", true, "详情块里显示近战武器(名称 + 蓄力)。");
			hudSettings.ShowCarry = cfg.Bind<bool>("3-Content", "ShowCarry", true, "每个队友各占一行显示他身上的资源包/消耗品种类与数量(不是只显示自己)。");
			hudSettings.ShowPocket = cfg.Bind<bool>("3-Content", "ShowPocket", true, "详情块里显示口袋物品(物品 ID + 数量)。");
			hudSettings.RemoteScannerPhase = cfg.Bind<bool>("3-Content", "RemoteScannerPhase", false, "队友(真人)的探测器是否也显示 准备/冷却/就绪。默认关闭:开着可能显示错误的冷却。有真人队友时可以打开试,若数字不对就报给我。");
			hudSettings.ToggleKey = cfg.Bind<string>("1-General", "ToggleKey", "F9", "小队面板的开关热键(KeyCode 名,如 F9 / F10 / Insert)。按一下切换显示,会自动存回本文件。");
			hudSettings.MoveWithArrows = cfg.Bind<bool>("1-General", "MoveWithArrows", true, "是否用 **Ctrl + 方向键** 移动小队面板(按住即移动,松手约 1 秒后自动存回本文件)。");
			hudSettings.MoveSpeed = cfg.Bind<float>("1-General", "MoveSpeed", 240f, "方向键移动速度(像素/秒)。");
			hudSettings.SelfX = cfg.Bind<float>("5-SelfPanel", "OffsetX", 12f, "距屏幕左边像素。");
			hudSettings.SelfY = cfg.Bind<float>("5-SelfPanel", "OffsetY", 30f, "距屏幕上边像素。");
			hudSettings.SelfScale = cfg.Bind<float>("5-SelfPanel", "Scale", 1f, "整体缩放 0.6–2.0。");
			hudSettings.SelfBarW = cfg.Bind<float>("5-SelfPanel", "BarWidth", 130f, "条宽。");
			hudSettings.SelfBarH = cfg.Bind<float>("5-SelfPanel", "BarHeight", 14f, "条高。");
			hudSettings.SelfRowGap = cfg.Bind<float>("5-SelfPanel", "RowGap", 7f, "行间距。");
			hudSettings.SelfLabelW = cfg.Bind<float>("5-SelfPanel", "LabelWidth", 0f, "第一列标签列的**额外留白**(列宽 = 文字实际宽度 + 这个值)。");
			hudSettings.SelfColGap = cfg.Bind<float>("5-SelfPanel", "ColGap", 16f, "两列之间的额外间距。");
			hudSettings.SelfNameW = cfg.Bind<float>("5-SelfPanel", "NameWidth", 0f, "第二列右侧「名字 + 百分号」的**额外留白**(同 LabelWidth)。");
			hudSettings.SelfColArmor = cfg.Bind<string>("5-SelfPanel", "ColArmor", "#3E7BD6", "护甲条颜色。");
			hudSettings.SelfColInfection = cfg.Bind<string>("5-SelfPanel", "ColInfection", "#43C24A", "感染条颜色。");
			hudSettings.SelfColHealth = cfg.Bind<string>("5-SelfPanel", "ColHealth", "#D6403A", "血量条颜色。");
			hudSettings.SelfColStamina = cfg.Bind<string>("5-SelfPanel", "ColStamina", "#E8C13A", "体力条 / 蓄力条颜色。");
			hudSettings.SelfColWeapon = cfg.Bind<string>("5-SelfPanel", "ColWeapon", "#4FD97A", "主/特殊武器条颜色(绿)。");
			hudSettings.SelfColTool = cfg.Bind<string>("5-SelfPanel", "ColTool", "#7FC7E8", "工具条颜色(蓝)。探测器不受此色影响(它用就绪绿/冷却红)。");
			hudSettings.SelfBarBg = cfg.Bind<string>("5-SelfPanel", "BarBg", "#FFFFFF66", "条内「空」的底色。#RRGGBBAA,末两位是透明度 —— 66 约为四成白,压暗场景上看着是浅灰、黑字清楚。想更亮写 99/B0,想更暗写 40/33。");
			hudSettings.PerfLog = cfg.Bind<bool>("1-General", "PerfLog", true, "性能日志:每秒打印一次采集/绘制耗时(ms)。不需要可以关掉。");
			hudSettings.ColorPanel = cfg.Bind<string>("4-Colours", "Panel", "#0A0F14B8", "面板底色,#RRGGBB 或 #RRGGBBAA。");
			hudSettings.ColorText = cfg.Bind<string>("5-Colours", "Text", "#E6F0F5FF", "主文字颜色。");
			hudSettings.ColorHealthGood = cfg.Bind<string>("5-Colours", "HealthGood", "#4FD97AFF", "血量充足时的颜色。");
			hudSettings.ColorHealthBad = cfg.Bind<string>("5-Colours", "HealthBad", "#E0453AFF", "血量危险时的颜色。");
			hudSettings.ColorStamina = cfg.Bind<string>("5-Colours", "Stamina", "#F2C14EFF", "体力条颜色。");
			hudSettings.ColorInfection = cfg.Bind<string>("5-Colours", "Infection", "#B06BE8FF", "感染度颜色。");
			hudSettings.ColorAmmo = cfg.Bind<string>("5-Colours", "Ammo", "#57B8E8FF", "弹药条颜色。");
			hudSettings.ColorAmmoEmpty = cfg.Bind<string>("5-Colours", "AmmoEmpty", "#E0453AFF", "弹药耗尽时的文字颜色。");
			hudSettings.ColorMeleeCharge = cfg.Bind<string>("5-Colours", "MeleeCharge", "#FF9A3CFF", "近战蓄力条颜色。");
			hudSettings.ColorPhaseReady = cfg.Bind<string>("5-Colours", "PhaseReady", "#4FD97AFF", "非弹药工具(生物探测器)**就绪**时的条颜色(冷却时固定用 AmmoEmpty 的红色)。");
			return hudSettings;
		}
	}
	internal sealed class HudSkin
	{
		internal bool Ready;

		internal int Size;

		internal string FontName;

		internal Font Font;

		internal GUIStyle Text;

		internal GUIStyle Small;

		internal GUIStyle Title;

		internal GUIStyle Right;

		internal static HudSkin Build(int size, string fontName)
		{
			HudSkin hudSkin = new HudSkin();
			hudSkin.Size = size;
			hudSkin.FontName = fontName;
			try
			{
				if (!string.IsNullOrEmpty(fontName))
				{
					hudSkin.Font = Font.CreateDynamicFontFromOSFont(fontName, size);
				}
			}
			catch
			{
				hudSkin.Font = null;
			}
			int size2 = Mathf.Max(8, size - 2);
			hudSkin.Text = Make(size, (TextAnchor)3, hudSkin.Font);
			hudSkin.Small = Make(size2, (TextAnchor)3, hudSkin.Font);
			hudSkin.Title = Make(size, (TextAnchor)3, hudSkin.Font);
			hudSkin.Title.fontStyle = (FontStyle)1;
			hudSkin.Right = Make(size2, (TextAnchor)5, hudSkin.Font);
			hudSkin.Ready = true;
			return hudSkin;
		}

		private static GUIStyle Make(int size, TextAnchor anchor, Font font)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0018: 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)
			GUIStyle val = new GUIStyle(GUI.skin.label);
			val.fontSize = size;
			val.alignment = anchor;
			val.wordWrap = false;
			val.richText = false;
			if ((Object)(object)font != (Object)null)
			{
				val.font = font;
			}
			val.normal.textColor = Color.white;
			return val;
		}

		internal static void Fill(Rect r, Color c)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!(((Rect)(ref r)).width <= 0f) && !(((Rect)(ref r)).height <= 0f))
			{
				Color color = GUI.color;
				GUI.color = c;
				GUI.DrawTexture(r, (Texture)(object)Texture2D.whiteTexture);
				GUI.color = color;
			}
		}

		internal static void Bar(Rect r, float rel, Color fill, Color bg, Color border)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			Fill(new Rect(((Rect)(ref r)).x - 1f, ((Rect)(ref r)).y - 1f, ((Rect)(ref r)).width + 2f, ((Rect)(ref r)).height + 2f), border);
			Fill(r, bg);
			rel = Mathf.Clamp01(rel);
			if (rel > 0.001f)
			{
				Fill(new Rect(((Rect)(ref r)).x, ((Rect)(ref r)).y, ((Rect)(ref r)).width * rel, ((Rect)(ref r)).height), fill);
			}
		}
	}
	internal static class Colors
	{
		internal static Color Parse(string hex, Color fallback)
		{
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(hex))
			{
				return fallback;
			}
			string text = hex.Trim();
			if (text.Length > 0 && text[0] == '#')
			{
				text = text.Substring(1);
			}
			if (text.Length == 3)
			{
				text = text[0].ToString() + text[0] + text[1] + text[1] + text[2] + text[2];
			}
			if (text.Length == 6)
			{
				text += "FF";
			}
			if (text.Length != 8)
			{
				return fallback;
			}
			try
			{
				int num = Convert.ToInt32(text.Substring(0, 2), 16);
				int num2 = Convert.ToInt32(text.Substring(2, 2), 16);
				int num3 = Convert.ToInt32(text.Substring(4, 2), 16);
				int num4 = Convert.ToInt32(text.Substring(6, 2), 16);
				return new Color((float)num / 255f, (float)num2 / 255f, (float)num3 / 255f, (float)num4 / 255f);
			}
			catch
			{
				return fallback;
			}
		}
	}
	[BepInPlugin("mltz.squadui", "Squad UI", "1.0.0")]
	public class Plugin : BasePlugin
	{
		public const string Guid = "mltz.squadui";

		public const string Name = "Squad UI";

		public const string Version = "1.0.0";

		internal static Plugin Instance;

		internal static ManualLogSource LogSource;

		internal static HudSettings Settings;

		public override void Load()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			Instance = this;
			LogSource = ((BasePlugin)this).Log;
			Settings = HudSettings.Bind(((BasePlugin)this).Config);
			try
			{
				((BasePlugin)this).AddComponent<HudBehaviour>();
			}
			catch (Exception ex)
			{
				LogSource.LogWarning((object)("[hud] 无法注入 HUD 组件:" + ex.Message));
			}
			ManualLogSource logSource = LogSource;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(44, 7, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Squad UI");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("(全队 UI)v");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.0");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded | 显示=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(Settings.Enabled.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("开关热键=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Settings.ToggleKey.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" 方向键移动=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(Settings.MoveWithArrows.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("缩放=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Settings.Scale.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" 采集=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Settings.UpdateHz.Value);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Hz");
			}
			logSource.LogInfo(val);
			LogSource.LogInfo((object)"[hud] 面板已就绪。");
		}

		public override bool Unload()
		{
			return true;
		}
	}
	internal sealed class AmmoView
	{
		internal string Tag = "?";

		internal string Name;

		internal int Clip = -1;

		internal int Pack;

		internal int PackMax;

		internal int ClipMax = -1;

		internal bool Present;

		internal bool Tool;

		internal string PhaseText;

		internal float PhaseRel = -1f;

		internal bool PhaseWarn;

		internal bool PhaseReady;

		internal bool NoAmmo;

		internal int OwnerSlot = -1;

		internal float RelPercent;

		internal float PackRel
		{
			get
			{
				if (PackMax <= 0)
				{
					return 0f;
				}
				return Mathf.Clamp01((float)Pack / (float)PackMax);
			}
		}

		internal float Rel
		{
			get
			{
				if (!(PhaseRel >= 0f))
				{
					return PackRel;
				}
				return Mathf.Clamp01(PhaseRel);
			}
		}

		internal string Text()
		{
			if (PhaseText != null)
			{
				return PhaseText;
			}
			if (!Present)
			{
				return "--";
			}
			if (Tool)
			{
				return Pack + "/" + PackMax;
			}
			if (ClipMax == 0)
			{
				return Pack + "/" + PackMax;
			}
			return ((Clip >= 0) ? Clip.ToString() : "--") + "/" + Pack + "/" + PackMax;
		}
	}
	internal sealed class GearView
	{
		internal string Name;

		internal int Amount = -1;

		internal int AmountMax = -1;

		internal bool IsResourcePack;
	}
	internal sealed class MemberView
	{
		internal int SlotIndex;

		internal string Name = "?";

		internal Color Color = Color.white;

		internal bool IsLocal;

		internal bool IsBot;

		internal bool Alive = true;

		internal string Error;

		internal SNet_Player Player;

		internal bool HasDamage;

		internal float Health;

		internal float HealthMax;

		internal float HealthRel;

		internal float Infection;

		internal bool HasInfection;

		internal bool HasArmor;

		internal float ArmorRel;

		internal bool HasStamina;

		internal float Stamina;

		internal float StaminaMax;

		internal float StaminaRel;

		internal bool IsTired;

		internal AmmoView Standard = new AmmoView
		{
			Tag = "STD"
		};

		internal AmmoView Special = new AmmoView
		{
			Tag = "SPC"
		};

		internal AmmoView Tool = new AmmoView
		{
			Tag = "TOL"
		};

		internal string MeleeName;

		internal string MeleeState;

		internal bool MeleeCharging;

		internal float MeleeChargeRel;

		internal float MeleeChargeSeconds;

		internal float MeleeChargeElapsed;

		internal float MeleeChargeNeed;

		internal bool ToolBusy;

		internal string ToolBusyLabel;

		internal readonly List<GearView> Carry = new List<GearView>();

		internal readonly List<GearView> Pocket = new List<GearView>();

		internal float Bpm;
	}
	internal static class SquadReader
	{
		private sealed class PlacedSentry
		{
			internal int Cur = -1;

			internal int Max = -1;
		}

		internal static readonly List<MemberView> Members = new List<MemberView>();

		internal static bool InLevel;

		internal static string LastError;

		internal static float MsCapture;

		internal static float MsScan;

		internal static float MsScanMax;

		internal static int LastMemberCount;

		private static readonly Dictionary<string, float> s_sentryCostByName = new Dictionary<string, float>();

		private static readonly HashSet<string> s_sentryModels = new HashSet<string>();

		private static readonly HashSet<string> s_scannerModels = new HashSet<string>();

		private static bool s_memLoaded;

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

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

		private static readonly Dictionary<uint, string> s_itemNameCache = new Dictionary<uint, string>();

		private static float s_lastProbe;

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

		private static readonly Dictionary<string, PlacedSentry> s_scanByModel = new Dictionary<string, PlacedSentry>();

		private static readonly List<SentryGunInstance> s_scanRefs = new List<SentryGunInstance>();

		private static readonly List<int> s_scanSlots = new List<int>();

		private static Type s_sentryType;

		private static float s_nextSentryScan;

		private static int s_scanMisses;

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

		private static float s_lastDump;

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

		internal static int PlacedCount => s_scanPlaced.Count;

		private static string SentryMemPath()
		{
			try
			{
				return Path.Combine(Paths.ConfigPath, "mltz.squadui.sentries.txt");
			}
			catch
			{
				return null;
			}
		}

		private static void LoadSentryMemory()
		{
			if (s_memLoaded)
			{
				return;
			}
			s_memLoaded = true;
			try
			{
				string text = SentryMemPath();
				if (text == null || !File.Exists(text))
				{
					return;
				}
				string[] array = File.ReadAllLines(text);
				foreach (string text2 in array)
				{
					if (string.IsNullOrEmpty(text2))
					{
						continue;
					}
					int num = text2.IndexOf('=');
					if (num <= 0)
					{
						continue;
					}
					string text3 = text2.Substring(0, num).Trim();
					string text4 = text2.Substring(num + 1).Trim();
					float result;
					if (text3 == "!scan")
					{
						if (!string.IsNullOrEmpty(text4))
						{
							s_scannerModels.Add(text4);
						}
					}
					else if (!string.IsNullOrEmpty(text3) && float.TryParse(text4, NumberStyles.Float, CultureInfo.InvariantCulture, out result) && result > 0.0001f)
					{
						s_sentryCostByName[text3] = result;
						s_sentryModels.Add(text3);
					}
				}
				Plugin.LogSource.LogInfo((object)("[sentry] 已载入型号记忆:" + s_sentryCostByName.Count + " 个型号 -> " + (text ?? "?")));
			}
			catch (Exception ex)
			{
				Plugin.LogSource.LogWarning((object)("[sentry] 载入型号记忆失败:" + ex.Message));
			}
		}

		private static void SaveSentryMemory()
		{
			try
			{
				string text = SentryMemPath();
				if (text == null)
				{
					return;
				}
				List<string> list = new List<string>();
				foreach (string s_scannerModel in s_scannerModels)
				{
					list.Add("!scan=" + s_scannerModel);
				}
				foreach (KeyValuePair<string, float> item in s_sentryCostByName)
				{
					list.Add(item.Key + "=" + item.Value.ToString("0.##########", CultureInfo.InvariantCulture));
				}
				File.WriteAllLines(text, list.ToArray());
			}
			catch (Exception ex)
			{
				Plugin.LogSource.LogWarning((object)("[sentry] 保存型号记忆失败:" + ex.Message));
			}
		}

		private static string ArchKey(ArchetypeDataBlock arch)
		{
			if (arch == null)
			{
				return null;
			}
			return F(arch.CostOfBullet) + "|" + arch.DefaultClipSize + "|" + F(arch.Sentry_DetectionMaxRange) + "|" + F(arch.Sentry_DetectionMaxAngle);
		}

		private static void ScanPlacedSentry()
		{
			float unscaledTime = Time.unscaledTime;
			for (int num = s_scanRefs.Count - 1; num >= 0; num--)
			{
				SentryGunInstance val = s_scanRefs[num];
				bool flag = false;
				try
				{
					flag = (Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null && ((Component)val).gameObject.activeInHierarchy;
				}
				catch
				{
				}
				if (!flag)
				{
					s_scanRefs.RemoveAt(num);
					if (num < s_scanSlots.Count)
					{
						s_scanSlots.RemoveAt(num);
					}
				}
			}
			s_scanPlaced.Clear();
			s_scanByModel.Clear();
			for (int i = 0; i < s_scanRefs.Count; i++)
			{
				SentryGunInstance val2 = s_scanRefs[i];
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				int num2 = ((i < s_scanSlots.Count) ? s_scanSlots[i] : (-1));
				if (num2 < 0)
				{
					try
					{
						PlayerAgent owner = ((Item)val2).Owner;
						if ((Object)(object)owner != (Object)null)
						{
							num2 = owner.PlayerSlotIndex;
							if (i < s_scanSlots.Count)
							{
								s_scanSlots[i] = num2;
							}
						}
					}
					catch
					{
					}
				}
				float num3 = -1f;
				float num4 = -1f;
				float num5 = -1f;
				try
				{
					num3 = val2.CostOfBullet;
				}
				catch
				{
				}
				try
				{
					num4 = val2.Ammo;
				}
				catch
				{
				}
				try
				{
					num5 = val2.AmmoMaxCap;
				}
				catch
				{
				}
				if (num3 <= 0.0001f)
				{
					continue;
				}
				PlacedSentry placedSentry = new PlacedSentry();
				placedSentry.Cur = ((num4 >= 0f) ? Mathf.FloorToInt(num4 / num3) : (-1));
				placedSentry.Max = ((num5 >= 0f) ? Mathf.FloorToInt(num5 / num3) : (-1));
				if (num2 >= 0)
				{
					s_scanPlaced[num2] = placedSentry;
				}
				try
				{
					string publicName = ((Item)val2).PublicName;
					if (!string.IsNullOrEmpty(publicName) && publicName.IndexOf(' ') > 0)
					{
						s_scanByModel[publicName] = placedSentry;
						float value;
						bool num6 = !s_sentryCostByName.TryGetValue(publicName, out value) || Mathf.Abs(value - num3) > 0.0001f;
						s_sentryCostByName[publicName] = num3;
						s_sentryModels.Add(publicName);
						if (num6)
						{
							SaveSentryMemory();
							Plugin.LogSource.LogInfo((object)("[sentry] 记下型号成本:" + publicName + " = " + num3.ToString("0.##########", CultureInfo.InvariantCulture)));
						}
					}
				}
				catch
				{
				}
			}
			bool flag2 = false;
			foreach (KeyValuePair<int, string> s_deployedSlot in s_deployedSlots)
			{
				if (!s_scanPlaced.TryGetValue(s_deployedSlot.Key, out var _) && (string.IsNullOrEmpty(s_deployedSlot.Value) || !s_scanByModel.ContainsKey(s_deployedSlot.Value)))
				{
					flag2 = true;
					break;
				}
			}
			if (flag2 && unscaledTime >= s_nextSentryScan)
			{
				s_scanMisses++;
				float num7 = 3f;
				for (int j = 1; j < s_scanMisses; j++)
				{
					if (!(num7 < 120f))
					{
						break;
					}
					num7 *= 2f;
				}
				if (num7 > 120f)
				{
					num7 = 120f;
				}
				s_nextSentryScan = unscaledTime + num7;
				try
				{
					if (s_sentryType == (Type)null)
					{
						s_sentryType = Il2CppType.From(typeof(SentryGunInstance));
					}
					Il2CppReferenceArray<Object> val3 = Object.FindObjectsOfType(s_sentryType);
					if (val3 == null)
					{
						return;
					}
					for (int k = 0; k < ((Il2CppArrayBase<Object>)(object)val3).Length; k++)
					{
						SentryGunInstance val4 = ((((Il2CppArrayBase<Object>)(object)val3)[k] != (Object)null) ? ((Il2CppObjectBase)((Il2CppArrayBase<Object>)(object)val3)[k]).TryCast<SentryGunInstance>() : null);
						if ((Object)(object)val4 == (Object)null)
						{
							continue;
						}
						bool flag3 = false;
						for (int l = 0; l < s_scanRefs.Count; l++)
						{
							if ((Object)(object)s_scanRefs[l] == (Object)(object)val4)
							{
								flag3 = true;
								break;
							}
						}
						if (!flag3)
						{
							s_scanRefs.Add(val4);
							s_scanSlots.Add(-1);
						}
					}
					return;
				}
				catch
				{
					return;
				}
			}
			if (!flag2)
			{
				s_scanMisses = 0;
			}
		}

		internal static void Capture()
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			LoadSentryMemory();
			Members.Clear();
			InLevel = false;
			LastError = null;
			try
			{
				if ((Object)(object)PlayerManager.Current == (Object)null)
				{
					return;
				}
				List<PlayerAgent> playerAgentsInLevel = PlayerManager.PlayerAgentsInLevel;
				if (playerAgentsInLevel == null)
				{
					return;
				}
				InLevel = true;
				int localSlot = -1;
				try
				{
					localSlot = PlayerManager.GetLocalPlayerSlotIndex();
				}
				catch
				{
				}
				for (int i = 0; i < playerAgentsInLevel.Count; i++)
				{
					MemberView memberView = null;
					try
					{
						PlayerAgent val = playerAgentsInLevel[i];
						if ((Object)(object)val != (Object)null)
						{
							memberView = new MemberView();
							ReadMember(val, memberView, localSlot);
						}
					}
					catch (Exception ex)
					{
						if (memberView == null)
						{
							memberView = new MemberView();
						}
						memberView.Error = ex.GetType().Name;
					}
					if (memberView != null)
					{
						Members.Add(memberView);
					}
				}
				Members.Sort((MemberView x, MemberView y) => x.SlotIndex.CompareTo(y.SlotIndex));
			}
			catch (Exception ex2)
			{
				LastError = ex2.Message;
			}
			if (!InLevel)
			{
				s_backpackBySlot.Clear();
				s_deployedCheckedAt.Clear();
				s_deployedSlots.Clear();
				SquadUIArmor.ClearAll();
				s_scanRefs.Clear();
				s_scanSlots.Clear();
				s_scanPlaced.Clear();
				s_scanMisses = 0;
			}
			float realtimeSinceStartup2 = Time.realtimeSinceStartup;
			ScanPlacedSentry();
			float realtimeSinceStartup3 = Time.realtimeSinceStartup;
			Probe();
			DumpAmmo();
			MsCapture = (realtimeSinceStartup2 - realtimeSinceStartup) * 1000f;
			MsScan = (realtimeSinceStartup3 - realtimeSinceStartup2) * 1000f;
			if (MsScan > MsScanMax)
			{
				MsScanMax = MsScan;
			}
			LastMemberCount = Members.Count;
		}

		private static void ReadMember(PlayerAgent a, MemberView mv, int localSlot)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			mv.SlotIndex = a.PlayerSlotIndex;
			mv.Alive = ((Agent)a).Alive;
			try
			{
				if (SquadUIArmor.TryGet(mv.SlotIndex, out var rel))
				{
					mv.HasArmor = true;
					mv.ArmorRel = Mathf.Clamp01(rel);
				}
			}
			catch
			{
			}
			try
			{
				mv.Name = a.PlayerName;
			}
			catch
			{
			}
			if (string.IsNullOrEmpty(mv.Name))
			{
				mv.Name = "P" + (mv.SlotIndex + 1);
			}
			try
			{
				mv.IsLocal = ((localSlot >= 0) ? (mv.SlotIndex == localSlot) : ((Agent)a).IsLocallyOwned);
			}
			catch
			{
				mv.IsLocal = false;
			}
			try
			{
				mv.Color = PlayerManager.GetStaticPlayerColor(mv.SlotIndex);
			}
			catch
			{
				mv.Color = Color.white;
			}
			Dam_PlayerDamageBase damage = a.Damage;
			if ((Object)(object)damage != (Object)null)
			{
				mv.HasDamage = true;
				try
				{
					mv.Health = ((Dam_SyncedDamageBase)damage).Health;
				}
				catch
				{
				}
				try
				{
					mv.HealthMax = ((Dam_SyncedDamageBase)damage).HealthMax;
				}
				catch
				{
				}
				if (mv.HealthMax <= 0.01f)
				{
					try
					{
						mv.HealthMax = ((Dam_SyncedDamageBase)damage).DamageMax;
					}
					catch
					{
					}
				}
				mv.HealthRel = ((mv.HealthMax > 0.01f) ? Mathf.Clamp01(mv.Health / mv.HealthMax) : 0f);
				float num = 0f;
				try
				{
					num = damage.Infection;
				}
				catch
				{
				}
				mv.Infection = Mathf.Clamp01(num);
				mv.HasInfection = num > 0.002f;
			}
			PlayerStamina stamina = a.Stamina;
			if ((Object)(object)stamina != (Object)null)
			{
				mv.HasStamina = true;
				try
				{
					mv.Stamina = stamina.Stamina;
				}
				catch
				{
				}
				try
				{
					mv.StaminaMax = PlayerStamina.MaxStamina;
				}
				catch
				{
				}
				try
				{
					mv.StaminaRel = stamina.StaminaRelative;
				}
				catch
				{
				}
				try
				{
					mv.IsTired = stamina.Tiredness > 0.5f;
				}
				catch
				{
				}
				if (mv.StaminaRel <= 0f && mv.StaminaMax > 0.01f)
				{
					mv.StaminaRel = Mathf.Clamp01(mv.Stamina / mv.StaminaMax);
				}
				if (mv.StaminaMax <= 0.01f && mv.StaminaRel > 0.001f)
				{
					mv.StaminaMax = mv.Stamina / mv.StaminaRel;
				}
				mv.StaminaRel = Mathf.Clamp01(mv.StaminaRel);
				mv.Bpm = Mathf.Clamp(Mathf.Lerp(68f, 168f, 1f - mv.StaminaRel), 55f, 185f);
			}
			SNet_Player val = null;
			try
			{
				val = a.Owner;
			}
			catch
			{
			}
			mv.Player = val;
			if (!((Object)(object)val != (Object)null))
			{
				return;
			}
			try
			{
				mv.IsBot = val.IsBot;
			}
			catch
			{
			}
			PlayerBackpack backpack = GetBackpack(val);
			if (backpack != null)
			{
				PlayerAmmoStorage ammo = null;
				try
				{
					ammo = backpack.AmmoStorage;
				}
				catch
				{
				}
				ReadAmmo(val, ammo, (InventorySlot)1, (AmmoType)0, mv.Standard, mv.IsLocal, isTool: false, mv.SlotIndex);
				ReadAmmo(val, ammo, (InventorySlot)2, (AmmoType)1, mv.Special, mv.IsLocal, isTool: false, mv.SlotIndex);
				ReadAmmo(val, ammo, (InventorySlot)3, (AmmoType)2, mv.Tool, mv.IsLocal, isTool: true, mv.SlotIndex);
				ReadCarry(val, backpack, ammo, mv);
			}
			try
			{
				BackpackItem item = GetItem(val, (InventorySlot)10);
				if (item != null && (Object)(object)item.Instance != (Object)null)
				{
					mv.MeleeName = SafeName(item.Instance);
					MeleeWeaponFirstPerson val2 = ((Il2CppObjectBase)item.Instance).TryCast<MeleeWeaponFirstPerson>();
					if ((Object)(object)val2 != (Object)null)
					{
						ReadMeleeState(val2, mv, mv.IsLocal);
					}
				}
			}
			catch
			{
			}
			if (!mv.Tool.Present)
			{
				return;
			}
			try
			{
				BackpackItem item2 = GetItem(val, (InventorySlot)3);
				ItemEquippable val3 = ((item2 != null && (Object)(object)item2.Instance != (Object)null) ? ((Il2CppObjectBase)item2.Instance).TryCast<ItemEquippable>() : null);
				if ((Object)(object)val3 != (Object)null && val3.IsReloading)
				{
					mv.ToolBusy = true;
					mv.ToolBusyLabel = "装填中";
				}
			}
			catch
			{
			}
		}

		private static void ReadAmmo(SNet_Player p, PlayerAmmoStorage ammo, InventorySlot slot, AmmoType fallbackType, AmmoView v, bool preferItem, bool isTool, int ownerSlot)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			AmmoType val = fallbackType;
			try
			{
				val = PlayerAmmoStorage.GetAmmoTypeFromSlot(slot);
			}
			catch
			{
			}
			v.Name = null;
			v.Clip = -1;
			v.Pack = 0;
			v.PackMax = 0;
			v.ClipMax = -1;
			v.Present = false;
			v.Tool = isTool;
			v.OwnerSlot = ownerSlot;
			int num = -1;
			BackpackItem item = GetItem(p, slot);
			if (item != null && (Object)(object)item.Instance != (Object)null)
			{
				v.Present = true;
				v.Name = SafeName(item.Instance);
				try
				{
					ItemEquippable val2 = ((Il2CppObjectBase)item.Instance).TryCast<ItemEquippable>();
					if ((Object)(object)val2 != (Object)null)
					{
						num = val2.GetCurrentClip();
						v.ClipMax = val2.GetMaxClip();
					}
				}
				catch
				{
				}
			}
			int num2 = -1;
			if (ammo != null)
			{
				try
				{
					num2 = Mathf.Max(0, Mathf.RoundToInt(ammo.GetClipAmmoFromSlot(slot)));
				}
				catch
				{
				}
			}
			v.Clip = ((!preferItem) ? ((num2 >= 0) ? num2 : num) : ((num >= 0) ? num : num2));
			if (ammo == null)
			{
				return;
			}
			InventorySlotAmmo val3 = null;
			try
			{
				val3 = ammo.GetInventorySlotAmmo(val);
			}
			catch
			{
			}
			if (isTool)
			{
				v.Clip = -1;
				v.ClipMax = 0;
				ItemEquippable val4 = null;
				try
				{
					val4 = ((item != null && (Object)(object)item.Instance != (Object)null) ? ((Il2CppObjectBase)item.Instance).TryCast<ItemEquippable>() : null);
				}
				catch
				{
				}
				string text = null;
				try
				{
					text = ((item != null && (Object)(object)item.Instance != (Object)null) ? SafeName(item.Instance) : null);
				}
				catch
				{
				}
				EnemyScanner val5 = ((item != null && (Object)(object)item.Instance != (Object)null) ? ((Il2CppObjectBase)item.Instance).TryCast<EnemyScanner>() : null);
				if ((Object)(object)val5 != (Object)null)
				{
					v.Present = true;
					v.NoAmmo = true;
					if (!string.IsNullOrEmpty(text) && s_scannerModels.Add(text))
					{
						SaveSentryMemory();
					}
					bool flag = preferItem;
					if (!flag)
					{
						try
						{
							flag = Plugin.Settings?.RemoteScannerPhase.Value ?? false;
						}
						catch
						{
						}
					}
					if (flag)
					{
						ReadScanner(val5, v);
						return;
					}
					v.PhaseText = "—";
					v.PhaseRel = 0f;
					return;
				}
				if (!string.IsNullOrEmpty(text) && s_scannerModels.Contains(text))
				{
					v.Present = true;
					v.NoAmmo = true;
					v.PhaseText = "—";
					v.PhaseRel = -1f;
					return;
				}
				try
				{
					PlayerBackpack value = null;
					if (v.OwnerSlot >= 0 && !s_backpackBySlot.TryGetValue(v.OwnerSlot, out value))
					{
						try
						{
							value = PlayerBackpackManager.GetBackpack(p);
						}
						catch
						{
						}
						if (value != null)
						{
							s_backpackBySlot[v.OwnerSlot] = value;
						}
					}
					if (value != null && v.OwnerSlot >= 0)
					{
						if (!s_deployedCheckedAt.TryGetValue(v.OwnerSlot, out var value2))
						{
							value2 = -999f;
						}
						float unscaledTime = Time.unscaledTime;
						if (unscaledTime - value2 > 0.2f)
						{
							s_deployedCheckedAt[v.OwnerSlot] = unscaledTime;
							try
							{
								if (value.IsDeployed((InventorySlot)3))
								{
									s_deployedSlots[v.OwnerSlot] = text ?? "";
								}
							}
							catch
							{
							}
						}
					}
				}
				catch
				{
				}
				PlacedSentry value3;
				bool flag2 = s_scanPlaced.TryGetValue(v.OwnerSlot, out value3);
				if (!flag2 && !string.IsNullOrEmpty(text))
				{
					flag2 = s_scanByModel.TryGetValue(text, out value3);
				}
				if (flag2)
				{
					v.Present = true;
					v.Tool = true;
					v.PhaseRel = ((value3.Max > 0 && value3.Cur >= 0) ? Mathf.Clamp01((float)value3.Cur / (float)value3.Max) : (-1f));
					v.Pack = value3.Cur;
					v.PackMax = value3.Max;
					v.PhaseText = "炮台 " + ((value3.Cur >= 0) ? value3.Cur.ToString() : "--") + ((value3.Max > 0) ? ("/" + value3.Max) : "");
					return;
				}
				if (!string.IsNullOrEmpty(text) && s_sentryModels.Contains(text))
				{
					float num3 = -1f;
					float num4 = -1f;
					try
					{
						if (val3 != null)
						{
							num3 = val3.AmmoInPack;
							num4 = val3.AmmoMaxCap;
						}
					}
					catch
					{
					}
					if (s_sentryCostByName.TryGetValue(text, out var value4) && value4 > 0.0001f && num3 >= 0f)
					{
						int num5 = Mathf.Max(0, Mathf.FloorToInt(num3 / value4));
						int num6 = ((num4 >= 0f) ? Mathf.Max(num5, Mathf.FloorToInt(num4 / value4)) : (-1));
						v.Present = true;
						v.Tool = true;
						v.PhaseRel = ((num6 > 0) ? Mathf.Clamp01((float)num5 / (float)num6) : (-1f));
						v.Pack = num5;
						v.PackMax = num6;
						v.PhaseText = "炮台 " + num5 + ((num6 > 0) ? ("/" + num6) : "");
						return;
					}
				}
				SentryGunFirstPerson val6 = null;
				try
				{
					val6 = ((item != null && (Object)(object)item.Instance != (Object)null) ? ((Il2CppObjectBase)item.Instance).TryCast<SentryGunFirstPerson>() : null);
				}
				catch
				{
				}
				if ((Object)(object)val6 != (Object)null)
				{
					int num7 = -1;
					try
					{
						num7 = ((ItemEquippable)val6).GetCurrentClip();
					}
					catch
					{
					}
					int num8 = -1;
					if (!string.IsNullOrEmpty(text))
					{
						float num9 = -1f;
						try
						{
							if (val3 != null)
							{
								num9 = val3.AmmoMaxCap;
							}
						}
						catch
						{
						}
						if (s_sentryCostByName.TryGetValue(text, out var value5) && value5 > 0.0001f && num9 > 0f)
						{
							num8 = Mathf.FloorToInt(num9 / value5);
						}
					}
					if (num7 >= 0)
					{
						v.Present = true;
						v.Tool = true;
						v.PhaseRel = ((num8 > 0) ? Mathf.Clamp01((float)num7 / (float)num8) : (-1f));
						v.Pack = num7;
						v.PackMax = num8;
						v.PhaseText = "炮台 " + num7 + ((num8 > 0) ? ("/" + num8) : "");
						return;
					}
				}
				bool flag3 = false;
				float num10 = -1f;
				try
				{
					ArchetypeDataBlock val7 = (((Object)(object)val4 != (Object)null) ? val4.ArchetypeData : null);
					if (val7 != null && val7.CostOfBullet > 0.0001f)
					{
						num10 = val7.CostOfBullet;
					}
				}
				catch
				{
				}
				if (flag3)
				{
					float num11 = -1f;
					float num12 = -1f;
					try
					{
						SentryGunInstance val8 = ((Il2CppObjectBase)item.Instance).TryCast<SentryGunInstance>();
						if ((Object)(object)val8 != (Object)null)
						{
							num11 = val8.Ammo;
							num12 = val8.AmmoMaxCap;
						}
					}
					catch
					{
					}
					if (num11 < 0f && val3 != null)
					{
						num11 = val3.AmmoInPack;
						num12 = val3.AmmoMaxCap;
					}
					float num13 = -1f;
					try
					{
						SentryGunInstance val9 = ((Il2CppObjectBase)item.Instance).TryCast<SentryGunInstance>();
						if ((Object)(object)val9 != (Object)null && val9.CostOfBullet > 0.0001f)
						{
							num13 = val9.CostOfBullet;
						}
					}
					catch
					{
					}
					if (num13 <= 0.0001f)
					{
						try
						{
							string text2 = SafeName(item.Instance);
							if (!string.IsNullOrEmpty(text2) && s_sentryCostByName.TryGetValue(text2, out var value6) && value6 > 0.0001f)
							{
								num13 = value6;
							}
						}
						catch
						{
						}
					}
					if (num13 <= 0.0001f && (Object)(object)val4 != (Object)null)
					{
						try
						{
							ArchetypeDataBlock archetypeData = val4.ArchetypeData;
							if (archetypeData != null)
							{
								float sentryCostOfBullet = archetypeData.GetSentryCostOfBullet(false);
								if (sentryCostOfBullet > 0.0001f)
								{
									num13 = sentryCostOfBullet;
								}
							}
						}
						catch
						{
						}
					}
					if (num13 <= 0.0001f)
					{
						num13 = num10;
					}
					if (num13 <= 0.0001f)
					{
						num13 = 1f;
					}
					v.Present = true;
					v.PhaseRel = -1f;
					int num14 = Mathf.Max(0, Mathf.FloorToInt(((num11 < 0f) ? 0f : num11) / num13));
					int packMax = Mathf.Max(num14, Mathf.FloorToInt(((num12 < 0f) ? 0f : num12) / num13));
					v.Pack = num14;
					v.PackMax = packMax;
					v.PhaseText = "炮台 " + num14 + "/" + packMax;
					return;
				}
				int num15 = -1;
				int packMax2 = -1;
				try
				{
					ItemEquippable val10 = ((item != null && (Object)(object)item.Instance != (Object)null) ? ((Il2CppObjectBase)item.Instance).TryCast<ItemEquippable>() : null);
					if ((Object)(object)val10 != (Object)null && (Object)(object)p != (Object)null)
					{
						num15 = val10.GetClassAmmoInPackAbs(p);
						packMax2 = val10.GetClassAmmoMaxCap(p);
					}
				}
				catch
				{
				}
				if (num15 >= 0)
				{
					v.Pack = num15;
					v.PackMax = packMax2;
				}
				else if (val3 != null)
				{
					if (val3.BulletsMaxCap > 0)
					{
						v.Pack = val3.BulletsInPack;
						v.PackMax = val3.BulletsMaxCap;
					}
					else
					{
						v.Pack = Mathf.RoundToInt(val3.AmmoInPack);
						v.PackMax = Mathf.RoundToInt(val3.AmmoMaxCap);
					}
				}
				if (!v.Present && val3 != null)
				{
					v.Present = val3.AmmoMaxCap > 0f || val3.BulletsMaxCap > 0;
				}
				return;
			}
			try
			{
				if (val3 != null)
				{
					if (val3.BulletsMaxCap > 0)
					{
						v.Pack = val3.BulletsInPack;
						v.PackMax = val3.BulletsMaxCap;
					}
					else
					{
						v.Pack = Mathf.RoundToInt(val3.AmmoInPack);
						v.PackMax = Mathf.RoundToInt(val3.AmmoMaxCap);
					}
					if (v.ClipMax < 0)
					{
						v.ClipMax = val3.BulletClipSize;
					}
					try
					{
						v.RelPercent = val3.RelInPack;
					}
					catch
					{
					}
					v.Present |= val3.BulletClipSize > 0 || v.PackMax > 0 || val3.AmmoInPack > 0f;
				}
			}
			catch
			{
			}
		}

		private static void ReadScanner(EnemyScanner sc, AmmoView v)
		{
			bool flag = false;
			bool flag2 = false;
			try
			{
				flag = sc.m_tagging;
			}
			catch
			{
			}
			try
			{
				flag2 = sc.m_recharging;
			}
			catch
			{
			}
			float time = Time.time;
			float num = 0f;
			try
			{
				num = EnemyScanner.TagDuration;
			}
			catch
			{
			}
			float num2 = 0f;
			try
			{
				num2 = sc.m_tagStartTime;
			}
			catch
			{
			}
			float num3 = 0f;
			try
			{
				num3 = sc.m_rechargeDuration;
			}
			catch
			{
			}
			float num4 = 0f;
			try
			{
				num4 = sc.m_rechargeStartTime;
			}
			catch
			{
			}
			if (flag)
			{
				float num5 = time - num2;
				if (num <= 0.01f || num5 <= num + 0.75f)
				{
					if (num > 0.01f)
					{
						v.PhaseRel = Mathf.Clamp01(num5 / num);
						v.PhaseText = "准备 " + Mathf.RoundToInt(v.PhaseRel * 100f) + "%";
					}
					else
					{
						v.PhaseRel = -1f;
						v.PhaseText = "准备";
					}
					return;
				}
			}
			float num6 = num3 - (time - num4);
			if (flag2 && num3 > 0.01f && num6 > 0f)
			{
				v.PhaseRel = Mathf.Clamp01(1f - num6 / num3);
				v.PhaseWarn = true;
				int num7 = Mathf.RoundToInt(num6 * 10f);
				v.PhaseText = "冷却 " + num7 / 10 + "." + num7 % 10 + "s";
			}
			else
			{
				v.PhaseRel = 1f;
				v.PhaseReady = true;
				v.PhaseText = "就绪";
			}
		}

		private static string F(float v)
		{
			return v.ToString("0.###", CultureInfo.InvariantCulture);
		}

		private static string DumpSlot(SNet_Player p, PlayerAmmoStorage ammo, InventorySlot slot)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: 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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_0186: 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_01bc: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			if (ammo == null)
			{
				return "no-ammo";
			}
			AmmoType val = (AmmoType)4;
			try
			{
				val = PlayerAmmoStorage.GetAmmoTypeFromSlot(slot);
			}
			catch
			{
			}
			stringBuilder.Append("type=").Append(val);
			try
			{
				InventorySlotAmmo inventorySlotAmmo = ammo.GetInventorySlotAmmo(val);
				if (inventorySlotAmmo == null)
				{
					stringBuilder.Append(" isa=-");
				}
				else
				{
					stringBuilder.Append(" pack=").Append(F(inventorySlotAmmo.AmmoInPack)).Append(" cap=")
						.Append(F(inventorySlotAmmo.AmmoMaxCap))
						.Append(" blt=")
						.Append(inventorySlotAmmo.BulletsInPack)
						.Append(" bltCap=")
						.Append(inventorySlotAmmo.BulletsMaxCap)
						.Append(" clipSize=")
						.Append(inventorySlotAmmo.BulletClipSize)
						.Append(" cost=")
						.Append(F(inventorySlotAmmo.CostOfBullet))
						.Append(" conv=")
						.Append(F(inventorySlotAmmo.BulletsToRelConv))
						.Append(" rel=")
						.Append(F(inventorySlotAmmo.RelInPack))
						.Append(" full=")
						.Append(inventorySlotAmmo.IsFull);
				}
			}
			catch (Exception ex)
			{
				stringBuilder.Append(" isaERR=").Append(ex.GetType().Name);
			}
			try
			{
				stringBuilder.Append(" clipAbs=").Append(F(ammo.GetClipAmmoFromSlot(slot)));
			}
			catch
			{
			}
			try
			{
				stringBuilder.Append(" getPack=").Append(F(ammo.GetAmmoInPack(val)));
			}
			catch
			{
			}
			try
			{
				stringBuilder.Append(" getBlt=").Append(ammo.GetBulletsInPack(val)).Append('/')
					.Append(ammo.GetBulletMaxCap(val));
			}
			catch
			{
			}
			BackpackItem item = GetItem(p, slot);
			Item val2 = ((item != null) ? item.Instance : null);
			if ((Object)(object)val2 == (Object)null)
			{
				stringBuilder.Append(" item=-");
				return stringBuilder.ToString();
			}
			stringBuilder.Append(" item=").Append(SafeName(val2));
			try
			{
				stringBuilder.Append("(").Append(((object)val2).GetType().Name).Append(")");
			}
			catch
			{
			}
			try
			{
				SentryGunInstance val3 = ((Il2CppObjectBase)val2).TryCast<SentryGunInstance>();
				if ((Object)(object)val3 != (Object)null)
				{
					stringBuilder.Append(" SENTRY ammo=").Append(F(val3.Ammo)).Append('/')
						.Append(F(val3.AmmoMaxCap))
						.Append(" cost=")
						.Append(F(val3.CostOfBullet))
						.Append(" rounds=")
						.Append(F((val3.CostOfBullet > 0.0001f) ? (val3.Ammo / val3.CostOfBullet) : val3.Ammo))
						.Append('/')
						.Append(F((val3.CostOfBullet > 0.0001f) ? (val3.AmmoMaxCap / val3.CostOfBullet) : val3.AmmoMaxCap))
						.Append(" clip=")
						.Append(((ItemEquippable)val3).GetCurrentClip())
						.Append(" clipRel=")
						.Append(F(((ItemEquippable)val3).GetCurrentClipRel()))
						.Append(" firing=")
						.Append(val3.m_isFiring);
				}
			}
			catch
			{
			}
			try
			{
				ItemEquippable val4 = ((Il2CppObjectBase)val2).TryCast<ItemEquippable>();
				if ((Object)(object)val4 != (Object)null)
				{
					try
					{
						ArchetypeDataBlock archetypeData = val4.ArchetypeData;
						if (archetypeData != null)
						{
							stringBuilder.Append(" ARCH cost=").Append(F(archetypeData.CostOfBullet)).Append(" clip=")
								.Append(archetypeData.DefaultClipSize)
								.Append(" sRange=")
								.Append(F(archetypeData.Sentry_DetectionMaxRange))
								.Append(" sAngle=")
								.Append(F(archetypeData.Sentry_DetectionMaxAngle));
							try
							{
								stringBuilder.Append(" sentryCost(false)=").Append(F(archetypeData.GetSentryCostOfBullet(false)));
							}
							catch
							{
							}
							try
							{
								stringBuilder.Append(" sentryCost(true)=").Append(F(archetypeData.GetSentryCostOfBullet(true)));
							}
							catch
							{
							}
						}
						string text = SafeName(val2);
						if (!string.IsNullOrEmpty(text) && s_sentryCostByName.TryGetValue(text, out var value))
						{
							stringBuilder.Append(" CACHE_NAME=").Append(F(value));
						}
						try
						{
							ItemEquippable val5 = ((Il2CppObjectBase)val2).TryCast<ItemEquippable>();
							if ((Object)(object)val5 != (Object)null && val5.ArchetypeData != null)
							{
								stringBuilder.Append(" ARCHKEY_HAND=[").Append(ArchKey(val5.ArchetypeData)).Append(']');
							}
						}
						catch
						{
						}
					}
					catch
					{
					}
					stringBuilder.Append(" itemClip=").Append(val4.GetCurrentClip()).Append('/')
						.Append(val4.GetMaxClip());
					try
					{
						stringBuilder.Append(" classAbs=").Append(val4.GetClassAmmoInPackAbs(p)).Append('/')
							.Append(val4.GetClassAmmoMaxCap(p));
					}
					catch
					{
					}
				}
			}
			catch
			{
			}
			try
			{
				EnemyScanner val6 = ((Il2CppObjectBase)val2).TryCast<EnemyScanner>();
				if ((Object)(object)val6 != (Object)null)
				{
					stringBuilder.Append(" SCANNER tag=").Append(val6.m_tagging).Append(" rech=")
						.Append(val6.m_recharging)
						.Append(" tagStart=")
						.Append(F(val6.m_tagStartTime))
						.Append(" lock=")
						.Append(F(val6.m_lockTimer))
						.Append(" scanTimer=")
						.Append(F(val6.m_scanTimer))
						.Append(" scanDelay=")
						.Append(F(val6.m_scanDelay))
						.Append(" rechStart=")
						.Append(F(val6.m_rechargeStartTime))
						.Append(" rechDur=")
						.Append(F(val6.m_rechargeDuration))
						.Append(" TagDur=")
						.Append(F(EnemyScanner.TagDuration));
				}
				else
				{
					stringBuilder.Append(" CASTS[");
					try
					{
						if ((Object)(object)((Il2CppObjectBase)val2).TryCast<EnemyScanner>() != (Object)null)
						{
							stringBuilder.Append("EnemyScanner ");
						}
					}
					catch
					{
					}
					try
					{
						if ((Object)(object)((Il2CppObjectBase)val2).TryCast<SentryGunFirstPerson>() != (Object)null)
						{
							stringBuilder.Append("SentryGunFirstPerson ");
						}
					}
					catch
					{
					}
					try
					{
						if ((Object)(object)((Il2CppObjectBase)val2).TryCast<SentryGunInstance>() != (Object)null)
						{
							stringBuilder.Append("SentryGunInstance ");
						}
					}
					catch
					{
					}
					try
					{
						if ((Object)(object)((Il2CppObjectBase)val2).TryCast<MineDeployerInstance>() != (Object)null)
						{
							stringBuilder.Append("MineDeployerInstance ");
						}
					}
					catch
					{
					}
					try
					{
						if ((Object)(object)((Il2CppObjectBase)val2).TryCast<ItemEquippable>() != (Object)null)
						{
							stringBuilder.Append("ItemEquippable ");
						}
					}
					catch
					{
					}
					stringBuilder.Append(']');
				}
			}
			catch
			{
			}
			return stringBuilder.ToString();
		}

		private static void DumpAmmo()
		{
			try
			{
				HudSettings settings = Plugin.Settings;
				if (settings == null || !settings.AmmoDump.Value)
				{
					return;
				}
				float unscaledTime = Time.unscaledTime;
				if (unscaledTime - s_lastDump < 1f)
				{
					return;
				}
				s_lastDump = unscaledTime;
				for (int i = 0; i < Members.Count; i++)
				{
					MemberView memberView = Members[i];
					SNet_Player player = memberView.Player;
					if ((Object)(object)player == (Object)null)
					{
						Plugin.LogSource.LogInfo((object)("[ammo] " + memberView.Name + " no SNet_Player"));
						continue;
					}
					PlayerBackpack backpack = GetBackpack(player);
					PlayerAmmoStorage ammo = ((backpack != null) ? backpack.AmmoStorage : null);
					string text = "";
					try
					{
						text = ((backpack == null) ? " DEPLOYED[bp=null]" : (" DEPLOYED[isDeployed=" + backpack.IsDeployed((InventorySlot)3) + "]"));
					}
					catch (Exception ex)
					{
						text = " DEPLOYED[err:" + ex.GetType().Name + "]";
					}
					Plugin.LogSource.LogInfo((object)("[ammo] t=" + F(Time.time) + " " + memberView.Name + " slot=" + memberView.SlotIndex + (memberView.IsLocal ? " LOCAL" : "") + text + " || STD " + DumpSlot(player, ammo, (InventorySlot)1) + " || SPC " + DumpSlot(player, ammo, (InventorySlot)2) + " || TOL " + DumpSlot(player, ammo, (InventorySlot)3)));
				}
			}
			catch (Exception ex2)
			{
				Plugin.LogSource.LogWarning((object)("[ammo] dump failed: " + ex2.Message));
			}
		}

		private static void ReadCarry(SNet_Player p, PlayerBackpack bp, PlayerAmmoStorage ammo, MemberView mv)
		{
			mv.Carry.Clear();
			AddCarry(p, ammo, (InventorySlot)4, (AmmoType)3, mv);
			AddCarry(p, ammo, (InventorySlot)5, (AmmoType)5, mv);
			AddCarry(p, ammo, (InventorySlot)6, (AmmoType)5, mv);
			mv.Pocket.Clear();
			try
			{
				List<List<PocketItem>> pocketItemsGroups = bp.PocketItemsGroups;
				if (pocketItemsGroups == null)
				{
					return;
				}
				for (int i = 0; i < pocketItemsGroups.Count; i++)
				{
					List<PocketItem> val = pocketItemsGroups[i];
					if (val != null && val.Count != 0)
					{
						uint id = 0u;
						try
						{
							id = val[0].itemID;
						}
						catch
						{
						}
						mv.Pocket.Add(new GearView
						{
							Name = ItemName(id),
							Amount = val.Count
						});
					}
				}
			}
			catch
			{
			}
		}

		private static void AddCarry(SNet_Player p, PlayerAmmoStorage ammo, InventorySlot slot, AmmoType type, MemberView mv)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			BackpackItem item = GetItem(p, slot);
			if (item == null || (Object)(object)item.Instance == (Object)null)
			{
				return;
			}
			Item instance = item.Instance;
			GearView gearView = new GearView();
			gearView.Name = SafeName(instance);
			try
			{
				ResourcePackFirstPerson val = ((Il2CppObjectBase)instance).TryCast<ResourcePackFirstPerson>();
				if ((Object)(object)val != (Object)null)
				{
					gearView.IsResourcePack = true;
					gearView.Name = PackKindName(val.m_packType);
				}
			}
			catch
			{
			}
			if (ammo != null)
			{
				try
				{
					InventorySlotAmmo inventorySlotAmmo = ammo.GetInventorySlotAmmo(type);
					if (inventorySlotAmmo != null)
					{
						gearView.Amount = ((inventorySlotAmmo.BulletsInPack > 0) ? inventorySlotAmmo.BulletsInPack : Mathf.RoundToInt(inventorySlotAmmo.AmmoInPack));
						gearView.AmountMax = ((inventorySlotAmmo.BulletsMaxCap > 0) ? inventorySlotAmmo.BulletsMaxCap : Mathf.RoundToInt(inventorySlotAmmo.AmmoMaxCap));
					}
				}
				catch
				{
				}
			}
			mv.Carry.Add(gearView);
		}

		private unsafe static void ReadMeleeState(MeleeWeaponFirstPerson mwf, MemberView mv, bool local)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			eMeleeWeaponState currentStateName;
			try
			{
				currentStateName = mwf.CurrentStateName;
			}
			catch
			{
				return;
			}
			mv.MeleeState = ((object)(*(eMeleeWeaponState*)(&currentStateName))/*cast due to .constrained prefix*/).ToString();
			mv.MeleeCharging = IsChargeState(currentStateName);
			try
			{
				MWS_Base currentState = mwf.CurrentState;
				MWS_ChargeUp val = ((currentState != null) ? ((Il2CppObjectBase)currentState).TryCast<MWS_ChargeUp>() : null);
				if (val == null)
				{
					mv.MeleeChargeRel = 0f;
					return;
				}
				float maxDamageTime = val.m_maxDamageTime;
				float elapsed = val.m_elapsed;
				float num = ((!(maxDamageTime > 0.01f)) ? val.m_animTimeRel : (elapsed / maxDamageTime));
				mv.MeleeChargeRel = Mathf.Clamp01(num);
				mv.MeleeChargeElapsed = elapsed;
				float value;
				if (maxDamageTime > 0.01f)
				{
					s_lastMeleeNeed[mv.SlotIndex] = maxDamageTime;
					mv.MeleeChargeSeconds = maxDamageTime;
					mv.MeleeChargeNeed = maxDamageTime;
				}
				else if (s_lastMeleeNeed.TryGetValue(mv.SlotIndex, out value))
				{
					mv.MeleeChargeNeed = value;
				}
			}
			catch
			{
				mv.MeleeChargeRel = 0f;
			}
		}

		private static bool IsChargeState(eMeleeWeaponState s)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if ((int)s != 7 && (int)s != 9 && (int)s != 8 && (int)s != 10 && (int)s != 11)
			{
				return (int)s == 12;
			}
			return true;
		}

		private static PlayerBackpack GetBackpack(SNet_Player p)
		{
			if ((Object)(object)p == (Object)null)
			{
				return null;
			}
			try
			{
				PlayerBackpack backpack = PlayerBackpackManager.GetBackpack(p);
				if (backpack != null)
				{
					return backpack;
				}
			}
			catch
			{
			}
			try
			{
				return PlayerBackpackManager.GetLocalOrSyncBackpack(p);
			}
			catch
			{
				return null;
			}
		}

		private static BackpackItem GetItem(SNet_Player p, InventorySlot slot)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)p == (Object)null)
			{
				return null;
			}
			try
			{
				return PlayerBackpackManager.GetItem(p, slot);
			}
			catch
			{
				return null;
			}
		}

		private static string SafeName(Item inst)
		{
			if ((Object)(object)inst == (Object)null)
			{
				return null;
			}
			try
			{
				string publicName = inst.PublicName;
				if (!string.IsNullOrEmpty(publicName))
				{
					return publicName;
				}
			}
			catch
			{
			}
			try
			{
				string archetypeName = inst.ArchetypeName;
				if (!string.IsNullOrEmpty(archetypeName))
				{
					return archetypeName;
				}
			}
			catch
			{
			}
			try
			{
				ItemDataBlock itemDataBlock = inst.ItemDataBlock;
				if (itemDataBlock != null)
				{
					string name = itemDataBlock.GetName();
					if (!string.IsNullOrEmpty(name))
					{
						return name;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		private unsafe static string PackKindName(eResourceContainerSpawnType t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected I4, but got Unknown
			return (int)t switch
			{
				0 => "医疗包", 
				1 => "弹药包", 
				2 => "工具包", 
				9 => "消毒包", 
				6 => "消耗品", 
				3 => "物资(小)", 
				4 => "物资(中)", 
				5 => "物资(大)", 
				7 => "钥匙卡", 
				10 => "神器", 
				_ => ((object)(*(eResourceContainerSpawnType*)(&t))/*cast due to .constrained prefix*/).ToString(), 
			};
		}

		private static string ItemName(uint id)
		{
			try
			{
				HudSettings settings = Plugin.Settings;
				if (settings != null && !settings.ShowPocket.Value)
				{
					return "#" + id;
				}
				if (s_itemNameCache.TryGetValue(id, out var value))
				{
					return value;
				}
				string text = null;
				try
				{
					Dictionary<uint, ItemDataBlock> s_blockByID = GameDataBlockBase<ItemDataBlock>.s_blockByID;
					ItemDataBlock val = default(ItemDataBlock);
					if (s_blockByID != null && s_blockByID.TryGetValue(id, ref val) && val != null)
					{
						try
						{
							text = val.publicName;
						}
						catch
						{
						}
						if (string.IsNullOrEmpty(text))
						{
							try
							{
								text = val.GetName();
							}
							catch
							{
							}
						}
					}
				}
				catch
				{
				}
				if (!string.IsNullOrEmpty(text))
				{
					s_itemNameCache[id] = text;
					return text;
				}
				return "#" + id;
			}
			catch
			{
				return "#" + id;
			}
		}

		private static void Probe()
		{
			try
			{
				HudSettings settings = Plugin.Settings;
				if (settings == null || !settings.ProbeLog.Value)
				{
					return;
				}
				float unscaledTime = Time.unscaledTime;
				if (unscaledTime - s_lastProbe < 1f)
				{
					return;
				}
				s_lastProbe = unscaledTime;
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("[probe] inLevel=").Append(InLevel).Append(" members=")
					.Append(Members.Count);
				for (int i = 0; i < Members.Count; i++)
				{
					MemberView memberView = Members[i];
					stringBuilder.Append(" | ").Append(memberView.Name).Append(" slot=")
						.Append(memberView.SlotIndex)
						.Append(memberView.IsLocal ? " local" : "")
						.Append(" hp=")
						.Append(Mathf.RoundToInt(memberView.Health))
						.Append("/")
						.Append(Mathf.RoundToInt(memberView.HealthMax))
						.Append(" inf=")
						.Append(Mathf.RoundToInt(memberView.Infection * 100f));
					if (memberView.HasStamina)
					{
						stringBuilder.Append(" sta=").Append(Mathf.RoundToInt(memberView.StaminaRel * 100f));
					}
					stringBuilder.Append(" std=").Append(memberView.Standard.Clip).Append("/")
						.Append(memberView.Standard.Pack)
						.Append("/")
						.Append(memberView.Standard.PackMax)
						.Append(" spc=")
						.Append(memberView.Special.Clip)
						.Append("/")
						.Append(memberView.Special.Pack)
						.Append("/")
						.Append(memberView.Special.PackMax)
						.Append(" tol=")
						.Append(memberView.Tool.Clip)
						.Append("/")
						.Append(memberView.Tool.Pack)
						.Append("/")
						.Append(memberView.Tool.PackMax)
						.Append(" melee=")
						.Append(memberView.MeleeName ?? "-")
						.Append(" carry=")
						.Append(memberView.Carry.Count)
						.Append(" pocket=")
						.Append(memberView.Pocket.Count);
					if (memberView.Error != null)
					{
						stringBuilder.Append(" ERR=").Append(memberView.Error);
					}
				}
				if (LastError != null)
				{
					stringBuilder.Append(" ROOTERR=").Append(LastError);
				}
				Plugin.LogSource.LogInfo((object)stringBuilder.ToString());
			}
			catch
			{
			}
		}
	}
}