Decompiled source of BoatStatusHUD v1.8.0

BoatStatusHUD.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyMetadata("PluginGUID", "com.luizbag.sailwind.boatstatushud")]
[assembly: AssemblyMetadata("PluginName", "BoatStatusHUD")]
[assembly: AssemblyCompany("BoatStatusHUD")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.8.0.0")]
[assembly: AssemblyInformationalVersion("1.8.0+66bc7d1a6a3c6df9f28430569bb9eb2d18877a6f")]
[assembly: AssemblyProduct("BoatStatusHUD")]
[assembly: AssemblyTitle("BoatStatusHUD")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.8.0.0")]
[module: UnverifiableCode]
namespace BoatStatusHUD;

[BepInPlugin("com.luizbag.sailwind.boatstatushud", "BoatStatusHUD", "0.0.0")]
public class BoatStatusHUDPlugin : BaseUnityPlugin
{
	public static BoatDamage CurrentBoatDamage;

	private ConfigEntry<bool> _hudVisible;

	private ConfigEntry<KeyCode> _hudToggleKey;

	private List<HUDPanel> _panels;

	private void Awake()
	{
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Utils.ParseProfilesString(((BaseUnityPlugin)this).Config.Bind<string>("ShipProfiles", "Profiles", "Kakam=400;Cog=700;Dhow=800;Junk=4000;Sanbuq=6000;Brig=10000;Jong=17000;Gallus=400;Caelanor=2000;Clipper=10000;Gloriana=12000;Chronian=17000;Leopard=20000;Shroud Small=600;Shroud Large=9000;BOAT CUTTER=250;DNG=150", "List of ship profiles and their max carrying capacities (Format: Key=Capacity;)").Value);
			_panels = new List<HUDPanel>
			{
				new InstrumentsPanel(),
				new CargoPanel(),
				new SoundingPanel(),
				new StatusPanel(),
				new WeatherPanel()
			};
			((object)((BaseUnityPlugin)this).Info.Metadata).GetType().GetProperty("Version")?.SetValue(((BaseUnityPlugin)this).Info.Metadata, new Version(PluginInfo.Version));
			_hudVisible = ((BaseUnityPlugin)this).Config.Bind<bool>("HUDSections", "HudVisible", true, "Master switch for the whole overlay.");
			_hudToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("HUDSections", "HudToggleKey", (KeyCode)289, "The key that flips the HUD visibility at sea.");
			foreach (HUDPanel panel in _panels)
			{
				panel.BindConfig(((BaseUnityPlugin)this).Config);
			}
			new Harmony(PluginInfo.GUID).PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[" + PluginInfo.Name + "] Telemetry system successfully initialized."));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("[" + PluginInfo.Name + "] Critical failure hook mapping: " + ex.Message));
		}
	}

	private void OnGUI()
	{
		//IL_003e: 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_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: 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: Expected O, but got Unknown
		//IL_0081: 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_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Expected O, but got Unknown
		//IL_0111: Expected O, but got Unknown
		if (!_hudVisible.Value || !GameState.playing || GameState.justStarted || (Object)(object)GameState.lastBoat == (Object)null)
		{
			return;
		}
		BoatDamage component = ((Component)GameState.lastBoat).GetComponent<BoatDamage>();
		GUIStyle val = new GUIStyle(GUI.skin.box);
		val.normal.background = Utils.MakeTexture(2, 2, new Color(0.29f, 0.35f, 0.41f, 0.25f));
		val.padding = new RectOffset(10, 10, 10, 10);
		val.stretchWidth = true;
		val.stretchHeight = true;
		GUIStyle defaultStyle = new GUIStyle(GUI.skin.label)
		{
			fontSize = HUDPanel.FontSize,
			richText = true,
			wordWrap = false,
			clipping = (TextClipping)0
		};
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Space(20f);
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		GUILayout.Space(20f);
		GUILayout.BeginVertical(val, (GUILayoutOption[])(object)new GUILayoutOption[3]
		{
			GUILayout.MinWidth(200f),
			GUILayout.ExpandWidth(true),
			GUILayout.ExpandHeight(true)
		});
		foreach (HUDPanel panel in _panels)
		{
			panel.DrawLines(defaultStyle, component);
		}
		GUILayout.EndVertical();
		GUILayout.EndVertical();
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();
	}

	private void Update()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		if (!GameState.playing || GameState.justStarted)
		{
			return;
		}
		if (Input.GetKeyDown(_hudToggleKey.Value))
		{
			_hudVisible.Value = !_hudVisible.Value;
		}
		if (!_hudVisible.Value || !((Object)(object)GameState.lastBoat != (Object)null))
		{
			return;
		}
		BoatDamage component = ((Component)GameState.lastBoat).GetComponent<BoatDamage>();
		foreach (HUDPanel panel in _panels)
		{
			panel.UpdateTelemetry(component);
		}
	}
}
public class CargoPanel : HUDPanel
{
	private enum BurdenLevel
	{
		Light,
		Normal,
		Loaded,
		Overloaded
	}

	private float _calculatedDeadweight;

	private float _nextCheckTime;

	private ConfigFile _configFile;

	private string _lastCachedBoatName = "";

	private ConfigEntry<float> _activeMaxCapacity;

	private ConfigEntry<float> _activeMaxFreeboard;

	private float _currentWaterLevel;

	public override void BindConfig(ConfigFile config)
	{
		IsEnabled = config.Bind<bool>("HUDSections", "ShowCargo", true, "Master switch for the Cargo panel.");
		_configFile = config;
	}

	public override void UpdateTelemetry(BoatDamage currentBoat)
	{
		if (!IsEnabled.Value || (Object)(object)currentBoat == (Object)null)
		{
			return;
		}
		_currentWaterLevel = currentBoat.waterLevel;
		if (!(Time.time >= _nextCheckTime))
		{
			return;
		}
		_nextCheckTime = Time.time + 1f;
		if (((Object)currentBoat).name != _lastCachedBoatName && _configFile != null)
		{
			_lastCachedBoatName = ((Object)currentBoat).name;
			SetupActiveBoatConfig(((Object)currentBoat).name);
		}
		BoatMass component = ((Component)currentBoat).GetComponent<BoatMass>();
		if (!((Object)(object)component != (Object)null))
		{
			return;
		}
		FieldInfo field = typeof(BoatMass).GetField("partsMass", BindingFlags.Instance | BindingFlags.NonPublic);
		FieldInfo field2 = typeof(BoatMass).GetField("itemsOnBoat", BindingFlags.Instance | BindingFlags.NonPublic);
		float num = 0f;
		if (field != null)
		{
			num += (float)field.GetValue(component);
		}
		if (field2 != null && field2.GetValue(component) is List<ItemRigidbody> list)
		{
			foreach (ItemRigidbody item in list)
			{
				if ((Object)(object)item != (Object)null && (Object)(object)item.GetCurrentInventorySlot() == (Object)null)
				{
					num += item.GetBody().mass;
				}
			}
		}
		if ((Object)(object)GameState.lastBoat == (Object)(object)((Component)currentBoat).gameObject && (Object)(object)GameState.currentBoat != (Object)null && (Object)(object)GameState.currentBoat.parent == (Object)(object)((Component)currentBoat).transform)
		{
			num += 160f;
		}
		float num2 = currentBoat.waterLevel * currentBoat.waterUnitsCapacity;
		num += num2;
		_calculatedDeadweight = num;
	}

	private void SetupActiveBoatConfig(string boatName)
	{
		ShipProfile profile = Utils.GetProfile(boatName);
		string text = "Cargo - " + ((profile != null) ? profile.DisplayName : boatName);
		float num = profile?.MaxCapacity ?? 4000f;
		float num2 = profile?.MaxFreeboard ?? 1.5f;
		_activeMaxCapacity = _configFile.Bind<float>(text, "MaxCapacity", num, "Maximum safe carrying capacity in lbs.");
		_activeMaxFreeboard = _configFile.Bind<float>(text, "MaxFreeboard", num2, "Target empty freeboard height in meters.");
	}

	public override void DrawLines(GUIStyle defaultStyle, BoatDamage currentBoat)
	{
		if (IsEnabled.Value && !((Object)(object)currentBoat == (Object)null) && _activeMaxCapacity != null)
		{
			BeginPanel();
			DrawHUDLine($"<color={ColorLabel}>Deadweight:</color> {_calculatedDeadweight:F0}lbs", defaultStyle);
			float value = _activeMaxFreeboard.Value;
			float value2 = _activeMaxCapacity.Value;
			float num = _calculatedDeadweight / value2 * (value * 0.5f);
			float num2 = value - num - _currentWaterLevel * value;
			if (num2 < 0f)
			{
				num2 = 0f;
			}
			string arg = ColorLabel;
			if (num2 <= 0.3f || _currentWaterLevel > 0.7f)
			{
				arg = ColorDanger;
			}
			else if (num2 <= 0.6f || _currentWaterLevel > 0.3f)
			{
				arg = "#bd7f2e";
			}
			DrawHUDLine($"<color={arg}>Freeboard:</color> {num2:F1}m", defaultStyle);
			float num3 = _calculatedDeadweight / value2;
			string text;
			string text2;
			if (num3 > 1f || _currentWaterLevel >= 0.9f)
			{
				text = BurdenLevel.Overloaded.ToString();
				text2 = ColorDanger;
			}
			else if (num3 > 0.75f || _currentWaterLevel > 0.4f)
			{
				text = BurdenLevel.Loaded.ToString();
				text2 = "#bd7f2e";
			}
			else if (num3 > 0.25f)
			{
				text = BurdenLevel.Normal.ToString();
				text2 = "#ffffff";
			}
			else
			{
				text = BurdenLevel.Light.ToString();
				text2 = ColorMuted;
			}
			DrawHUDLine("<color=" + ColorLabel + ">Burden:</color> <color=" + text2 + ">" + text + "</color>", defaultStyle);
			EndPanel();
		}
	}
}
public abstract class HUDPanel
{
	protected ConfigEntry<bool> IsEnabled;

	protected readonly Color BackgroundColor = new Color(0.047f, 0.035f, 0.02f, 0.3f);

	protected readonly string ColorLabel = "#F5EEDCE0";

	protected readonly string ColorMuted = "#A19B8EE0";

	protected readonly string ColorDanger = "#ff3333";

	public static Font Font { get; private set; }

	public static int FontSize { get; set; } = 14;

	protected HUDPanel()
	{
		//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)
		Font = GetGameFont();
	}

	protected void BeginPanel()
	{
		//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_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		//IL_0049: 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_0081: Expected O, but got Unknown
		GUIStyle val = new GUIStyle(GUI.skin.box);
		val.normal.background = Utils.MakeTexture(2, 2, BackgroundColor);
		val.margin = new RectOffset(0, 0, 0, 8);
		val.padding = new RectOffset(12, 12, 12, 12);
		val.stretchWidth = true;
		val.stretchHeight = true;
		GUILayout.BeginVertical(val, (GUILayoutOption[])(object)new GUILayoutOption[3]
		{
			GUILayout.MinWidth(200f),
			GUILayout.ExpandWidth(true),
			GUILayout.ExpandHeight(true)
		});
	}

	protected void EndPanel()
	{
		GUILayout.EndVertical();
	}

	private Font GetGameFont()
	{
		Font result = null;
		Object[] array = Resources.FindObjectsOfTypeAll(typeof(Font));
		foreach (Object obj in array)
		{
			Font val = (Font)(object)((obj is Font) ? obj : null);
			if (!((Object)(object)val == (Object)null))
			{
				string text = ((Object)val).name ?? "";
				if (text.IndexOf("Arial", StringComparison.OrdinalIgnoreCase) < 0 && text.Length > 0)
				{
					result = val;
					break;
				}
			}
		}
		return result;
	}

	public abstract void BindConfig(ConfigFile config);

	public abstract void UpdateTelemetry(BoatDamage currentBoat);

	public abstract void DrawLines(GUIStyle defaultStyle, BoatDamage currentBoat);

	protected void DrawHUDLine(string text, GUIStyle style)
	{
		if (style != null)
		{
			style.fontSize = FontSize;
			style.font = Font;
			style.richText = true;
		}
		GUILayout.Label(text, style, Array.Empty<GUILayoutOption>());
	}
}
public class InstrumentsPanel : HUDPanel
{
	private ConfigEntry<bool> _requireChipLog;

	private ConfigEntry<bool> _requireCompass;

	private bool _hasChipLog;

	private bool _hasCompass;

	private float _nextCheckTime;

	public override void BindConfig(ConfigFile config)
	{
		IsEnabled = config.Bind<bool>("HUDSections", "ShowInstruments", true, "Master switch for the Instruments panel.");
		_requireChipLog = config.Bind<bool>("EquipmentRequirements", "RequireChipLogForSpeed", true, "Speed appears only with a chip log aboard.");
		_requireCompass = config.Bind<bool>("EquipmentRequirements", "RequireCompassForHeading", true, "Heading appears only with a compass aboard.");
	}

	public override void UpdateTelemetry(BoatDamage currentBoat)
	{
		if (!IsEnabled.Value || (Object)(object)currentBoat == (Object)null || !(Time.time >= _nextCheckTime))
		{
			return;
		}
		_nextCheckTime = Time.time + 1f;
		_hasChipLog = !_requireChipLog.Value;
		_hasCompass = !_requireCompass.Value;
		Transform[] componentsInChildren = ((Component)currentBoat).GetComponentsInChildren<Transform>(true);
		CheckTransforms(componentsInChildren);
		if ((_requireCompass.Value && !_hasCompass) || (_requireChipLog.Value && !_hasChipLog))
		{
			GameObject val = GameObject.FindGameObjectWithTag("Player");
			if ((Object)(object)val != (Object)null)
			{
				Transform[] componentsInChildren2 = val.GetComponentsInChildren<Transform>(true);
				CheckTransforms(componentsInChildren2);
			}
		}
	}

	private void CheckTransforms(Transform[] transforms)
	{
		foreach (Transform val in transforms)
		{
			if (!((Object)(object)val == (Object)null))
			{
				string text = ((Object)val).name.ToLower();
				if (_requireCompass.Value && (text.Contains("compass") || text.Contains("bussola")))
				{
					_hasCompass = true;
				}
				if (_requireChipLog.Value && (text.Contains("chip log") || text.Contains("chiplog")))
				{
					_hasChipLog = true;
				}
			}
		}
	}

	public override void DrawLines(GUIStyle defaultStyle, BoatDamage currentBoat)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		if (!IsEnabled.Value || (Object)(object)currentBoat == (Object)null)
		{
			return;
		}
		Rigidbody component = ((Component)currentBoat).GetComponent<Rigidbody>();
		if ((Object)(object)component == (Object)null)
		{
			return;
		}
		BeginPanel();
		if (_hasChipLog)
		{
			float num = Vector3.Dot(component.velocity, ((Component)currentBoat).transform.forward) * 1.94384f;
			if (Mathf.Abs(num) < 0.1f)
			{
				num = 0f;
			}
			DrawHUDLine($"<color={ColorLabel}>Speed: </color>{num:F1}kts", defaultStyle);
		}
		else
		{
			DrawHUDLine("<color=" + ColorMuted + ">Speed: </color>[Requires Chip Log]", defaultStyle);
		}
		if (_hasCompass)
		{
			float num2 = ((Component)currentBoat).transform.eulerAngles.y;
			if (num2 < 0f)
			{
				num2 += 360f;
			}
			string compassDirection = Utils.GetCompassDirection(num2);
			DrawHUDLine($"<color={ColorLabel}>Heading: </color>{num2:F0}° {compassDirection}", defaultStyle);
		}
		else
		{
			DrawHUDLine("<color=" + ColorMuted + ">Heading: </color>[Requires Compass]", defaultStyle);
		}
		float num3 = Vector3.Angle(((Component)currentBoat).transform.up, Vector3.up);
		float num4 = ((Component)currentBoat).transform.localEulerAngles.z;
		if (num4 > 180f)
		{
			num4 -= 360f;
		}
		string text = "";
		if (num3 > 0.5f)
		{
			text = ((num4 > 0f) ? "P" : "S");
		}
		string text2 = ((num3 > currentBoat.safeAngleLimit) ? ColorDanger : ColorLabel);
		DrawHUDLine($"<color={text2}>Heel Angle: </color>{num3:F1}° {text}/{currentBoat.safeAngleLimit:F0}°", defaultStyle);
		EndPanel();
	}
}
public static class PluginInfo
{
	public static readonly string GUID = ((AssemblyMetadataAttribute)Attribute.GetCustomAttributes(typeof(BoatStatusHUDPlugin).Assembly, typeof(AssemblyMetadataAttribute)).FirstOrDefault((Attribute x) => ((AssemblyMetadataAttribute)x).Key == "PluginGUID"))?.Value ?? "com.luizbag.sailwind.boatstatushud";

	public static readonly string Name = ((AssemblyMetadataAttribute)Attribute.GetCustomAttributes(typeof(BoatStatusHUDPlugin).Assembly, typeof(AssemblyMetadataAttribute)).FirstOrDefault((Attribute x) => ((AssemblyMetadataAttribute)x).Key == "PluginName"))?.Value ?? "BoatStatusHUD";

	public static readonly string Version = typeof(BoatStatusHUDPlugin).Assembly.GetName().Version.ToString(3);
}
public class ShipProfile
{
	public string Key;

	public string DisplayName;

	public float MaxCapacity;

	public float MaxFreeboard;
}
public class ShipProfileList
{
	public ShipProfile[] Profiles;
}
public class SoundingPanel : HUDPanel
{
	private float _seaDepth = 300f;

	private float _keelClearance = 300f;

	private float _nextCheckTime;

	public override void BindConfig(ConfigFile config)
	{
		IsEnabled = config.Bind<bool>("HUDSections", "ShowSounding", true, "Master switch for the Sounding panel.");
	}

	public override void UpdateTelemetry(BoatDamage currentBoat)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		if (!IsEnabled.Value || (Object)(object)currentBoat == (Object)null || !(Time.time >= _nextCheckTime))
		{
			return;
		}
		_nextCheckTime = Time.time + 0.5f;
		Vector3 position = GameState.lastBoat.position;
		Vector3 down = Vector3.down;
		float num = 300f;
		RaycastHit val = default(RaycastHit);
		if (Physics.Raycast(position, down, ref val, num))
		{
			_seaDepth = ((RaycastHit)(ref val)).distance;
			_keelClearance = _seaDepth - 1.5f;
			if (_seaDepth < 0f)
			{
				_seaDepth = 0f;
			}
			if (_keelClearance < 0f)
			{
				_keelClearance = 0f;
			}
		}
		else
		{
			_seaDepth = 300f;
			_keelClearance = 300f;
		}
	}

	public override void DrawLines(GUIStyle defaultStyle, BoatDamage currentBoat)
	{
		if (IsEnabled.Value && !((Object)(object)currentBoat == (Object)null))
		{
			BeginPanel();
			DrawHUDLine($"<color={ColorLabel}>Sea Depth: </color>{_seaDepth:F1}m", defaultStyle);
			if (_keelClearance <= 0.1f)
			{
				DrawHUDLine($"<color={ColorDanger}>Keel Clearance: </color>{_keelClearance:F1}m", defaultStyle);
			}
			else if (_keelClearance <= 2f)
			{
				DrawHUDLine($"<color=#bd7f2e>Keel Clearance: </color>{_keelClearance:F1}m", defaultStyle);
			}
			else
			{
				DrawHUDLine($"<color={ColorLabel}>Keel Clearance: </color>{_keelClearance:F1}m", defaultStyle);
			}
			EndPanel();
		}
	}
}
public class StatusPanel : HUDPanel
{
	private float _hullIntegrityPercent = 100f;

	private float _bilgeWaterPercent;

	private float _nextCheckTime;

	public override void BindConfig(ConfigFile config)
	{
		IsEnabled = config.Bind<bool>("HUDSections", "ShowStatus", true, "Master switch for the Status panel.");
	}

	public override void UpdateTelemetry(BoatDamage currentBoat)
	{
		if (IsEnabled.Value && !((Object)(object)currentBoat == (Object)null) && Time.time >= _nextCheckTime)
		{
			_nextCheckTime = Time.time + 0.5f;
			_hullIntegrityPercent = (1f - currentBoat.hullDamage) * 100f;
			if (_hullIntegrityPercent < 0f)
			{
				_hullIntegrityPercent = 0f;
			}
			_bilgeWaterPercent = currentBoat.waterLevel * 100f;
		}
	}

	public override void DrawLines(GUIStyle defaultStyle, BoatDamage currentBoat)
	{
		if (IsEnabled.Value && !((Object)(object)currentBoat == (Object)null))
		{
			BeginPanel();
			string arg = ColorLabel;
			if (_hullIntegrityPercent <= 30f)
			{
				arg = ColorDanger;
			}
			else if (_hullIntegrityPercent <= 75f)
			{
				arg = "#bd7f2e";
			}
			DrawHUDLine($"<color={arg}>Hull Integrity: </color>{_hullIntegrityPercent:F1}%", defaultStyle);
			string arg2 = ColorLabel;
			if (_bilgeWaterPercent >= 50f)
			{
				arg2 = ColorDanger;
			}
			else if (_bilgeWaterPercent > 15f)
			{
				arg2 = "#bd7f2e";
			}
			DrawHUDLine($"<color={arg2}>Bilge Water: </color>{_bilgeWaterPercent:F1}%", defaultStyle);
			EndPanel();
		}
	}
}
public static class Utils
{
	private static Dictionary<string, ShipProfile> _profileCache = new Dictionary<string, ShipProfile>();

	public static Texture2D MakeTexture(int width, int height, Color col)
	{
		//IL_000f: 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_0021: 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)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Expected O, but got Unknown
		Color[] array = (Color[])(object)new Color[width * height];
		for (int i = 0; i < array.Length; i++)
		{
			array[i] = col;
		}
		Texture2D val = new Texture2D(width, height);
		val.SetPixels(array);
		val.Apply();
		return val;
	}

	public static void ParseProfilesString(string profilesRawData)
	{
		_profileCache.Clear();
		if (string.IsNullOrEmpty(profilesRawData))
		{
			return;
		}
		string[] array = profilesRawData.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			string[] array2 = array[i].Split(new char[1] { '=' });
			if (array2.Length != 2)
			{
				continue;
			}
			string text = array2[0].Trim();
			if (float.TryParse(array2[1].Trim(), out var result))
			{
				float num = 1f + result / 10000f;
				if (num > 2.8f)
				{
					num = 2.8f;
				}
				_profileCache[text.ToLower()] = new ShipProfile
				{
					Key = text,
					DisplayName = text,
					MaxCapacity = result,
					MaxFreeboard = num
				};
			}
		}
	}

	public static ShipProfile GetProfile(string gameObjectName)
	{
		if (string.IsNullOrEmpty(gameObjectName))
		{
			return null;
		}
		string text = gameObjectName.ToLower();
		foreach (KeyValuePair<string, ShipProfile> item in _profileCache)
		{
			if (text.Contains(item.Key))
			{
				return item.Value;
			}
		}
		return null;
	}

	public static string GetCompassDirection(float degrees)
	{
		string[] obj = new string[16]
		{
			"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW",
			"SW", "WSW", "W", "WNW", "NW", "NNW"
		};
		int num = Mathf.RoundToInt(degrees / 22.5f) % 16;
		return obj[num];
	}
}
public class WeatherPanel : HUDPanel
{
	private bool _hasWindIndicator;

	private ConfigEntry<bool> _requireWindicator;

	private string _windString = "Calm";

	private string _conditionsString = "Fair";

	private string _conditionsColor = "#ffffff";

	private float _nextCheckTime;

	public override void BindConfig(ConfigFile config)
	{
		IsEnabled = config.Bind<bool>("HUDSections", "ShowWeather", true, "Master switch for the Weather panel.");
		_requireWindicator = config.Bind<bool>("EquipmentRequirements", "RequireWindicatorForWind", true, "Wind speed and direction appear only with a windicator aboard.");
	}

	public override void UpdateTelemetry(BoatDamage currentBoat)
	{
		//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_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: 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)
		if (!IsEnabled.Value || (Object)(object)currentBoat == (Object)null || !(Time.time >= _nextCheckTime))
		{
			return;
		}
		_nextCheckTime = Time.time + 1f;
		_hasWindIndicator = CheckForWindIndicators(currentBoat);
		if (_hasWindIndicator)
		{
			Vector3 wind = Vector3.zero;
			if ((Object)(object)Weather.instance != (Object)null)
			{
				FieldInfo field = typeof(Weather).GetField("wind", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					wind = (Vector3)field.GetValue(Weather.instance);
				}
				else
				{
					float num = (((Object)(object)Sun.sun != (Object)null) ? Sun.sun.localTime : 12f) * 15f;
					wind = Quaternion.Euler(0f, num, 0f) * Vector3.forward * 6f;
				}
			}
			_windString = ConvertWindToSailorTerms(wind);
		}
		UpdateWeatherConditions();
	}

	private bool CheckForWindIndicators(BoatDamage boat)
	{
		if (!_requireWindicator.Value)
		{
			return true;
		}
		BoatCustomParts component = ((Component)boat).GetComponent<BoatCustomParts>();
		if ((Object)(object)component != (Object)null && component.availableParts != null)
		{
			foreach (BoatPart availablePart in component.availableParts)
			{
				if (availablePart == null)
				{
					continue;
				}
				BoatPartOption activeOption = availablePart.GetActiveOption();
				if (!((Object)(object)activeOption == (Object)null))
				{
					string text = ((Object)((Component)activeOption).gameObject).name.ToLower();
					if (text.Contains("windicator") || text.Contains("tell tale") || text.Contains("wind compass"))
					{
						return true;
					}
				}
			}
		}
		return false;
	}

	private string ConvertWindToSailorTerms(Vector3 wind)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		float magnitude = ((Vector3)(ref wind)).magnitude;
		if (magnitude < 0.1f)
		{
			return "Calm";
		}
		float num = Mathf.Atan2(wind.x, wind.z) * 57.29578f;
		if (num < 0f)
		{
			num += 360f;
		}
		string compassDirection = Utils.GetCompassDirection(num);
		string text = ((magnitude < 2f) ? "Light Air" : ((magnitude < 5f) ? "Breeze" : ((magnitude < 10f) ? "Fresh Breeze" : ((!(magnitude < 18f)) ? "Gale" : "Strong Wind"))));
		return compassDirection + " " + text;
	}

	private void UpdateWeatherConditions()
	{
		float rainIntensity = GameState.rainIntensity;
		if (rainIntensity > 0.6f)
		{
			_conditionsString = "Tempest";
			_conditionsColor = ColorDanger;
		}
		else if (rainIntensity > 0.1f)
		{
			_conditionsString = "Squally";
			_conditionsColor = "#bd7f2e";
		}
		else if (rainIntensity > 0f)
		{
			_conditionsString = "Moderate";
			_conditionsColor = "#ffffff";
		}
		else
		{
			_conditionsString = "Fair";
			_conditionsColor = "#44cc44";
		}
	}

	public override void DrawLines(GUIStyle defaultStyle, BoatDamage currentBoat)
	{
		if (IsEnabled.Value && !((Object)(object)currentBoat == (Object)null))
		{
			BeginPanel();
			if (_hasWindIndicator)
			{
				DrawHUDLine("<color=" + ColorLabel + ">Wind: </color>" + _windString, defaultStyle);
			}
			else
			{
				DrawHUDLine("<color=" + ColorMuted + ">Wind: </color>No Indicator Aboard", defaultStyle);
			}
			DrawHUDLine("<color=" + ColorLabel + ">Conditions: </color><color=" + _conditionsColor + ">" + _conditionsString + "</color>", defaultStyle);
			EndPanel();
		}
	}
}