Decompiled source of SailInfo v1.1.10

SailInfo.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("SailInfo")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SailInfo")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2eaa768e-251a-47e7-b1c7-0b5ce52789c9")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SailInfo;

[BepInPlugin("pr0skynesis.sailinfo", "SailInfo", "1.1.10")]
public class SailInfoMain : BaseUnityPlugin
{
	public const string pluginGuid = "pr0skynesis.sailinfo";

	public const string pluginName = "SailInfo";

	public const string pluginVersion = "1.1.10";

	public static ConfigEntry<bool> winchesInfoConfig;

	public static ConfigEntry<bool> rudderHUDConfig;

	public static ConfigEntry<bool> winchesOutConfig;

	public static ConfigEntry<bool> winchesOutDegreeConfig;

	public static ConfigEntry<bool> winchesBarConfig;

	public static ConfigEntry<bool> sailEfficiencyConfig;

	public static ConfigEntry<bool> sailForwardForceConfig;

	public static ConfigEntry<bool> sailSidewaysForceConfig;

	public static ConfigEntry<bool> flipWinchesOutConfig;

	public static ConfigEntry<bool> sailNameConfig;

	public static ConfigEntry<bool> uniqueSailNameConfig;

	public static ConfigEntry<bool> simpleUniqueNamesConfig;

	public static ConfigEntry<bool> coloredWinchesConfig;

	public static ConfigEntry<bool> rudderBarConfig;

	public static ConfigEntry<bool> windSpeedConfig;

	public static ConfigEntry<bool> windSpeedBeaufortConfig;

	public static ConfigEntry<bool> windDirectionConfig;

	public static ConfigEntry<bool> windDirectionNESWConfig;

	public static ConfigEntry<bool> windRelativeConfig;

	public static ConfigEntry<bool> windRelativeColorConfig;

	public static ConfigEntry<bool> boatHeadingConfig;

	public static ConfigEntry<bool> approximateBoatHeading;

	public static ConfigEntry<bool> boatSpeedConfig;

	public static ConfigEntry<bool> boatVMGConfig;

	public static ConfigEntry<bool> nauticalMilePerHourConfig;

	public static ConfigEntry<bool> boatHeelingConfig;

	public static ConfigEntry<bool> showCoordinatesConfig;

	public static ConfigEntry<bool> showGlobalTimeConfig;

	public static ConfigEntry<bool> showLocalTimeConfig;

	public void Awake()
	{
		//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ac: Expected O, but got Unknown
		//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_04bb: Expected O, but got Unknown
		//IL_04c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cf: Expected O, but got Unknown
		//IL_0521: Unknown result type (might be due to invalid IL or missing references)
		//IL_052f: Expected O, but got Unknown
		//IL_050c: Unknown result type (might be due to invalid IL or missing references)
		//IL_051a: Expected O, but got Unknown
		//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f4: Expected O, but got Unknown
		winchesInfoConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("A) Main Switches", "winchesInfo", true, "Enables or disables the winches information entirely. Requires restarting the game.");
		rudderHUDConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("A) Main Switches", "rudderHUD", true, "Enables or disables the rudder HUD entirely. Requires restarting the game.");
		winchesOutConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Winches Display: 1. Sail Trimming and Efficiency", "winchesOutText", true, "Shows 'X out' when looking at winches. 0 means the winch is fully tightened in, 100 means it's fully released. Set to false to disable.");
		winchesOutDegreeConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Winches Display: 1. Sail Trimming and Efficiency", "winchesOutDegree", true, "Replaces the 'X out' text with the degrees the sail is out, e.g. '45° out'. THIS REQUIRES THE (winchesOutText) OPTION TO BE SET TO TRUE! Set to false to disable.");
		winchesBarConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Winches Display: 1. Sail Trimming and Efficiency", "winchesBar", true, "Shows a loading bar type of thing when looking at winches. Empty bar means the winch is fully tightened in, 100 means it's fully released. Set to false to disable.");
		sailEfficiencyConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Winches Display: 1. Sail Trimming and Efficiency", "sailEfficiency", true, "Shows the efficiency of the sail attached to the winch you are looking at. Does not apply to halyard winches. Negative means sail is pushing backwards. Maximize to find the best trim. Set to false to disable.");
		sailForwardForceConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Winches Display: 1. Sail Trimming and Efficiency", "sailForwardForce", false, "Shows how close the FORWARD force generated by the sail is to the maximum. 0% means no force forward, 100% means maximum force forward. Maximize for best result. This was called Sail Efficiency up to v1.1.8. Set to true to enable.");
		sailSidewaysForceConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Winches Display: 1. Sail Trimming and Efficiency", "sailSidewayForce", false, "Shows how close the SIDEWAY force generated by the sail is to the maximum. 0% means no force sideway, 100% means maximum force sideway. Minimize for best result. Set to true to enable.");
		flipWinchesOutConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Winches Display: 1. Sail Trimming and Efficiency", "flipWinchesOut", true, "Flips the 'X out' when looking at halyard winches of sail that folds by releasing the rope, like junk sails and some gaffs. When true the sail will be at 100 out when fully opened and at 0 when close, making it more consistent with other type of sail.");
		sailNameConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Winches Display: 2. Sail Names", "sailName", false, "Shows the name of the sail attached to the winch currently looked at. Set to true to enable.");
		uniqueSailNameConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Winches Display: 2. Sail Names", "uniqueSailName", true, "Adds a colored dot next to the sail name. The color of the dot is different for sail with the same name. This helps differentiating winches that control the same type of sail (e.g. if you have two squares of the same size on one mast and don't know wich halyard controls what). THIS REQUIRES THE (sailName) OPTION TO BE SET TO TRUE! Set to true to enable.");
		simpleUniqueNamesConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Winches Display: 2. Sail Names", "simpleUniqueSailName", false, "Uses simple prefixes for sail names (Bottom, Middle, Top, Highest) instead of historical ones. THIS REQUIRES THE (sailName) OPTION TO BE SET TO TRUE! Set to true to enable.");
		coloredWinchesConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("B) Winches Display: 2. Sail Names", "coloredWinches", false, "Colors all the winches attached to a single sail of the same color, making it easier to identify. Change to true to enable.");
		rudderBarConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 5. Other", "rudderBar", true, "Shows a loading bar type of thing indicating how much the rudder is turned either way.  Set to false to disable.");
		windSpeedConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 1. Apparent Wind", "windSpeed", true, "Shows the APPARENT wind speed.  Set to false to disable.");
		windSpeedBeaufortConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 1. Apparent Wind", "windSpeedBeaufort", true, "Replaces wind speed with Beaufort scale descriptor words (e.g. Calm, Light Breeze, Gale, etc.). THIS REQUIRES THE (windSpeed) OPTION TO BE SET TO TRUE! Set to false to disable.");
		windDirectionConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 1. Apparent Wind", "windDirection", true, "Shows APPARENT wind direction in degree, relative to the world (e.g. 45° means the APPARENT wind comes from the North-West).  Set to false to disable.");
		windDirectionNESWConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 1. Apparent Wind", "windDirectionNESW", true, "Shows the approximate cardinal direction of the APPARENT wind (e.g. wind coming from 45° will be shown as NW instead of it's exact numerical value. Set to false to disable. THIS REQUIRES THE (windDirection) TO BE SET TO TRUE!");
		windRelativeConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 2. Point of Sail", "windAngleToBoat", true, "Shows the angle (0°-180°) between the APPARENT wind and the boat forward direction. Negative angles mean the wind comes from the left of the boat. Set to false to disable.");
		windRelativeColorConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 2. Point of Sail", "windAngleToBoatColor", true, "Wind direction relative to boat displayed in green it wind comes from the right, red if wind comes from the left. THIS REQUIRES THE (windAngleToBoat) TO BE SET TO TRUE! Set to false to disable.");
		boatHeadingConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 3. Heading", "boatHeading", false, "Shows the boat heading in degrees. Set to false to disable.");
		approximateBoatHeading = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 3. Heading", "approximateBoatHeading", true, "Shows the approximate boat heading in cardinal directions (e.g. N, NW, SSE, etc.). THIS REQUIRES THE (boatHeading) TO BE SET TO TRUE! Set to false to disable.");
		boatSpeedConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 4. Boat Speed", "boatSpeed", false, "Shows current boat speed in kts. Set to false to disable.");
		nauticalMilePerHourConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 4. Boat Speed", "nauticalMilePerHour", false, "Displays boat speed in nautical miles per hour instead of kts. In the game nmi/h = kts / 1.555. THIS REQUIRES THE (boatSpeed) TO BE SET TO TRUE! Change to true to enable.");
		boatVMGConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 4. Boat Speed", "boatVMG", false, "Shows the current boat VMG in kts. Set to false to disable.");
		boatHeelingConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 5. Other", "boatHeeling", false, "Shows current boat heeling in degrees.");
		showCoordinatesConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("C) Rudder HUD: 5. Other", "showCoordinates", false, "Adds latitude and longitude to the rudder HUD. Set to true to enable.");
		showGlobalTimeConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("D) Other Items: 1. Clock", "showGlobalTime", false, "Shows exact global time in the hh:mm format when looking at a clock. Set to true to enable.");
		showLocalTimeConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("D) Other Items: 1. Clock", "showLocalTime", false, "Shows exact local time in the hh:mm format when looking at a clock. Set to true to enable.");
		Harmony val = new Harmony("pr0skynesis.sailinfo");
		MethodInfo methodInfo = AccessTools.Method(typeof(GPButtonRopeWinch), "Update", (Type[])null, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(SailInfoPatches), "Update_Patch", (Type[])null, (Type[])null);
		MethodInfo methodInfo3 = AccessTools.Method(typeof(GPButtonSteeringWheel), "ExtraLateUpdate", (Type[])null, (Type[])null);
		MethodInfo methodInfo4 = AccessTools.Method(typeof(SailInfoPatches), "ExtraLateUpdate_Patch", (Type[])null, (Type[])null);
		MethodInfo methodInfo5 = AccessTools.Method(typeof(SailConnections), "Awake", (Type[])null, (Type[])null);
		MethodInfo methodInfo6 = AccessTools.Method(typeof(SailInfoPatches), "Awake_Patch", (Type[])null, (Type[])null);
		MethodInfo methodInfo7 = AccessTools.Method(typeof(Mast), "UpdateControllerAttachments", (Type[])null, (Type[])null);
		MethodInfo methodInfo8 = AccessTools.Method(typeof(SailInfoPatches), "UpdateControllerAttachments_Patch", (Type[])null, (Type[])null);
		MethodInfo methodInfo9 = AccessTools.Method(typeof(ShipItemClock), "ExtraLateUpdate", (Type[])null, (Type[])null);
		MethodInfo methodInfo10 = AccessTools.Method(typeof(SailInfoPatches), "ClockPatch", (Type[])null, (Type[])null);
		if (winchesInfoConfig.Value)
		{
			val.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)methodInfo5, new HarmonyMethod(methodInfo6), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			if (coloredWinchesConfig.Value)
			{
				val.Patch((MethodBase)methodInfo7, new HarmonyMethod(methodInfo8), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}
		if (rudderHUDConfig.Value)
		{
			val.Patch((MethodBase)methodInfo3, new HarmonyMethod(methodInfo4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}
		val.Patch((MethodBase)methodInfo9, new HarmonyMethod(methodInfo10), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}
}
public class SailInfoPatches
{
	public static Dictionary<Sail, List<RopeController>> sailRopeControllerMap = new Dictionary<Sail, List<RopeController>>();

	public static int winchColorIndex = 0;

	public static Color[] colorArray = (Color[])(object)new Color[9]
	{
		Color.black,
		Color.blue,
		Color.cyan,
		Color.gray,
		Color.green,
		Color.magenta,
		Color.red,
		Color.white,
		Color.yellow
	};

	private static bool quadrantHeld;

	[HarmonyPrefix]
	public static void Update_Patch(GPButtonRopeWinch __instance, GoPointer ___stickyClickedBy, bool ___isLookedAt)
	{
		if (___isLookedAt || Object.op_Implicit((Object)(object)___stickyClickedBy))
		{
			((GoPointerButton)__instance).description = RopeBar(__instance.rope);
		}
	}

	public static string RopeBar(RopeController rope)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		float num = rope.currentLength;
		if (SailInfoMain.flipWinchesOutConfig.Value && SailInfoMain.winchesOutConfig.Value && ((Object)rope).name.Contains("reef"))
		{
			RopeControllerSailReef val = (RopeControllerSailReef)rope;
			if (val.reverseReefing)
			{
				num = 1f - num;
			}
		}
		int num2 = 300;
		int num3 = (int)(num * (float)num2);
		string text = "";
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < num2; i++)
		{
			if (i < num3)
			{
				stringBuilder.Append("█");
			}
			else
			{
				stringBuilder.Append("░");
			}
		}
		float num4 = Mathf.Round(num * 100f);
		if (((Object)rope).name.Contains("reef"))
		{
			if (SailInfoMain.flipWinchesOutConfig.Value || SailInfoMain.sailNameConfig.Value)
			{
				foreach (KeyValuePair<Sail, List<RopeController>> item in sailRopeControllerMap)
				{
					foreach (RopeController item2 in item.Value)
					{
						if ((Object)(object)rope == (Object)(object)item2)
						{
							Sail key = item.Key;
							if (SailInfoMain.sailNameConfig.Value)
							{
								text = ((!SailInfoMain.uniqueSailNameConfig.Value) ? (text + "<size=70%>" + key.sailName + " Halyard\n</size>") : (text + "<size=70%>" + SailName(key) + " Halyard\n</size>"));
							}
							break;
						}
					}
				}
			}
			if (SailInfoMain.winchesOutConfig.Value)
			{
				text += $"<size=70%>{num4} out</size>";
			}
			if (SailInfoMain.winchesBarConfig.Value)
			{
				text += $"\n<size=3%>{stringBuilder}</size>";
			}
		}
		else
		{
			if (SailInfoMain.sailEfficiencyConfig.Value || SailInfoMain.sailForwardForceConfig.Value || SailInfoMain.sailSidewaysForceConfig.Value || SailInfoMain.sailNameConfig.Value)
			{
				foreach (KeyValuePair<Sail, List<RopeController>> item3 in sailRopeControllerMap)
				{
					foreach (RopeController item4 in item3.Value)
					{
						if ((Object)(object)rope == (Object)(object)item4)
						{
							Sail key2 = item3.Key;
							if (SailInfoMain.sailNameConfig.Value)
							{
								text = ((!SailInfoMain.uniqueSailNameConfig.Value) ? (text + "<size=70%>" + key2.sailName + "\n</size>") : (text + "<size=70%>" + SailName(key2) + "\n</size>"));
							}
							if (SailInfoMain.sailEfficiencyConfig.Value)
							{
								text += $"<size=70%>Eff: {CombinedEfficiency(key2)}% </size>";
							}
							if (SailInfoMain.sailForwardForceConfig.Value)
							{
								text += $"<size=70%>F: {SailEfficiency(key2)}% </size>";
							}
							if (SailInfoMain.sailSidewaysForceConfig.Value)
							{
								text += $"<size=70%>S: {SailInefficiency(key2)}% </size>";
							}
							if (SailInfoMain.winchesOutConfig.Value)
							{
								text = ((!SailInfoMain.winchesOutDegreeConfig.Value) ? (text + $"<size=70%>\n{num4} out</size>") : (text + $"<size=70%>\n{SailDegree(key2)}° out</size>"));
							}
						}
					}
				}
			}
			if (SailInfoMain.winchesBarConfig.Value)
			{
				text += $"\n<size=3%>{stringBuilder}</size>";
			}
		}
		return text;
	}

	private static float SailEfficiency(Sail currentSail)
	{
		FieldInfo fieldInfo = AccessTools.Field(typeof(Sail), "unamplifiedForwardForce");
		float num = (float)fieldInfo.GetValue(currentSail);
		FieldInfo fieldInfo2 = AccessTools.Field(typeof(Sail), "totalWindForce");
		float num2 = (float)fieldInfo2.GetValue(currentSail);
		return Mathf.Round(num / num2 * 100f);
	}

	private static float SailInefficiency(Sail currentSail)
	{
		FieldInfo fieldInfo = AccessTools.Field(typeof(Sail), "unamplifiedSidewayForce");
		float num = (float)fieldInfo.GetValue(currentSail);
		FieldInfo fieldInfo2 = AccessTools.Field(typeof(Sail), "totalWindForce");
		float num2 = (float)fieldInfo2.GetValue(currentSail);
		return Mathf.Abs(Mathf.Round(num / num2 * 100f));
	}

	private static float CombinedEfficiency(Sail currentSail)
	{
		float num = SailEfficiency(currentSail);
		if (num <= 0f)
		{
			return num;
		}
		float num2 = 100f - SailInefficiency(currentSail);
		return Mathf.Round((num + num2) / 2f);
	}

	private static string SailName(Sail currentSail)
	{
		FieldInfo currentInstallHeightInfo = AccessTools.Field(typeof(Sail), "currentInstallHeight");
		string[] array = new string[4] { "Main", "Topsail", "T'gallant", "Royal" };
		if (SailInfoMain.simpleUniqueNamesConfig.Value)
		{
			array[0] = "Bottom Square";
			array[1] = "Middle Square";
			array[2] = "Top Square";
			array[3] = "Highest Square";
		}
		Mast component = ((Component)((Component)currentSail).transform.parent).GetComponent<Mast>();
		Sail[] componentsInChildren = ((Component)component).GetComponentsInChildren<Sail>();
		componentsInChildren = componentsInChildren.OrderBy((Sail sail) => (float)currentInstallHeightInfo.GetValue(sail)).ToArray();
		int num = 0;
		string result = "";
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			float num2 = (float)currentInstallHeightInfo.GetValue(componentsInChildren[i]);
			if (((Object)componentsInChildren[i]).name.Contains("square"))
			{
				result = MastName(component) + array[num];
				num++;
			}
			else if (((Object)componentsInChildren[i]).name.Contains("gaff"))
			{
				result = MastName(component) + "Gaff";
			}
			else if (((Object)componentsInChildren[i]).name.Contains("lateen"))
			{
				result = MastName(component) + "Lateen";
			}
			else if (((Object)componentsInChildren[i]).name.Contains("junk"))
			{
				result = MastName(component) + "Junk";
			}
			else if (((Object)componentsInChildren[i]).name.Contains("junklateen"))
			{
				result = MastName(component) + "Fin";
			}
			else if (((Object)componentsInChildren[i]).name.Contains("jib"))
			{
				result = MastName(component) + "Jib";
			}
			else if (((Object)componentsInChildren[i]).name.Contains("genoa"))
			{
				result = MastName(component) + "Genoa";
			}
			if (((Object)currentSail).name == ((Object)componentsInChildren[i]).name)
			{
				return result;
			}
		}
		return "";
	}

	private static string MastName(Mast currentMast)
	{
		Mast[] componentsInChildren = ((Component)GameState.currentBoat).GetComponentsInChildren<Mast>();
		int num = componentsInChildren.Length;
		for (int i = 0; i < num; i++)
		{
			if (((Object)componentsInChildren[i]).name.Contains("bowsprit") || ((Object)componentsInChildren[i]).name.Contains("stay"))
			{
				num--;
			}
		}
		if (num > 1)
		{
			if (((Object)currentMast).name.Contains("bowsprit"))
			{
				return "Bowsprit ";
			}
			if (((Object)currentMast).name == "mast_front_" || ((Object)currentMast).name == "mast_Front_0" || ((Object)currentMast).name == "mast_Front_1")
			{
				return "Foremast ";
			}
			if (((Object)currentMast).name == "mast" || ((Object)currentMast).name == "mast_1" || ((Object)currentMast).name == "mast_0_extension" || ((Object)currentMast).name == "mast_1_extension" || ((Object)currentMast).name == "mast_center" || ((Object)currentMast).name == "mast_mid_0" || ((Object)currentMast).name == "mast_mid_1" || ((Object)currentMast).name == "mast_front" || ((Object)currentMast).name == "mast_Back_1" || ((Object)currentMast).name == "mast_Back_2")
			{
				return "Mainmast ";
			}
			if (((Object)currentMast).name == "mast_002" || ((Object)currentMast).name == "mast_001" || ((Object)currentMast).name == "mast_mizzen_0" || ((Object)currentMast).name == "mast_mizzen_1" || ((Object)currentMast).name == "mast_mizzen")
			{
				return "Mizzen ";
			}
		}
		return "";
	}

	private static void WinchColor(GPButtonRopeWinch winch, int winchColorIndex)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		winchColorIndex %= colorArray.Length;
		((Renderer)((Component)((Component)winch).transform).GetComponent<MeshRenderer>()).material.color = colorArray[winchColorIndex];
	}

	private static int SailDegree(Sail sail)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: 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_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: 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_0043: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = -((Component)GameState.currentBoat).transform.right;
		Vector3 val2 = (sail.squareSail ? ((Component)sail).transform.up : (-((Component)sail).transform.right));
		int num = Mathf.RoundToInt(Vector3.SignedAngle(val, val2, -Vector3.up));
		num = ((num > 90) ? (180 - num) : num);
		return (num < 0) ? (-num) : num;
	}

	[HarmonyPrefix]
	public static void ExtraLateUpdate_Patch(ref string ___description, GoPointer ___stickyClickedBy, bool ___isLookedAt, Rudder ___rudder, HingeJoint ___attachedRudder)
	{
		//IL_039b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
		if (!___isLookedAt && !Object.op_Implicit((Object)(object)___stickyClickedBy))
		{
			return;
		}
		___description = "";
		if (SailInfoMain.windSpeedConfig.Value || SailInfoMain.windDirectionConfig.Value || SailInfoMain.windRelativeConfig.Value)
		{
			___description = "Wind: ";
		}
		if (SailInfoMain.windSpeedConfig.Value)
		{
			if (SailInfoMain.windSpeedBeaufortConfig.Value)
			{
				___description = ___description + Beaufort() + " ";
			}
			else
			{
				___description += $"{Mathf.Round(WindForce())} kts ";
			}
		}
		if (SailInfoMain.windDirectionConfig.Value)
		{
			if (SailInfoMain.windDirectionNESWConfig.Value)
			{
				___description = ___description + DirectionNESW(Mathf.Round(WindDirection())) + " ";
			}
			else
			{
				___description += $"{Mathf.Round(WindDirection())}° ";
			}
		}
		if (SailInfoMain.windRelativeConfig.Value)
		{
			if (SailInfoMain.windRelativeColorConfig.Value)
			{
				float num = AngleToBoat();
				if (num > 0f)
				{
					___description += $"<color=#113905>{Mathf.Round(num)}°</color>";
				}
				else
				{
					___description += $"<color=#7C0000>{Mathf.Round(num)}°</color>";
				}
			}
			else
			{
				___description += $"{Mathf.Round(AngleToBoat())}°";
			}
		}
		if (SailInfoMain.boatHeadingConfig.Value || SailInfoMain.boatSpeedConfig.Value || SailInfoMain.boatVMGConfig.Value)
		{
			___description += "\n";
		}
		if (SailInfoMain.boatSpeedConfig.Value)
		{
			if (SailInfoMain.nauticalMilePerHourConfig.Value)
			{
				___description += $"SPD: {Mathf.Round(BoatSpeed() / 1.555f)} nmi/h ";
			}
			else
			{
				___description += $"SPD: {Mathf.Round(BoatSpeed())} kts ";
			}
		}
		if (SailInfoMain.boatHeadingConfig.Value)
		{
			if (SailInfoMain.approximateBoatHeading.Value)
			{
				___description = ___description + "HDG: " + DirectionNESW(Mathf.Round(BoatHeading())) + " ";
			}
			else
			{
				___description += $"HDG: {Mathf.Round(BoatHeading())}° ";
			}
		}
		if (SailInfoMain.boatVMGConfig.Value)
		{
			___description += $"VMG: {Mathf.Round(VMG())} kts";
		}
		if (SailInfoMain.boatHeelingConfig.Value)
		{
			___description += $"\nHeeling {Mathf.Round(Heeling())}°";
		}
		if (SailInfoMain.showCoordinatesConfig.Value)
		{
			___description = ___description + "\n" + Latitude() + ", " + Longitude();
		}
		if (SailInfoMain.rudderBarConfig.Value)
		{
			string obj = ___description;
			float currentAngle = ___rudder.currentAngle;
			JointLimits limits = ___attachedRudder.limits;
			___description = obj + "\n" + RudderBar(currentAngle, ((JointLimits)(ref limits)).max);
		}
	}

	public static string RudderBar(float currentAngle, float angleLimit)
	{
		int num = 150;
		bool flag = currentAngle <= 0f;
		string text = "░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░";
		int num2 = (int)(Math.Abs(currentAngle) * (float)num / angleLimit);
		int num3 = num - num2;
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < num; i++)
		{
			if (i < num2)
			{
				stringBuilder.Append("█");
			}
			else
			{
				stringBuilder.Append("░");
			}
		}
		StringBuilder stringBuilder2 = new StringBuilder();
		for (int j = 0; j < num; j++)
		{
			if (j < num3)
			{
				stringBuilder2.Append("░");
			}
			else
			{
				stringBuilder2.Append("█");
			}
		}
		if (flag)
		{
			return $"<size=3%>{text}█{stringBuilder}</size>";
		}
		return $"<size=3%>{stringBuilder2}█{text}</size>";
	}

	private static float WindForce()
	{
		if ((Object)(object)((Component)GameState.currentBoat).GetComponentInChildren<Sail>() != (Object)null)
		{
			return ((Vector3)(ref ((Component)GameState.currentBoat).GetComponentInChildren<Sail>().apparentWind)).magnitude;
		}
		return 0f;
	}

	private static float WindDirection()
	{
		//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_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)
		Transform currentBoat = GameState.currentBoat;
		if ((Object)(object)((Component)currentBoat).GetComponentInChildren<Sail>() != (Object)null)
		{
			Sail componentInChildren = ((Component)currentBoat).GetComponentInChildren<Sail>();
			float num = Vector3.SignedAngle(componentInChildren.apparentWind, -Vector3.forward, -Vector3.up);
			return (num < 0f) ? (num + 360f) : num;
		}
		return 0f;
	}

	private static float BoatHeading()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: 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_001e: 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)
		Transform currentBoat = GameState.currentBoat;
		Vector3 val = -((Component)currentBoat).transform.right;
		float num = Vector3.SignedAngle(val, -Vector3.forward, -Vector3.up);
		return (num < 0f) ? (num + 360f) : num;
	}

	private static float AngleToBoat()
	{
		//IL_0032: 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_003d: 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_0044: Unknown result type (might be due to invalid IL or missing references)
		Transform currentBoat = GameState.currentBoat;
		if ((Object)(object)((Component)currentBoat).GetComponentInChildren<Sail>() != (Object)null)
		{
			Sail componentInChildren = ((Component)currentBoat).GetComponentInChildren<Sail>();
			Vector3 val = -((Component)currentBoat).transform.right;
			return Vector3.SignedAngle(val, componentInChildren.apparentWind, Vector3.up);
		}
		return 0f;
	}

	private static float BoatSpeed()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		Transform currentBoat = GameState.currentBoat;
		Vector3 velocity = ((Component)currentBoat.parent).GetComponent<Rigidbody>().velocity;
		float magnitude = ((Vector3)(ref velocity)).magnitude;
		return magnitude * 1.94384f;
	}

	private static string DirectionNESW(float direction)
	{
		string[] array = new string[17]
		{
			"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW",
			"SW", "WSW", "W", "WNW", "NW", "NNW", "N"
		};
		return array[(int)Math.Floor(((double)direction + 11.25) % 360.0 / 22.5)];
	}

	private static float VMG()
	{
		//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_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		Vector3 velocity = ((Component)GameState.currentBoat.parent).GetComponent<Rigidbody>().velocity;
		Vector3 currentWind = Wind.currentWind;
		float num = Vector3.Angle(velocity, currentWind) * ((float)Math.PI / 180f);
		float num2 = ((Vector3)(ref velocity)).magnitude * 1.94384f;
		return (0f - num2) * Mathf.Cos(num);
	}

	private static string Beaufort()
	{
		if ((Object)(object)((Component)GameState.currentBoat).GetComponentInChildren<Sail>() != (Object)null)
		{
			float magnitude = ((Vector3)(ref ((Component)GameState.currentBoat).GetComponentInChildren<Sail>().apparentWind)).magnitude;
			string text = ((magnitude < 1f) ? "Calm(0) " : ((magnitude >= 1f && magnitude < 3f) ? "Light Air(1) " : ((magnitude >= 3f && magnitude < 6f) ? "Light Breeze(2) " : ((magnitude >= 6f && magnitude < 10f) ? "Gentle Breeze(3) " : ((magnitude >= 10f && magnitude < 16f) ? "Moderate Breeze(4) " : ((magnitude >= 16f && magnitude < 21f) ? "Fresh Breeze(5) " : ((magnitude >= 21f && magnitude < 27f) ? "Strong Breeze(6) " : ((magnitude >= 27f && magnitude < 33f) ? "High Wind(7) " : ((magnitude >= 33f && magnitude < 40f) ? "Gale(8) " : ((magnitude >= 40f && magnitude < 47f) ? "Strong Gale(9) " : ((magnitude >= 47f && magnitude < 55f) ? "Storm(10) " : ((magnitude >= 55f && magnitude < 63f) ? "Violent Storm(11) " : ((magnitude >= 63f) ? "Hurricane-force(12) " : "Unknown")))))))))))));
			return "<size=60%>" + text + "</size>";
		}
		return "Add at least one sail. ";
	}

	private static float Heeling()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: 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)
		//IL_0019: 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)
		Transform currentBoat = GameState.currentBoat;
		Vector3 up = ((Component)currentBoat).transform.up;
		return Vector3.SignedAngle(up, Vector3.up, -Vector3.forward);
	}

	[HarmonyPrefix]
	public static void ClockPatch(ShipItemClock __instance, bool ___isLookedAt)
	{
		if (!___isLookedAt)
		{
			return;
		}
		((GoPointerButton)__instance).description = "";
		if (SailInfoMain.showGlobalTimeConfig.Value || SailInfoMain.showLocalTimeConfig.Value)
		{
			if (SailInfoMain.showGlobalTimeConfig.Value)
			{
				float globalTime = Sun.sun.globalTime;
				((GoPointerButton)__instance).description = ((GoPointerButton)__instance).description + "\n\n" + GetTime(globalTime);
			}
			if (SailInfoMain.showLocalTimeConfig.Value)
			{
				float localTime = Sun.sun.localTime;
				((GoPointerButton)__instance).description = ((GoPointerButton)__instance).description + "\n" + GetTime(localTime);
			}
		}
	}

	private static string GetTime(float time)
	{
		int num = (int)time;
		int num2 = (int)((time - (float)num) * 60f);
		if (num2 < 10)
		{
			return $"{num}:0{num2}";
		}
		return $"{num}:{num2}";
	}

	[HarmonyPrefix]
	public static void QuadrantPatch()
	{
		if (quadrantHeld)
		{
			Sleep.instance.recoveryText.text = "<size=20%>\n\n\nLat: " + Latitude() + "</size>";
		}
		else
		{
			Sleep.instance.recoveryText.text = "";
		}
	}

	[HarmonyPrefix]
	public static void QuadrantOnPickupPatch()
	{
		quadrantHeld = true;
	}

	[HarmonyPrefix]
	public static void QuadrantOnDropPatch()
	{
		quadrantHeld = false;
	}

	[HarmonyPrefix]
	public static void QuadrantLeaveInventoryPatch()
	{
		quadrantHeld = true;
	}

	private static string Latitude()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		Transform transform = ((Component)Refs.charController).transform;
		float z = FloatingOriginManager.instance.GetGlobeCoords(transform).z;
		int num = (int)z;
		int num2 = (int)((z - (float)num) * 60f);
		if (num >= 0)
		{
			return $"{num}° {num2}'N";
		}
		return $"{num}° {num2}'S";
	}

	private static string Longitude()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		Transform transform = ((Component)Refs.charController).transform;
		float x = FloatingOriginManager.instance.GetGlobeCoords(transform).x;
		int num = (int)x;
		int num2 = (int)((x - (float)num) * 60f);
		if (num >= 0)
		{
			return $"{num}° {num2}'E";
		}
		return $"{num}° {num2}'W";
	}

	[HarmonyPostfix]
	public static void Awake_Patch(Sail ___sail, RopeController ___reefController, RopeController ___angleControllerMid, RopeController ___angleControllerLeft, RopeController ___angleControllerRight)
	{
		if ((Object)(object)___angleControllerMid != (Object)null || ((Object)(object)___angleControllerLeft != (Object)null && (Object)(object)___angleControllerRight != (Object)null))
		{
			List<RopeController> list = new List<RopeController>();
			if ((Object)(object)___angleControllerMid != (Object)null)
			{
				list.Add(___angleControllerMid);
			}
			if ((Object)(object)___angleControllerLeft != (Object)null && (Object)(object)___angleControllerRight != (Object)null)
			{
				list.Add(___angleControllerLeft);
				list.Add(___angleControllerRight);
			}
			list.Add(___reefController);
			sailRopeControllerMap[___sail] = list;
		}
	}

	[HarmonyPostfix]
	public static void UpdateControllerAttachments_Patch(Mast __instance)
	{
		if (!GameState.currentlyLoading)
		{
			return;
		}
		GPButtonRopeWinch[] leftAngleWinch = __instance.leftAngleWinch;
		GPButtonRopeWinch[] rightAngleWinch = __instance.rightAngleWinch;
		GPButtonRopeWinch[] midAngleWinch = __instance.midAngleWinch;
		GPButtonRopeWinch[] reefWinch = __instance.reefWinch;
		foreach (GameObject sail in __instance.sails)
		{
			Sail component = sail.GetComponent<Sail>();
			SailConnections component2 = sail.GetComponent<SailConnections>();
			bool flag = false;
			if (component.squareSail)
			{
				for (int num = component.mastOrder - 1; num >= 0; num--)
				{
					if ((Object)(object)__instance.sails[num] != (Object)null && __instance.sails[num].GetComponent<Sail>().squareSail)
					{
						flag = true;
					}
				}
			}
			if (Object.op_Implicit((Object)(object)component2.reefController))
			{
				WinchColor(reefWinch[component.mastOrder], winchColorIndex);
			}
			if (Object.op_Implicit((Object)(object)component2.angleControllerMid))
			{
				WinchColor(midAngleWinch[component.mastOrder], winchColorIndex);
			}
			if (Object.op_Implicit((Object)(object)component2.angleControllerLeft) || Object.op_Implicit((Object)(object)component2.angleControllerRight))
			{
				if (component.squareSail)
				{
					if (!flag)
					{
						WinchColor(leftAngleWinch[0], winchColorIndex);
						WinchColor(rightAngleWinch[0], winchColorIndex);
					}
				}
				else
				{
					WinchColor(leftAngleWinch[component.mastOrder], winchColorIndex);
					WinchColor(rightAngleWinch[component.mastOrder], winchColorIndex);
				}
			}
			winchColorIndex++;
		}
	}
}