Decompiled source of FishHealthBars v1.1.1

BepInEx/plugins/FishHealthBars/FishHealthBars.dll

Decompiled 39 minutes ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using UnityEngine;

[assembly: AssemblyDescription("Client-side overhead health bars for fish in How to Fish.")]
[assembly: AssemblyTitle("How to Fish - Fish Health Bars")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("1.1.1.0")]
namespace HowToFishFishHealthBars;

[BepInPlugin("net.howtofish.fishhealthbars", "How to Fish - Fish Health Bars", "1.1.1")]
public sealed class FishHealthBarsPlugin : BaseUnityPlugin
{
	private sealed class FishState
	{
		public Fish Fish;

		public int LastHealth;

		public float VisibleUntil;
	}

	public const string PluginGuid = "net.howtofish.fishhealthbars";

	public const string PluginName = "How to Fish - Fish Health Bars";

	public const string PluginVersion = "1.1.1";

	private const int SettingsWindowId = 418042;

	private readonly List<FishState> _fishStates = new List<FishState>();

	private readonly HashSet<Fish> _knownFish = new HashSet<Fish>();

	private ConfigEntry<bool> _enabled;

	private ConfigEntry<KeyboardShortcut> _toggleKey;

	private ConfigEntry<bool> _showWhenAimed;

	private ConfigEntry<bool> _showAfterDamage;

	private ConfigEntry<bool> _alwaysShow;

	private ConfigEntry<bool> _showBosses;

	private ConfigEntry<bool> _showNumbers;

	private ConfigEntry<float> _damageDisplaySeconds;

	private ConfigEntry<float> _maximumDistance;

	private ConfigEntry<float> _verticalOffset;

	private ConfigEntry<float> _barWidth;

	private ConfigEntry<float> _barHeight;

	private ConfigEntry<int> _fontSize;

	private ConfigEntry<float> _scanInterval;

	private ConfigEntry<bool> _useChinese;

	private ConfigEntry<string> _healthyColorHex;

	private ConfigEntry<string> _mediumColorHex;

	private ConfigEntry<string> _lowColorHex;

	private Camera _camera;

	private Fish _aimedFish;

	private float _nextScanTime;

	private float _nextHealthPollTime;

	private float _statusUntil;

	private GUIStyle _healthTextStyle;

	private GUIStyle _statusStyle;

	private GUIStyle _windowStyle;

	private GUIStyle _sectionStyle;

	private GUIStyle _labelStyle;

	private GUIStyle _buttonStyle;

	private GUIStyle _toggleStyle;

	private Font _uiFont;

	private Rect _settingsWindowRect;

	private Vector2 _settingsScroll;

	private bool _settingsOpen;

	private bool _windowPositionInitialized;

	private bool _mouseWasLocked;

	private bool _cursorWasVisible;

	private CursorLockMode _cursorWasLocked;

	private bool _configDirty;

	private float _nextConfigSaveTime;

	private Color _healthyColor;

	private Color _mediumColor;

	private Color _lowColor;

	private void Awake()
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0310: Unknown result type (might be due to invalid IL or missing references)
		//IL_0315: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_033b: Unknown result type (might be due to invalid IL or missing references)
		((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
		_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable fish health bars.");
		_toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)289, (KeyCode[])(object)new KeyCode[0]), "Keyboard shortcut that opens or closes the in-game settings window.");
		_useChinese = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UseChinese", true, "Use Chinese in the in-game settings window. False uses English.");
		_showWhenAimed = ((BaseUnityPlugin)this).Config.Bind<bool>("Visibility", "ShowWhenAimed", true, "Show a health bar while the crosshair is pointing at a fish.");
		_showAfterDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("Visibility", "ShowAfterDamage", true, "Show a health bar for a short time after the fish loses health.");
		_alwaysShow = ((BaseUnityPlugin)this).Config.Bind<bool>("Visibility", "AlwaysShow", false, "Always show health bars for living fish within MaximumDistance.");
		_showBosses = ((BaseUnityPlugin)this).Config.Bind<bool>("Visibility", "ShowBosses", false, "Also show overhead bars for boss fish. The game already has a boss health UI.");
		_damageDisplaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Visibility", "DamageDisplaySeconds", 6f, "Seconds a health bar remains visible after the fish takes damage.");
		_maximumDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Visibility", "MaximumDistance", 35f, "Maximum world distance at which a health bar can be displayed.");
		_scanInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Visibility", "ScanInterval", 0.75f, "Seconds between searches for newly spawned fish. Lower values react faster but cost more CPU.");
		_showNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "ShowNumbers", true, "Display current and maximum health as text on the bar.");
		_verticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "VerticalOffset", 0.35f, "Additional world-space height above the fish's built-in head position.");
		_barWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "BarWidth", 120f, "Health bar width in screen pixels.");
		_barHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "BarHeight", 14f, "Health bar height in screen pixels.");
		_fontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Appearance", "FontSize", 13, "Health number font size.");
		_healthyColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Colors", "HealthyColor", "#1FE038", "Health bar color at high health, in #RRGGBB format.");
		_mediumColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Colors", "MediumColor", "#FFC70D", "Health bar color at medium health, in #RRGGBB format.");
		_lowColorHex = ((BaseUnityPlugin)this).Config.Bind<string>("Colors", "LowColor", "#EB1414", "Health bar color at low health, in #RRGGBB format.");
		_healthyColor = ParseColor(_healthyColorHex.Value, new Color(0.12f, 0.88f, 0.22f, 0.95f));
		_mediumColor = ParseColor(_mediumColorHex.Value, new Color(1f, 0.78f, 0.05f, 0.95f));
		_lowColor = ParseColor(_lowColorHex.Value, new Color(0.92f, 0.08f, 0.08f, 0.95f));
		((BaseUnityPlugin)this).Config.Save();
		((BaseUnityPlugin)this).Logger.LogInfo((object)string.Concat("How to Fish - Fish Health Bars 1.1.1 loaded. Press ", _toggleKey.Value, " for settings."));
	}

	private void Update()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		KeyboardShortcut value = _toggleKey.Value;
		if (((KeyboardShortcut)(ref value)).IsDown())
		{
			SetSettingsOpen(!_settingsOpen);
		}
		float unscaledTime = Time.unscaledTime;
		if (_settingsOpen)
		{
			KeepSettingsMouseUnlocked();
		}
		if (_configDirty && unscaledTime >= _nextConfigSaveTime)
		{
			SaveConfigNow();
		}
		if (!_enabled.Value)
		{
			_aimedFish = null;
			return;
		}
		_camera = GetGameplayCamera();
		if (!((Object)(object)_camera == (Object)null))
		{
			if (unscaledTime >= _nextScanTime)
			{
				ScanForFish();
				_nextScanTime = unscaledTime + Mathf.Max(0.1f, _scanInterval.Value);
			}
			if (unscaledTime >= _nextHealthPollTime)
			{
				PollHealthChanges(unscaledTime);
				_nextHealthPollTime = unscaledTime + 0.1f;
			}
			_aimedFish = (_showWhenAimed.Value ? FindAimedFish(_camera) : null);
		}
	}

	private Camera GetGameplayCamera()
	{
		try
		{
			if ((Object)(object)Player.LocalPlayer != (Object)null && (Object)(object)Player.LocalPlayer.CurCam != (Object)null)
			{
				return Player.LocalPlayer.CurCam;
			}
		}
		catch (Exception)
		{
		}
		return Camera.main;
	}

	private void ScanForFish()
	{
		Fish[] array;
		try
		{
			array = Object.FindObjectsByType<Fish>();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not scan for fish: " + ex.Message));
			return;
		}
		foreach (Fish val in array)
		{
			if (!((Object)(object)val == (Object)null) && !_knownFish.Contains(val))
			{
				_knownFish.Add(val);
				_fishStates.Add(new FishState
				{
					Fish = val,
					LastHealth = ((Creature)val).Hp,
					VisibleUntil = 0f
				});
			}
		}
		for (int num = _fishStates.Count - 1; num >= 0; num--)
		{
			Fish fish = _fishStates[num].Fish;
			if (!((Object)(object)fish != (Object)null))
			{
				_knownFish.Remove(fish);
				_fishStates.RemoveAt(num);
			}
		}
	}

	private void PollHealthChanges(float now)
	{
		for (int num = _fishStates.Count - 1; num >= 0; num--)
		{
			FishState fishState = _fishStates[num];
			Fish fish = fishState.Fish;
			if ((Object)(object)fish == (Object)null)
			{
				_knownFish.Remove(fish);
				_fishStates.RemoveAt(num);
			}
			else
			{
				int hp = ((Creature)fish).Hp;
				if (_showAfterDamage.Value && hp < fishState.LastHealth)
				{
					fishState.VisibleUntil = now + Mathf.Max(0f, _damageDisplaySeconds.Value);
				}
				fishState.LastHealth = hp;
			}
		}
	}

	private Fish FindAimedFish(Camera camera)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		Ray val = camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f));
		float num = Mathf.Max(1f, _maximumDistance.Value);
		RaycastHit val2 = default(RaycastHit);
		if (!Physics.Raycast(val, ref val2, num, -1, (QueryTriggerInteraction)2))
		{
			return null;
		}
		Fish componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Fish>();
		if (!IsEligible(componentInParent))
		{
			return null;
		}
		return componentInParent;
	}

	private bool IsEligible(Fish fish)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)fish == (Object)null || !((Behaviour)fish).isActiveAndEnabled || ((Creature)fish).IsDead || ((Creature)fish).Hp <= 0 || ((Creature)fish).MaxHp <= 0)
		{
			return false;
		}
		if (!_showBosses.Value && (int)((Creature)fish).BossType != 0)
		{
			return false;
		}
		return true;
	}

	private void OnGUI()
	{
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		EnsureStyles();
		if (Time.unscaledTime < _statusUntil)
		{
			DrawToggleStatus();
		}
		if (_enabled.Value && (Object)(object)_camera != (Object)null)
		{
			Camera camera = _camera;
			float num = Mathf.Max(1f, _maximumDistance.Value);
			float num2 = num * num;
			float unscaledTime = Time.unscaledTime;
			for (int i = 0; i < _fishStates.Count; i++)
			{
				FishState fishState = _fishStates[i];
				Fish fish = fishState.Fish;
				if (IsEligible(fish) && (_alwaysShow.Value || (Object)(object)fish == (Object)(object)_aimedFish || (_showAfterDamage.Value && unscaledTime <= fishState.VisibleUntil)))
				{
					Vector3 val = ((Component)fish).transform.position - ((Component)camera).transform.position;
					if (!(((Vector3)(ref val)).sqrMagnitude > num2))
					{
						DrawHealthBar(camera, fish);
					}
				}
			}
		}
		if (_settingsOpen)
		{
			DrawSettingsWindow();
		}
	}

	private void EnsureStyles()
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Expected O, but got Unknown
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Expected O, but got Unknown
		//IL_0100: 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)
		//IL_0138: Expected O, but got Unknown
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Expected O, but got Unknown
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Expected O, but got Unknown
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Expected O, but got Unknown
		//IL_021d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0227: Expected O, but got Unknown
		//IL_0250: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Expected O, but got Unknown
		//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Expected O, but got Unknown
		//IL_02db: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)_uiFont == (Object)null)
		{
			try
			{
				_uiFont = Font.CreateDynamicFontFromOSFont(new string[4] { "Microsoft YaHei UI", "Microsoft YaHei", "SimHei", "Arial" }, 16);
			}
			catch (Exception)
			{
				_uiFont = GUI.skin.font;
			}
		}
		if (_healthTextStyle == null)
		{
			_healthTextStyle = new GUIStyle(GUI.skin.label);
			_healthTextStyle.alignment = (TextAnchor)4;
			_healthTextStyle.fontStyle = (FontStyle)1;
			_healthTextStyle.normal.textColor = Color.white;
			_healthTextStyle.font = _uiFont;
		}
		if (_statusStyle == null)
		{
			_statusStyle = new GUIStyle(GUI.skin.box);
			_statusStyle.alignment = (TextAnchor)4;
			_statusStyle.fontStyle = (FontStyle)1;
			_statusStyle.fontSize = 15;
			_statusStyle.normal.textColor = Color.white;
			_statusStyle.font = _uiFont;
		}
		if (_windowStyle == null)
		{
			_windowStyle = new GUIStyle(GUI.skin.window);
			_windowStyle.font = _uiFont;
			_windowStyle.fontSize = 16;
			_windowStyle.fontStyle = (FontStyle)1;
			_windowStyle.alignment = (TextAnchor)1;
			_windowStyle.padding = new RectOffset(14, 14, 28, 12);
		}
		if (_sectionStyle == null)
		{
			_sectionStyle = new GUIStyle(GUI.skin.label);
			_sectionStyle.font = _uiFont;
			_sectionStyle.fontSize = 15;
			_sectionStyle.fontStyle = (FontStyle)1;
			_sectionStyle.normal.textColor = new Color(0.35f, 0.85f, 1f, 1f);
			_sectionStyle.margin = new RectOffset(2, 2, 8, 2);
		}
		if (_labelStyle == null)
		{
			_labelStyle = new GUIStyle(GUI.skin.label);
			_labelStyle.font = _uiFont;
			_labelStyle.fontSize = 13;
			_labelStyle.normal.textColor = Color.white;
		}
		if (_buttonStyle == null)
		{
			_buttonStyle = new GUIStyle(GUI.skin.button);
			_buttonStyle.font = _uiFont;
			_buttonStyle.fontSize = 13;
		}
		if (_toggleStyle == null)
		{
			_toggleStyle = new GUIStyle(GUI.skin.toggle);
			_toggleStyle.font = _uiFont;
			_toggleStyle.fontSize = 13;
			_toggleStyle.normal.textColor = Color.white;
			_toggleStyle.onNormal.textColor = Color.white;
		}
		_healthTextStyle.fontSize = Mathf.Clamp(_fontSize.Value, 8, 40);
	}

	private void DrawToggleStatus()
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		string text = ((!_settingsOpen) ? (_useChinese.Value ? "鱼血条设置:已关闭" : "Fish Health Settings: CLOSED") : (_useChinese.Value ? "鱼血条设置:已打开" : "Fish Health Settings: OPEN"));
		Rect val = default(Rect);
		((Rect)(ref val))..ctor(((float)Screen.width - 260f) * 0.5f, 36f, 260f, 34f);
		GUI.Box(val, text, _statusStyle);
	}

	private void DrawHealthBar(Camera camera, Fish fish)
	{
		//IL_0020: 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_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_0041: 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_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Abs(((Creature)fish).HeadPos);
		if (num < 0.1f)
		{
			num = 0.8f;
		}
		Vector3 val = ((Component)fish).transform.position + Vector3.up * (num + _verticalOffset.Value);
		Vector3 val2 = camera.WorldToScreenPoint(val);
		if (val2.z <= 0f)
		{
			return;
		}
		float num2 = Mathf.Clamp(_barWidth.Value, 40f, 500f);
		float num3 = Mathf.Clamp(_barHeight.Value, 5f, 80f);
		float num4 = val2.x - num2 * 0.5f;
		float num5 = (float)Screen.height - val2.y - num3 * 0.5f;
		if (!(num4 + num2 < 0f) && !(num4 > (float)Screen.width) && !(num5 + num3 < 0f) && !(num5 > (float)Screen.height))
		{
			int num6 = Mathf.Max(0, ((Creature)fish).Hp);
			int num7 = Mathf.Max(1, ((Creature)fish).MaxHp);
			float num8 = Mathf.Clamp01((float)num6 / (float)num7);
			Color color = GUI.color;
			GUI.color = new Color(0f, 0f, 0f, 0.82f);
			GUI.DrawTexture(new Rect(num4 - 2f, num5 - 2f, num2 + 4f, num3 + 4f), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = new Color(0.08f, 0.08f, 0.08f, 0.92f);
			GUI.DrawTexture(new Rect(num4, num5, num2, num3), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = GetHealthColor(num8);
			GUI.DrawTexture(new Rect(num4, num5, num2 * num8, num3), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color;
			if (_showNumbers.Value)
			{
				GUI.Label(new Rect(num4, num5 - 2f, num2, num3 + 4f), num6 + " / " + num7, _healthTextStyle);
			}
		}
	}

	private void DrawSettingsWindow()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Expected O, but got Unknown
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Clamp((float)Screen.width - 40f, 360f, 600f);
		float num2 = Mathf.Clamp((float)Screen.height - 40f, 420f, 680f);
		if (!_windowPositionInitialized)
		{
			_settingsWindowRect = new Rect(((float)Screen.width - num) * 0.5f, ((float)Screen.height - num2) * 0.5f, num, num2);
			_windowPositionInitialized = true;
		}
		((Rect)(ref _settingsWindowRect)).width = num;
		((Rect)(ref _settingsWindowRect)).height = num2;
		((Rect)(ref _settingsWindowRect)).x = Mathf.Clamp(((Rect)(ref _settingsWindowRect)).x, 0f, Mathf.Max(0f, (float)Screen.width - num));
		((Rect)(ref _settingsWindowRect)).y = Mathf.Clamp(((Rect)(ref _settingsWindowRect)).y, 0f, Mathf.Max(0f, (float)Screen.height - num2));
		int depth = GUI.depth;
		GUI.depth = -2000;
		string text = (_useChinese.Value ? "鱼血条设置  ·  F8 关闭" : "Fish Health Bar Settings  ·  F8 to close");
		_settingsWindowRect = GUI.Window(418042, _settingsWindowRect, new WindowFunction(DrawSettingsWindowContents), text, _windowStyle);
		GUI.depth = depth;
	}

	private void DrawSettingsWindowContents(int windowId)
	{
		//IL_00c6: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_035f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0364: Unknown result type (might be due to invalid IL or missing references)
		//IL_0369: Unknown result type (might be due to invalid IL or missing references)
		//IL_037c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0381: Unknown result type (might be due to invalid IL or missing references)
		//IL_0386: Unknown result type (might be due to invalid IL or missing references)
		//IL_0399: Unknown result type (might be due to invalid IL or missing references)
		//IL_039e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_03be: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04be: Unknown result type (might be due to invalid IL or missing references)
		bool value = _useChinese.Value;
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.Label(value ? "界面语言" : "Interface language", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(180f) });
		if (GUILayout.Button(value ? "中文  ✓" : "中文", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(27f) }))
		{
			SetLanguage(useChinese: true);
		}
		if (GUILayout.Button((!value) ? "English  ✓" : "English", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(27f) }))
		{
			SetLanguage(useChinese: false);
		}
		GUILayout.EndHorizontal();
		_settingsScroll = GUILayout.BeginScrollView(_settingsScroll, false, true, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.Label(T("常规", "General"), _sectionStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		DrawBoolSetting(_enabled, "启用鱼血条", "Enable fish health bars");
		GUILayout.Label(T("显示规则", "Visibility"), _sectionStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		DrawBoolSetting(_alwaysShow, "范围内始终显示", "Always show within range");
		DrawBoolSetting(_showWhenAimed, "瞄准鱼时显示", "Show while aiming at a fish");
		DrawBoolSetting(_showAfterDamage, "鱼受伤后显示", "Show after a fish takes damage");
		DrawBoolSetting(_showBosses, "同时显示 Boss 头顶血条", "Show overhead bars for bosses");
		_maximumDistance.Value = DrawFloatSetting(T("最大显示范围", "Maximum display range"), _maximumDistance.Value, 5f, 150f, "0");
		_damageDisplaySeconds.Value = DrawFloatSetting(T("受伤后显示秒数", "Seconds visible after damage"), _damageDisplaySeconds.Value, 0f, 20f, "0.0");
		GUILayout.Label(T("血条外观", "Appearance"), _sectionStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		DrawBoolSetting(_showNumbers, "显示 HP 数字", "Show HP numbers");
		_barWidth.Value = DrawFloatSetting(T("血条宽度", "Bar width"), _barWidth.Value, 50f, 300f, "0");
		_barHeight.Value = DrawFloatSetting(T("血条高度", "Bar height"), _barHeight.Value, 6f, 40f, "0");
		_fontSize.Value = Mathf.RoundToInt(DrawFloatSetting(T("HP 字号", "HP font size"), _fontSize.Value, 8f, 32f, "0"));
		_verticalOffset.Value = DrawFloatSetting(T("垂直位置", "Vertical offset"), _verticalOffset.Value, -1f, 3f, "0.00");
		GUILayout.Label(T("HP 颜色", "HP Colors"), _sectionStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		Color next = DrawColorEditor(T("高血量颜色", "High health color"), _healthyColor);
		Color next2 = DrawColorEditor(T("中血量颜色", "Medium health color"), _mediumColor);
		Color next3 = DrawColorEditor(T("低血量颜色", "Low health color"), _lowColor);
		SetColorIfChanged(ref _healthyColor, next, _healthyColorHex);
		SetColorIfChanged(ref _mediumColor, next2, _mediumColorHex);
		SetColorIfChanged(ref _lowColor, next3, _lowColorHex);
		DrawColorPreview();
		GUILayout.Space(10f);
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
		if (GUILayout.Button(T("恢复默认颜色", "Reset default colors"), _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
		{
			ResetDefaultColors();
		}
		if (GUILayout.Button(T("保存并关闭", "Save and close"), _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }))
		{
			SetSettingsOpen(open: false);
		}
		GUILayout.EndHorizontal();
		GUILayout.Space(6f);
		GUILayout.Label(T("设置会自动保存。按 F8 可随时重新打开。", "Settings are saved automatically. Press F8 to reopen."), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.EndScrollView();
		GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref _settingsWindowRect)).width, 26f));
	}

	private void DrawBoolSetting(ConfigEntry<bool> entry, string chineseLabel, string englishLabel)
	{
		bool value = entry.Value;
		bool flag = GUILayout.Toggle(value, T(chineseLabel, englishLabel), _toggleStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(23f) });
		if (flag != value)
		{
			entry.Value = flag;
			MarkConfigDirty();
		}
	}

	private float DrawFloatSetting(string label, float value, float minimum, float maximum, string format)
	{
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.Label(label, _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(225f) });
		float num = GUILayout.HorizontalSlider(value, minimum, maximum, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(120f) });
		GUILayout.Label(num.ToString(format), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(56f) });
		GUILayout.EndHorizontal();
		if (!Mathf.Approximately(num, value))
		{
			MarkConfigDirty();
		}
		return num;
	}

	private Color DrawColorEditor(string label, Color color)
	{
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.Label(label, _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(155f) });
		Rect rect = GUILayoutUtility.GetRect(42f, 18f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(42f) });
		Color color2 = GUI.color;
		GUI.color = new Color(color.r, color.g, color.b, 1f);
		GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
		GUI.color = color2;
		GUILayout.Label(ToHexColor(color), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(78f) });
		GUILayout.EndHorizontal();
		float num = DrawColorChannel("R", color.r);
		float num2 = DrawColorChannel("G", color.g);
		float num3 = DrawColorChannel("B", color.b);
		return new Color(num, num2, num3, 0.95f);
	}

	private float DrawColorChannel(string channel, float value)
	{
		GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[0]);
		GUILayout.Space(22f);
		GUILayout.Label(channel, _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(22f) });
		float num = GUILayout.HorizontalSlider(value, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(180f) });
		GUILayout.Label(Mathf.RoundToInt(num * 255f).ToString(), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(42f) });
		GUILayout.EndHorizontal();
		return num;
	}

	private void DrawColorPreview()
	{
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		GUILayout.Label(T("颜色预览(低 → 中 → 高)", "Color preview (low → medium → high)"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[0]);
		Rect rect = GUILayoutUtility.GetRect(100f, 20f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
		float num = ((Rect)(ref rect)).width / 3f;
		Color color = GUI.color;
		GUI.color = _lowColor;
		GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num, ((Rect)(ref rect)).height), (Texture)(object)Texture2D.whiteTexture);
		GUI.color = _mediumColor;
		GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + num, ((Rect)(ref rect)).y, num, ((Rect)(ref rect)).height), (Texture)(object)Texture2D.whiteTexture);
		GUI.color = _healthyColor;
		GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + num * 2f, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width - num * 2f, ((Rect)(ref rect)).height), (Texture)(object)Texture2D.whiteTexture);
		GUI.color = color;
	}

	private void SetLanguage(bool useChinese)
	{
		if (_useChinese.Value != useChinese)
		{
			_useChinese.Value = useChinese;
			MarkConfigDirty();
		}
	}

	private string T(string chinese, string english)
	{
		if (!_useChinese.Value)
		{
			return english;
		}
		return chinese;
	}

	private void SetColorIfChanged(ref Color current, Color next, ConfigEntry<string> entry)
	{
		//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_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		if (!ColorsApproximatelyEqual(current, next))
		{
			current = next;
			entry.Value = ToHexColor(next);
			MarkConfigDirty();
		}
	}

	private static bool ColorsApproximatelyEqual(Color first, Color second)
	{
		if (Mathf.Abs(first.r - second.r) < 0.001f && Mathf.Abs(first.g - second.g) < 0.001f)
		{
			return Mathf.Abs(first.b - second.b) < 0.001f;
		}
		return false;
	}

	private static Color ParseColor(string value, Color fallback)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		Color result = default(Color);
		if (!string.IsNullOrEmpty(value) && ColorUtility.TryParseHtmlString(value, ref result))
		{
			result.a = 0.95f;
			return result;
		}
		return fallback;
	}

	private static string ToHexColor(Color color)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		return "#" + ColorUtility.ToHtmlStringRGB(color);
	}

	private void ResetDefaultColors()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		_healthyColor = new Color(0.12f, 0.88f, 0.22f, 0.95f);
		_mediumColor = new Color(1f, 0.78f, 0.05f, 0.95f);
		_lowColor = new Color(0.92f, 0.08f, 0.08f, 0.95f);
		_healthyColorHex.Value = ToHexColor(_healthyColor);
		_mediumColorHex.Value = ToHexColor(_mediumColor);
		_lowColorHex.Value = ToHexColor(_lowColor);
		MarkConfigDirty();
	}

	private void SetSettingsOpen(bool open)
	{
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Invalid comparison between Unknown and I4
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Invalid comparison between Unknown and I4
		if (_settingsOpen == open)
		{
			return;
		}
		_settingsOpen = open;
		_statusUntil = Time.unscaledTime + 1.5f;
		if (open)
		{
			_cursorWasVisible = Cursor.visible;
			_cursorWasLocked = Cursor.lockState;
			try
			{
				_mouseWasLocked = (((Object)(object)Player.LocalPlayer != (Object)null && (Object)(object)Player.LocalPlayer.Camera != (Object)null) ? Player.LocalPlayer.Camera.MouseLocked : ((int)_cursorWasLocked == 1));
			}
			catch (Exception)
			{
				_mouseWasLocked = (int)_cursorWasLocked == 1;
			}
			KeepSettingsMouseUnlocked();
		}
		else
		{
			SaveConfigNow();
			RestoreGameplayMouse();
		}
	}

	private void KeepSettingsMouseUnlocked()
	{
		try
		{
			if ((Object)(object)Player.LocalPlayer != (Object)null && (Object)(object)Player.LocalPlayer.Camera != (Object)null && Player.LocalPlayer.Camera.MouseLocked)
			{
				PlayerCamera.ToggleMouse(true);
			}
		}
		catch (Exception)
		{
		}
		Cursor.lockState = (CursorLockMode)0;
		Cursor.visible = true;
	}

	private void RestoreGameplayMouse()
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)Player.LocalPlayer != (Object)null && (Object)(object)Player.LocalPlayer.Camera != (Object)null)
			{
				PlayerCamera.ToggleMouse(!_mouseWasLocked);
			}
		}
		catch (Exception)
		{
		}
		Cursor.lockState = _cursorWasLocked;
		Cursor.visible = _cursorWasVisible;
	}

	private void MarkConfigDirty()
	{
		_configDirty = true;
		_nextConfigSaveTime = Time.unscaledTime + 0.5f;
	}

	private void SaveConfigNow()
	{
		((BaseUnityPlugin)this).Config.Save();
		_configDirty = false;
	}

	private void OnDestroy()
	{
		SaveConfigNow();
		if (_settingsOpen)
		{
			RestoreGameplayMouse();
		}
	}

	private Color GetHealthColor(float healthPercent)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: 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_0021: Unknown result type (might be due to invalid IL or missing references)
		if (healthPercent > 0.5f)
		{
			return Color.Lerp(_mediumColor, _healthyColor, (healthPercent - 0.5f) * 2f);
		}
		return Color.Lerp(_lowColor, _mediumColor, healthPercent * 2f);
	}
}