Decompiled source of MonsterHealthBars v1.0.0

MonsterHealthBars.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MonsterHealthBars")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MonsterHealthBars")]
[assembly: AssemblyTitle("MonsterHealthBars")]
[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 MonsterHealthBars
{
	internal class BarsOverlay : MonoBehaviour
	{
		private class Entry
		{
			public EnemyParent parent;

			public Enemy enemy;

			public EnemyHealth health;

			public int viewId;

			public Collider[] colliders;

			public Renderer[] renderers;

			public float lastHitTime;

			public float alpha;

			public int lastSentHp = int.MinValue;

			public float lastSendTime = -999f;

			public Bar bar;
		}

		private class Bar
		{
			public GameObject root;

			public RectTransform rect;

			public CanvasGroup group;

			public Image back;

			public Image fill;

			public RectTransform fillRect;

			public TextMeshProUGUI label;

			private float _shownFill = -1f;

			private float _appliedWidth = -1f;

			private Color _lastColor;

			private string _lastText;

			public void Show(Vector2 anchoredPosition, float scale, float alpha, float fillTarget, float barWidth, float barHeight, Color color, string text, float dt)
			{
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0110: Unknown result type (might be due to invalid IL or missing references)
				//IL_011a: Unknown result type (might be due to invalid IL or missing references)
				//IL_011d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00da: Unknown result type (might be due to invalid IL or missing references)
				//IL_012a: Unknown result type (might be due to invalid IL or missing references)
				//IL_012c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0137: Unknown result type (might be due to invalid IL or missing references)
				if (!root.activeSelf)
				{
					root.SetActive(true);
				}
				rect.anchoredPosition = anchoredPosition;
				((Transform)rect).localScale = new Vector3(scale, scale, 1f);
				rect.sizeDelta = new Vector2(barWidth, barHeight);
				group.alpha = alpha;
				if (_shownFill < 0f)
				{
					_shownFill = fillTarget;
				}
				else
				{
					float num = 1f - Mathf.Exp(-14f * dt);
					_shownFill = Mathf.Lerp(_shownFill, fillTarget, num);
					if (Mathf.Abs(_shownFill - fillTarget) < 0.002f)
					{
						_shownFill = fillTarget;
					}
				}
				if (_appliedWidth < 0f || !Mathf.Approximately(barWidth, _appliedWidth) || !Mathf.Approximately(fillRect.sizeDelta.x, barWidth * _shownFill))
				{
					_appliedWidth = barWidth;
					fillRect.sizeDelta = new Vector2(barWidth * _shownFill, 0f);
				}
				if (color != _lastColor)
				{
					_lastColor = color;
					((Graphic)fill).color = color;
				}
				if (text != _lastText)
				{
					_lastText = text;
					((TMP_Text)label).text = text ?? string.Empty;
					((Component)label).gameObject.SetActive(!string.IsNullOrEmpty(text));
				}
			}

			public void Hide()
			{
				if (root.activeSelf)
				{
					root.SetActive(false);
				}
				_shownFill = -1f;
				_appliedWidth = -1f;
			}

			public void Destroy()
			{
				if ((Object)(object)root != (Object)null)
				{
					Object.Destroy((Object)(object)root);
				}
			}
		}

		private class Popup
		{
			public GameObject go;

			public RectTransform rect;

			public TextMeshProUGUI text;

			public Vector3 world;

			public Vector2 screenOffset;

			public float rise;

			public float riseCurrent;

			public float age;

			public float life;
		}

		private const float RescanInterval = 0.5f;

		private const float FadeInTime = 0.12f;

		private const float FillSmoothing = 14f;

		private const float PopupFadeIn = 0.15f;

		private const float PopupFadeOut = 0.5f;

		private Camera _cam;

		private Canvas _canvas;

		private RectTransform _canvasRect;

		private Sprite _whiteSprite;

		private readonly List<Entry> _entries = new List<Entry>();

		private readonly List<Popup> _popups = new List<Popup>();

		private float _rescanTimer;

		private TMP_FontAsset _font;

		private int _popupCounter;

		internal static BarsOverlay Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			BuildCanvas();
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			if ((Object)(object)_canvas != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_canvas).gameObject);
			}
		}

		private void OnEnable()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			Application.onBeforeRender += new UnityAction(RepositionOnly);
		}

		private void OnDisable()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			Application.onBeforeRender -= new UnityAction(RepositionOnly);
		}

		private void RepositionOnly()
		{
			//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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: 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)
			if ((Object)(object)_cam == (Object)null || (_entries.Count == 0 && _popups.Count == 0))
			{
				return;
			}
			float value = MonsterHealthBarsPlugin.BarYOffset.Value;
			float depth;
			for (int i = 0; i < _entries.Count; i++)
			{
				Entry entry = _entries[i];
				if (entry.bar != null && entry.bar.root.activeSelf && !((Object)(object)entry.parent == (Object)null) && !((Object)(object)entry.health == (Object)null))
				{
					Vector3 world = GetTopPoint(entry) + Vector3.up * value;
					if (Project(world, out var screen, out depth))
					{
						entry.bar.rect.anchoredPosition = ToCanvas(screen);
					}
				}
			}
			for (int j = 0; j < _popups.Count; j++)
			{
				Popup popup = _popups[j];
				if (!((Object)(object)popup.go == (Object)null) && popup.go.activeSelf && Project(popup.world, out var screen2, out depth))
				{
					popup.rect.anchoredPosition = ToCanvas(screen2) + popup.screenOffset + new Vector2(0f, popup.riseCurrent);
				}
			}
		}

		private void BuildCanvas()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("MonsterHealthBars_Canvas", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(((Component)this).transform, false);
			_canvas = val.AddComponent<Canvas>();
			_canvas.renderMode = (RenderMode)0;
			_canvas.sortingOrder = 30000;
			_canvas.pixelPerfect = false;
			CanvasScaler obj = val.AddComponent<CanvasScaler>();
			obj.uiScaleMode = (ScaleMode)0;
			obj.scaleFactor = 1f;
			_canvasRect = (RectTransform)val.transform;
			_whiteSprite = Sprite.Create(Texture2D.whiteTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
			((Object)_whiteSprite).name = "MHB_White";
		}

		private void LateUpdate()
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Invalid comparison between Unknown and I4
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			float num = Mathf.Min(Time.unscaledDeltaTime, 0.1f);
			if ((Object)(object)_cam == (Object)null)
			{
				_cam = Camera.main;
			}
			if ((Object)(object)_cam == (Object)null)
			{
				HideAllBars();
				return;
			}
			HealthSync.TrySubscribe();
			_rescanTimer -= num;
			if (_rescanTimer <= 0f)
			{
				_rescanTimer = 0.5f;
				Rescan();
			}
			Vector3 playerPosition = GetPlayerPosition();
			float num2 = Mathf.Max(1f, MonsterHealthBarsPlugin.Radius.Value);
			float value = MonsterHealthBarsPlugin.BarYOffset.Value;
			bool flag = HealthSync.IsMaster();
			bool flag2 = HealthSync.IsMultiplayer();
			float interval = Mathf.Max(0.2f, MonsterHealthBarsPlugin.SyncInterval.Value);
			bool value2 = MonsterHealthBarsPlugin.ShowBars.Value;
			bool value3 = MonsterHealthBarsPlugin.AlwaysShow.Value;
			float num3 = Mathf.Max(0f, MonsterHealthBarsPlugin.HideDelay.Value);
			float num4 = Mathf.Max(0.05f, MonsterHealthBarsPlugin.FadeOutDuration.Value);
			float num5 = Mathf.Clamp(MonsterHealthBarsPlugin.MinDistanceScale.Value, 0.2f, 1f);
			float value4 = MonsterHealthBarsPlugin.BarWidth.Value;
			float value5 = MonsterHealthBarsPlugin.BarHeight.Value;
			bool value6 = MonsterHealthBarsPlugin.ShowHpText.Value;
			bool value7 = MonsterHealthBarsPlugin.RequireLineOfSight.Value;
			Color barColor = MonsterHealthBarsPlugin.BarColor;
			float unscaledTime = Time.unscaledTime;
			for (int num6 = _entries.Count - 1; num6 >= 0; num6--)
			{
				Entry entry = _entries[num6];
				if ((Object)(object)entry.parent == (Object)null || (Object)(object)entry.health == (Object)null)
				{
					RemoveEntry(num6);
				}
				else
				{
					if (flag && flag2)
					{
						int current = HealthSync.GetCurrent(entry.health, 0);
						if (HealthSync.ShouldSend(ref entry.lastSentHp, ref entry.lastSendTime, current, interval))
						{
							HealthSync.Send(entry.viewId, current);
						}
					}
					bool flag3 = HealthSync.IsDead(entry.health);
					Vector3 val = GetTopPoint(entry) + Vector3.up * value;
					float num7 = Vector3.Distance(playerPosition, val);
					Vector2 screen = default(Vector2);
					float depth;
					bool flag4 = Project(val, out screen, out depth);
					bool num8 = value2 && ((Behaviour)entry.health).isActiveAndEnabled && ((Component)entry.health).gameObject.activeInHierarchy && ((Object)(object)entry.enemy == (Object)null || (int)entry.enemy.CurrentState != 11) && num7 <= num2 && flag4 && (!value7 || HasLineOfSight(val, ((Component)entry.parent).transform));
					bool flag5 = value3 || unscaledTime - entry.lastHitTime <= num3;
					float num9 = ((num8 && !flag3 && flag5) ? 1f : 0f);
					if (num9 > entry.alpha)
					{
						entry.alpha = Mathf.Min(num9, entry.alpha + num / 0.12f);
					}
					else if (num9 < entry.alpha)
					{
						entry.alpha = Mathf.Max(num9, entry.alpha - num / num4);
					}
					if (!num8 || entry.alpha <= 0.001f)
					{
						entry.bar.Hide();
					}
					else
					{
						int current2 = HealthSync.GetCurrent(entry.health, entry.viewId);
						int max = HealthSync.GetMax(entry.health);
						float num10 = Mathf.Clamp01(num7 / num2);
						float scale = Mathf.Lerp(1f, num5, num10);
						entry.bar.Show(ToCanvas(screen), scale, entry.alpha, (max > 0) ? Mathf.Clamp01((float)current2 / (float)max) : 0f, value4, value5, barColor, value6 ? (current2 + " / " + max) : null, num);
					}
				}
			}
			UpdatePopups(num);
		}

		private void Rescan()
		{
			EnemyDirector instance = EnemyDirector.instance;
			if ((Object)(object)instance == (Object)null)
			{
				ClearEntries();
				return;
			}
			HealthSync.NotifyDirector(instance);
			List<EnemyParent> enemiesSpawned = instance.enemiesSpawned;
			if (enemiesSpawned == null)
			{
				return;
			}
			for (int i = 0; i < enemiesSpawned.Count; i++)
			{
				EnemyParent val = enemiesSpawned[i];
				if (!((Object)(object)val == (Object)null) && FindEntry(val) == null)
				{
					AddEntry(val);
				}
			}
		}

		private Entry FindEntry(EnemyParent parent)
		{
			for (int i = 0; i < _entries.Count; i++)
			{
				if ((Object)(object)_entries[i].parent == (Object)(object)parent)
				{
					return _entries[i];
				}
			}
			return null;
		}

		private Entry FindEntryByHealth(EnemyHealth health)
		{
			for (int i = 0; i < _entries.Count; i++)
			{
				if ((Object)(object)_entries[i].health == (Object)(object)health)
				{
					return _entries[i];
				}
			}
			return null;
		}

		private Entry AddEntry(EnemyParent parent)
		{
			if ((Object)(object)parent == (Object)null)
			{
				return null;
			}
			EnemyHealth componentInChildren = ((Component)parent).GetComponentInChildren<EnemyHealth>(true);
			if ((Object)(object)componentInChildren == (Object)null)
			{
				return null;
			}
			Enemy componentInChildren2 = ((Component)parent).GetComponentInChildren<Enemy>(true);
			PhotonView component = ((Component)componentInChildren).GetComponent<PhotonView>();
			Entry entry = new Entry
			{
				parent = parent,
				health = componentInChildren,
				enemy = componentInChildren2,
				viewId = (((Object)(object)component != (Object)null) ? component.ViewID : 0),
				colliders = CollectColliders(((Component)parent).transform),
				renderers = CollectRenderers(((Component)parent).transform),
				lastHitTime = float.NegativeInfinity,
				bar = CreateBar()
			};
			_entries.Add(entry);
			return entry;
		}

		private void RemoveEntry(int index)
		{
			Entry entry = _entries[index];
			if (entry.bar != null)
			{
				entry.bar.Destroy();
			}
			_entries.RemoveAt(index);
		}

		private void ClearEntries()
		{
			for (int num = _entries.Count - 1; num >= 0; num--)
			{
				RemoveEntry(num);
			}
		}

		private void HideAllBars()
		{
			for (int i = 0; i < _entries.Count; i++)
			{
				_entries[i].bar?.Hide();
			}
		}

		private static Vector3 GetTopPoint(Entry e)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			return GetTopPoint(((Object)(object)e.enemy != (Object)null && (Object)(object)e.enemy.CenterTransform != (Object)null) ? e.enemy.CenterTransform : ((Component)e.health).transform, e.colliders, e.renderers);
		}

		private static Vector3 GetTopPoint(Transform center, Collider[] colliders, Renderer[] renderers)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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_01a1: 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)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			float num = float.NegativeInfinity;
			float x = center.position.x;
			float z = center.position.z;
			Vector3 size;
			if (colliders != null)
			{
				foreach (Collider val in colliders)
				{
					if (!((Object)(object)val == (Object)null) && val.enabled && ((Component)val).gameObject.activeInHierarchy)
					{
						Bounds bounds = val.bounds;
						size = ((Bounds)(ref bounds)).size;
						if (!(((Vector3)(ref size)).sqrMagnitude > 2500f) && ((Bounds)(ref bounds)).max.y > num)
						{
							num = ((Bounds)(ref bounds)).max.y;
							x = ((Bounds)(ref bounds)).center.x;
							z = ((Bounds)(ref bounds)).center.z;
						}
					}
				}
			}
			if (float.IsNegativeInfinity(num) && renderers != null)
			{
				foreach (Renderer val2 in renderers)
				{
					if (!((Object)(object)val2 == (Object)null) && val2.enabled)
					{
						Bounds bounds2 = val2.bounds;
						size = ((Bounds)(ref bounds2)).size;
						if (!(((Vector3)(ref size)).sqrMagnitude > 2500f) && ((Bounds)(ref bounds2)).max.y > num)
						{
							num = ((Bounds)(ref bounds2)).max.y;
							x = ((Bounds)(ref bounds2)).center.x;
							z = ((Bounds)(ref bounds2)).center.z;
						}
					}
				}
			}
			if (float.IsNegativeInfinity(num))
			{
				num = center.position.y + 1.2f;
				x = center.position.x;
				z = center.position.z;
			}
			if (num < center.position.y + 0.2f)
			{
				num = center.position.y + 0.2f;
			}
			return new Vector3(x, num, z);
		}

		private static Collider[] CollectColliders(Transform root)
		{
			Collider[] componentsInChildren = ((Component)root).GetComponentsInChildren<Collider>(true);
			List<Collider> list = new List<Collider>(componentsInChildren.Length);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && !componentsInChildren[i].isTrigger)
				{
					list.Add(componentsInChildren[i]);
				}
			}
			return list.ToArray();
		}

		private static Renderer[] CollectRenderers(Transform root)
		{
			Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
			List<Renderer> list = new List<Renderer>(componentsInChildren.Length);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (componentsInChildren[i] is MeshRenderer || componentsInChildren[i] is SkinnedMeshRenderer)
				{
					list.Add(componentsInChildren[i]);
				}
			}
			return list.ToArray();
		}

		private Bar CreateBar()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Expected O, but got Unknown
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Expected O, but got Unknown
			//IL_021a: 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)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Bar", new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)_canvasRect, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.sizeDelta = new Vector2(110f, 10f);
			CanvasGroup val4 = val.AddComponent<CanvasGroup>();
			val4.interactable = false;
			val4.blocksRaycasts = false;
			val4.alpha = 0f;
			GameObject val5 = new GameObject("Back", new Type[1] { typeof(RectTransform) });
			RectTransform val6 = (RectTransform)val5.transform;
			((Transform)val6).SetParent((Transform)(object)val2, false);
			val6.anchorMin = Vector2.zero;
			val6.anchorMax = Vector2.one;
			val6.offsetMin = new Vector2(-1f, -1f);
			val6.offsetMax = new Vector2(1f, 1f);
			Image val7 = val5.AddComponent<Image>();
			val7.sprite = _whiteSprite;
			((Graphic)val7).color = MonsterHealthBarsPlugin.BarBackColor;
			((Graphic)val7).raycastTarget = false;
			GameObject val8 = new GameObject("Fill", new Type[1] { typeof(RectTransform) });
			RectTransform val9 = (RectTransform)val8.transform;
			((Transform)val9).SetParent((Transform)(object)val2, false);
			val9.anchorMin = new Vector2(0f, 0f);
			val9.anchorMax = new Vector2(0f, 1f);
			val9.pivot = new Vector2(0f, 0.5f);
			val9.anchoredPosition = Vector2.zero;
			val9.sizeDelta = new Vector2(110f, 0f);
			Image val10 = val8.AddComponent<Image>();
			val10.sprite = _whiteSprite;
			((Graphic)val10).color = MonsterHealthBarsPlugin.BarColor;
			((Graphic)val10).raycastTarget = false;
			GameObject val11 = new GameObject("Label", new Type[1] { typeof(RectTransform) });
			RectTransform val12 = (RectTransform)val11.transform;
			((Transform)val12).SetParent((Transform)(object)val2, false);
			val12.anchorMin = new Vector2(0.5f, 1f);
			val12.anchorMax = new Vector2(0.5f, 1f);
			val12.pivot = new Vector2(0.5f, 0f);
			val12.anchoredPosition = new Vector2(0f, 2f);
			val12.sizeDelta = new Vector2(160f, 20f);
			TextMeshProUGUI val13 = CreateText(val11, 14f, (TextAlignmentOptions)514);
			((Graphic)val13).color = Color.white;
			val.SetActive(false);
			return new Bar
			{
				root = val,
				rect = val2,
				group = val4,
				back = val7,
				fill = val10,
				fillRect = val9,
				label = val13
			};
		}

		private TextMeshProUGUI CreateText(GameObject go, float size, TextAlignmentOptions align)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI val = go.AddComponent<TextMeshProUGUI>();
			TMP_FontAsset val2 = ResolveFont();
			if ((Object)(object)val2 != (Object)null)
			{
				((TMP_Text)val).font = val2;
			}
			((TMP_Text)val).fontSize = size;
			((TMP_Text)val).alignment = align;
			((Graphic)val).raycastTarget = false;
			((TMP_Text)val).text = string.Empty;
			return val;
		}

		private TMP_FontAsset ResolveFont()
		{
			if ((Object)(object)_font != (Object)null)
			{
				return _font;
			}
			try
			{
				_font = TMP_Settings.defaultFontAsset;
			}
			catch (Exception)
			{
			}
			if ((Object)(object)_font == (Object)null)
			{
				try
				{
					TMP_Text val = Object.FindAnyObjectByType<TMP_Text>();
					if ((Object)(object)val != (Object)null)
					{
						_font = val.font;
					}
				}
				catch (Exception)
				{
				}
			}
			if ((Object)(object)_font == (Object)null)
			{
				MonsterHealthBarsPlugin.LogWarn("TMP font asset not found - damage numbers may be invisible.");
			}
			return _font;
		}

		private void UpdatePopups(float dt)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: 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_01d0: Unknown result type (might be due to invalid IL or missing references)
			if (dt <= 0f)
			{
				return;
			}
			float value = MonsterHealthBarsPlugin.DamageTextSize.Value;
			Color val = Color.Lerp(MonsterHealthBarsPlugin.BarColor, Color.white, 0.45f);
			for (int num = _popups.Count - 1; num >= 0; num--)
			{
				Popup popup = _popups[num];
				if ((Object)(object)popup.go == (Object)null)
				{
					_popups.RemoveAt(num);
				}
				else if (popup.go.activeSelf)
				{
					popup.age += dt;
					Vector2 screen;
					float depth;
					if (popup.age >= popup.life)
					{
						popup.go.SetActive(false);
					}
					else if (!Project(popup.world, out screen, out depth))
					{
						popup.go.SetActive(false);
					}
					else
					{
						float num2 = Mathf.Clamp01(popup.age / popup.life);
						float num3 = 1f - (1f - num2) * (1f - num2);
						float num4 = (popup.riseCurrent = popup.rise * num3);
						float num5 = Mathf.Clamp01(popup.age / 0.15f);
						float num6 = Mathf.Clamp01((popup.life - popup.age) / 0.5f);
						float num7 = Mathf.Min(num5, num6);
						float num8 = ((num2 < 0.12f) ? Mathf.Lerp(1.2f, 1f, num2 / 0.12f) : 1f);
						popup.rect.anchoredPosition = ToCanvas(screen) + popup.screenOffset + new Vector2(0f, num4);
						((Transform)popup.rect).localScale = Vector3.one * num8;
						((TMP_Text)popup.text).fontSize = value;
						((Graphic)popup.text).color = new Color(val.r, val.g, val.b, num7);
					}
				}
			}
		}

		private Popup GetPopup()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_00a3: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _popups.Count; i++)
			{
				if (!_popups[i].go.activeSelf)
				{
					_popups[i].go.SetActive(true);
					return _popups[i];
				}
			}
			GameObject val = new GameObject("DamagePopup", new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)_canvasRect, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.sizeDelta = new Vector2(300f, 80f);
			TextMeshProUGUI val4 = CreateText(val, 36f, (TextAlignmentOptions)514);
			((TMP_Text)val4).fontStyle = (FontStyles)1;
			Popup popup = new Popup
			{
				go = val,
				rect = val2,
				text = val4,
				life = 2f
			};
			_popups.Add(popup);
			return popup;
		}

		internal static void OnDamage(EnemyHealth health, int amount)
		{
			BarsOverlay instance = Instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)health == (Object)null))
			{
				instance.MarkHit(health);
				if (amount > 0)
				{
					instance.SpawnDamage(health, amount);
				}
			}
		}

		private void MarkHit(EnemyHealth health)
		{
			Entry entry = FindEntryByHealth(health);
			if (entry == null)
			{
				EnemyParent componentInParent = ((Component)health).GetComponentInParent<EnemyParent>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					return;
				}
				entry = FindEntry(componentInParent) ?? AddEntry(componentInParent);
			}
			if (entry != null)
			{
				entry.lastHitTime = Time.unscaledTime;
			}
		}

		private void SpawnDamage(EnemyHealth health, int amount)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			if (MonsterHealthBarsPlugin.ShowDamageNumbers.Value && !((Object)(object)_cam == (Object)null) && !((Object)(object)ResolveFont() == (Object)null))
			{
				Vector3 val = GetAnchorFor(health) + Vector3.up * MonsterHealthBarsPlugin.BarYOffset.Value;
				float num = Mathf.Max(1f, MonsterHealthBarsPlugin.Radius.Value);
				if (!(Vector3.Distance(GetPlayerPosition(), val) > num) && Project(val, out var _, out var _))
				{
					Popup popup = GetPopup();
					float num2 = Mathf.Max(0.2f, MonsterHealthBarsPlugin.DamageTextDuration.Value);
					float num3 = (float)(_popupCounter++ % 5 - 2) * 30f + Random.Range(-6f, 6f);
					popup.world = val + new Vector3(Random.Range(-0.1f, 0.1f), 0.1f, Random.Range(-0.1f, 0.1f));
					popup.screenOffset = new Vector2(num3, 0f);
					popup.rise = MonsterHealthBarsPlugin.DamageTextRise.Value * num2;
					popup.riseCurrent = 0f;
					popup.age = 0f;
					popup.life = num2;
					((TMP_Text)popup.text).text = amount.ToString();
					popup.go.SetActive(true);
				}
			}
		}

		private Vector3 GetAnchorFor(EnemyHealth health)
		{
			//IL_000c: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			Entry entry = FindEntryByHealth(health);
			if (entry != null)
			{
				return GetTopPoint(entry);
			}
			EnemyParent componentInParent = ((Component)health).GetComponentInParent<EnemyParent>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				Enemy componentInChildren = ((Component)componentInParent).GetComponentInChildren<Enemy>(true);
				return GetTopPoint(((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.CenterTransform != (Object)null) ? componentInChildren.CenterTransform : ((Component)health).transform, CollectColliders(((Component)componentInParent).transform), null);
			}
			return ((Component)health).transform.position + Vector3.up * 1.5f;
		}

		private Vector3 GetPlayerPosition()
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			PlayerController instance = PlayerController.instance;
			if ((Object)(object)instance != (Object)null)
			{
				PlayerAvatar playerAvatarScript = instance.playerAvatarScript;
				if ((Object)(object)playerAvatarScript != (Object)null && (Object)(object)playerAvatarScript.playerTransform != (Object)null)
				{
					return playerAvatarScript.playerTransform.position;
				}
				if ((Object)(object)((Component)instance).transform != (Object)null)
				{
					return ((Component)instance).transform.position;
				}
			}
			if (!((Object)(object)_cam != (Object)null))
			{
				return Vector3.zero;
			}
			return ((Component)_cam).transform.position;
		}

		private bool Project(Vector3 world, out Vector2 screen, out float depth)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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)
			screen = default(Vector2);
			depth = 0f;
			if ((Object)(object)_cam == (Object)null)
			{
				return false;
			}
			Vector3 val = _cam.WorldToViewportPoint(world);
			depth = val.z;
			if (val.z <= 0f)
			{
				return false;
			}
			screen = new Vector2(val.x * (float)Screen.width, val.y * (float)Screen.height);
			return true;
		}

		private static Vector2 ToCanvas(Vector2 screen)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			return new Vector2(screen.x - (float)Screen.width * 0.5f, screen.y - (float)Screen.height * 0.5f);
		}

		private bool HasLineOfSight(Vector3 target, Transform root)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_cam == (Object)null)
			{
				return true;
			}
			Vector3 position = ((Component)_cam).transform.position;
			Vector3 val = target - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.01f)
			{
				return true;
			}
			RaycastHit val2 = default(RaycastHit);
			if (!Physics.Raycast(position, val / magnitude, ref val2, magnitude - 0.3f, -1, (QueryTriggerInteraction)1))
			{
				return true;
			}
			if ((Object)(object)((RaycastHit)(ref val2)).transform != (Object)null)
			{
				return ((RaycastHit)(ref val2)).transform.IsChildOf(root);
			}
			return false;
		}
	}
	internal static class HealthSync
	{
		internal const byte EventCode = 173;

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

		private static bool _subscribed;

		private static FieldRef<EnemyHealth, int> _healthCurrentRef;

		private static FieldRef<EnemyHealth, bool> _deadRef;

		private static FieldInfo _healthCurrentField;

		private static FieldInfo _deadField;

		private static EnemyDirector _lastDirector;

		internal static void Initialize()
		{
			try
			{
				_healthCurrentRef = AccessTools.FieldRefAccess<EnemyHealth, int>("healthCurrent");
			}
			catch (Exception)
			{
				_healthCurrentField = AccessTools.Field(typeof(EnemyHealth), "healthCurrent");
			}
			try
			{
				_deadRef = AccessTools.FieldRefAccess<EnemyHealth, bool>("dead");
			}
			catch (Exception)
			{
				_deadField = AccessTools.Field(typeof(EnemyHealth), "dead");
			}
			if (_healthCurrentRef == null && _healthCurrentField == null)
			{
				MonsterHealthBarsPlugin.LogError("EnemyHealth.healthCurrent not found - HP will not be readable. Game version changed?");
			}
			TrySubscribe();
		}

		internal static void Shutdown()
		{
			TryUnsubscribe();
		}

		internal static void TrySubscribe()
		{
			if (_subscribed)
			{
				return;
			}
			try
			{
				if (PhotonNetwork.NetworkingClient != null)
				{
					PhotonNetwork.NetworkingClient.EventReceived -= OnPhotonEvent;
					PhotonNetwork.NetworkingClient.EventReceived += OnPhotonEvent;
					_subscribed = true;
				}
			}
			catch (Exception ex)
			{
				MonsterHealthBarsPlugin.LogDebug("Photon subscribe failed: " + ex.Message);
			}
		}

		internal static void TryUnsubscribe()
		{
			if (!_subscribed)
			{
				return;
			}
			try
			{
				if (PhotonNetwork.NetworkingClient != null)
				{
					PhotonNetwork.NetworkingClient.EventReceived -= OnPhotonEvent;
				}
			}
			catch (Exception)
			{
			}
			_subscribed = false;
		}

		private static void OnPhotonEvent(EventData e)
		{
			if (e.Code == 173 && e.CustomData is object[] array && array.Length >= 2 && array[0] is int key && array[1] is int value)
			{
				NetHealth[key] = value;
			}
		}

		internal static bool IsMaster()
		{
			try
			{
				return SemiFunc.IsMasterClientOrSingleplayer();
			}
			catch (Exception)
			{
				try
				{
					return !GameManager.Multiplayer();
				}
				catch (Exception)
				{
					return true;
				}
			}
		}

		internal static bool IsMultiplayer()
		{
			try
			{
				return SemiFunc.IsMultiplayer();
			}
			catch (Exception)
			{
				try
				{
					return GameManager.Multiplayer();
				}
				catch (Exception)
				{
					return false;
				}
			}
		}

		internal static void NotifyDirector(EnemyDirector director)
		{
			if (!((Object)(object)director == (Object)(object)_lastDirector))
			{
				_lastDirector = director;
				NetHealth.Clear();
			}
		}

		internal static int GetMax(EnemyHealth health)
		{
			if (!((Object)(object)health == (Object)null))
			{
				return health.health;
			}
			return 0;
		}

		internal static bool IsDead(EnemyHealth health)
		{
			if ((Object)(object)health == (Object)null)
			{
				return true;
			}
			try
			{
				if (_deadRef != null)
				{
					return _deadRef.Invoke(health);
				}
				if (_deadField != null)
				{
					return (bool)_deadField.GetValue(health);
				}
			}
			catch (Exception)
			{
			}
			return false;
		}

		internal static int GetCurrent(EnemyHealth health, int viewId)
		{
			if ((Object)(object)health == (Object)null)
			{
				return 0;
			}
			if (IsMaster())
			{
				try
				{
					if (_healthCurrentRef != null)
					{
						return _healthCurrentRef.Invoke(health);
					}
					if (_healthCurrentField != null)
					{
						return (int)_healthCurrentField.GetValue(health);
					}
				}
				catch (Exception)
				{
				}
				return health.health;
			}
			if (viewId != 0 && NetHealth.TryGetValue(viewId, out var value))
			{
				return value;
			}
			return health.health;
		}

		internal static void Send(int viewId, int hp)
		{
			//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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			if (!MonsterHealthBarsPlugin.SyncEnabled.Value || viewId == 0)
			{
				return;
			}
			try
			{
				if (PhotonNetwork.InRoom)
				{
					object[] obj = new object[2] { viewId, hp };
					RaiseEventOptions val = new RaiseEventOptions
					{
						Receivers = (ReceiverGroup)0
					};
					SendOptions val2 = default(SendOptions);
					((SendOptions)(ref val2)).Reliability = true;
					PhotonNetwork.RaiseEvent((byte)173, (object)obj, val, val2);
				}
			}
			catch (Exception ex)
			{
				MonsterHealthBarsPlugin.LogDebug("RaiseEvent failed: " + ex.Message);
			}
		}

		internal static bool ShouldSend(ref int lastSent, ref float lastTime, int hp, float interval)
		{
			if (hp != lastSent || Time.unscaledTime - lastTime >= interval)
			{
				lastSent = hp;
				lastTime = Time.unscaledTime;
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(EnemyHealth), "Hurt", new Type[]
	{
		typeof(int),
		typeof(Vector3)
	})]
	internal static class EnemyHealthHurtPatch
	{
		private static void Prefix(EnemyHealth __instance, out int __state)
		{
			__state = HealthSync.GetCurrent(__instance, 0);
		}

		private static void Postfix(EnemyHealth __instance, int __state)
		{
			if (HealthSync.IsMaster())
			{
				int current = HealthSync.GetCurrent(__instance, 0);
				int num = __state - current;
				if (num > 0)
				{
					BarsOverlay.OnDamage(__instance, num);
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHealth), "HurtRPC", new Type[]
	{
		typeof(int),
		typeof(Vector3),
		typeof(PhotonMessageInfo)
	})]
	internal static class EnemyHealthHurtRpcPatch
	{
		private static void Postfix(EnemyHealth __instance, int _damage)
		{
			if (!HealthSync.IsMaster())
			{
				BarsOverlay.OnDamage(__instance, _damage);
			}
		}
	}
	[BepInPlugin("RuboMods.MonsterHealthBars", "MonsterHealthBars", "1.0.0")]
	public class MonsterHealthBarsPlugin : BaseUnityPlugin
	{
		public const string Guid = "RuboMods.MonsterHealthBars";

		public const string Version = "1.0.0";

		internal static ConfigEntry<float> Radius;

		internal static ConfigEntry<string> BarColorEntry;

		internal static ConfigEntry<float> BarWidth;

		internal static ConfigEntry<float> BarHeight;

		internal static ConfigEntry<float> BarYOffset;

		internal static ConfigEntry<float> MinDistanceScale;

		internal static ConfigEntry<bool> ShowBars;

		internal static ConfigEntry<bool> AlwaysShow;

		internal static ConfigEntry<float> HideDelay;

		internal static ConfigEntry<float> FadeOutDuration;

		internal static ConfigEntry<bool> ShowHpText;

		internal static ConfigEntry<bool> RequireLineOfSight;

		internal static ConfigEntry<bool> ShowDamageNumbers;

		internal static ConfigEntry<float> DamageTextSize;

		internal static ConfigEntry<float> DamageTextDuration;

		internal static ConfigEntry<float> DamageTextRise;

		internal static ConfigEntry<bool> SyncEnabled;

		internal static ConfigEntry<float> SyncInterval;

		internal static Color BarColor = new Color(1f, 0.16f, 0.16f, 1f);

		internal static readonly Color BarBackColor = new Color(0f, 0f, 0f, 0.65f);

		internal static MonsterHealthBarsPlugin Instance { get; private set; }

		internal static void Log(string message)
		{
			MonsterHealthBarsPlugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogInfo((object)message);
			}
		}

		internal static void LogWarn(string message)
		{
			MonsterHealthBarsPlugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogWarning((object)message);
			}
		}

		internal static void LogError(string message)
		{
			MonsterHealthBarsPlugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogError((object)message);
			}
		}

		internal static void LogDebug(string message)
		{
			MonsterHealthBarsPlugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogDebug((object)message);
			}
		}

		private void Awake()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Expected O, but got Unknown
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Expected O, but got Unknown
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Expected O, but got Unknown
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Expected O, but got Unknown
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Expected O, but got Unknown
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Expected O, but got Unknown
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Expected O, but got Unknown
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Expected O, but got Unknown
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Expected O, but got Unknown
			//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Radius = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "Radius", 20f, new ConfigDescription("Радиус (в метрах) вокруг игрока, в котором видны полоски HP и цифры урона.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 300f), Array.Empty<object>()));
			ShowBars = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "ShowHealthBars", true, "Показывать полоски HP над монстрами.");
			AlwaysShow = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "AlwaysShow", false, "true — полоски видны всегда; false — только после урона, затем гаснут через HideDelay.");
			HideDelay = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "HideDelay", 4f, new ConfigDescription("Сколько секунд полоска остаётся после последнего удара (если AlwaysShow = false).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>()));
			FadeOutDuration = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "FadeOutDuration", 0.5f, new ConfigDescription("За сколько секунд полоска плавно исчезает.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 3f), Array.Empty<object>()));
			BarColorEntry = ((BaseUnityPlugin)this).Config.Bind<string>("1. General", "BarColor", "#FF2A2A", "Цвет полоски HP. Формат: #RRGGBB, #RRGGBBAA или \"R,G,B\" (0-255).");
			BarWidth = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "BarWidth", 110f, new ConfigDescription("Ширина полоски в пикселях (при масштабе 1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 600f), Array.Empty<object>()));
			BarHeight = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "BarHeight", 10f, new ConfigDescription("Толщина полоски в пикселях.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 60f), Array.Empty<object>()));
			BarYOffset = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "BarYOffset", 0.25f, new ConfigDescription("Дополнительный подъём полоски над верхней точкой модели монстра (метры).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 5f), Array.Empty<object>()));
			MinDistanceScale = ((BaseUnityPlugin)this).Config.Bind<float>("1. General", "MinDistanceScale", 0.65f, new ConfigDescription("Во сколько раз уменьшается полоска на краю радиуса (1 = размер не зависит от расстояния).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
			ShowHpText = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "ShowHpText", false, "Показывать рядом с полоской текст \"текущее/максимум\".");
			RequireLineOfSight = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General", "RequireLineOfSight", false, "Скрывать полоску, если монстр за стеной (дороже по производительности).");
			ShowDamageNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("2. DamageNumbers", "Enabled", true, "Показывать всплывающие цифры урона рядом с монстром.");
			DamageTextSize = ((BaseUnityPlugin)this).Config.Bind<float>("2. DamageNumbers", "TextSize", 36f, new ConfigDescription("Размер цифр урона в пикселях (при масштабе 1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 200f), Array.Empty<object>()));
			DamageTextDuration = ((BaseUnityPlugin)this).Config.Bind<float>("2. DamageNumbers", "Duration", 2f, new ConfigDescription("Сколько секунд цифра висит и растворяется.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 10f), Array.Empty<object>()));
			DamageTextRise = ((BaseUnityPlugin)this).Config.Bind<float>("2. DamageNumbers", "RiseSpeed", 20f, new ConfigDescription("Скорость подъёма цифры (пикселей в секунду, с замедлением к концу).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>()));
			SyncEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("3. Multiplayer", "SyncHealth", true, "Хост рассылает клиентам текущее HP монстров (Photon event). Без этого клиенты видели бы только максимум.");
			SyncInterval = ((BaseUnityPlugin)this).Config.Bind<float>("3. Multiplayer", "HeartbeatInterval", 1f, new ConfigDescription("Как часто хост дополнительно рассылает HP (сек) даже без урона.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 10f), Array.Empty<object>()));
			BarColor = ParseColor(BarColorEntry.Value, new Color(1f, 0.16f, 0.16f, 1f));
			BarColorEntry.SettingChanged += delegate
			{
				//IL_000a: 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_0014: Unknown result type (might be due to invalid IL or missing references)
				BarColor = ParseColor(BarColorEntry.Value, Color.red);
			};
			GameObject val = new GameObject("MonsterHealthBars_Overlay");
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<BarsOverlay>();
			HealthSync.Initialize();
			try
			{
				new Harmony("RuboMods.MonsterHealthBars").PatchAll(typeof(MonsterHealthBarsPlugin).Assembly);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Harmony patch failed: " + ex));
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("MonsterHealthBars v1.0.0 loaded. Radius=" + Radius.Value + "m, color=" + BarColorEntry.Value));
		}

		private void OnDestroy()
		{
			HealthSync.Shutdown();
		}

		internal static Color ParseColor(string value, Color fallback)
		{
			//IL_0008: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrWhiteSpace(value))
			{
				return fallback;
			}
			value = value.Trim();
			Color result = default(Color);
			if (value.StartsWith("#") && ColorUtility.TryParseHtmlString(value, ref result))
			{
				return result;
			}
			string[] array = value.Split(',');
			if (array.Length >= 3 && float.TryParse(array[0], out var result2) && float.TryParse(array[1], out var result3) && float.TryParse(array[2], out var result4))
			{
				float result5 = 255f;
				if (array.Length >= 4)
				{
					float.TryParse(array[3], out result5);
				}
				return new Color(Mathf.Clamp01(result2 / 255f), Mathf.Clamp01(result3 / 255f), Mathf.Clamp01(result4 / 255f), Mathf.Clamp01((result5 <= 1f) ? result5 : (result5 / 255f)));
			}
			Color result6 = default(Color);
			if (ColorUtility.TryParseHtmlString(value, ref result6))
			{
				return result6;
			}
			return fallback;
		}
	}
}