Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ShipSense v1.0.0
ShipSense.dll
Decompiled a week agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("ShipSense")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+901b84ab23f2f10926b13865f9b40bb283490874")] [assembly: AssemblyProduct("ShipSense")] [assembly: AssemblyTitle("ShipSense")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ShipSense { public static class ShipSenseHud { private static readonly Vector3[] s_corners = (Vector3[])(object)new Vector3[4]; private static Texture2D s_whiteTex; private static GUIStyle s_titleStyle; private static GUIStyle s_badgeStyle; private static GUIStyle s_healthTextStyle; private static GUIStyle s_speedStyle; private static float s_lastSpeedSampleTime; private static float s_previousSpeed; private static float s_currentSpeed; private static float s_speedDelta; private static float s_lastWarningTime; private static bool s_hasActiveShip; private static string s_shipName = string.Empty; private static float s_currentHp; private static float s_maxHp; private static float s_hpPct; private static float s_signedSpeedMs; private static float s_linearMagnitudeMs; private static bool s_isTailwindActive; public static void Update() { //IL_011a: 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) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || !IsHudVisible()) { s_hasActiveShip = false; return; } Ship val = FindActiveShip(localPlayer); if ((Object)(object)val == (Object)null) { s_hasActiveShip = false; return; } s_hasActiveShip = true; Piece component = ((Component)val).GetComponent<Piece>(); if ((Object)(object)component != (Object)null && Localization.instance != null) { s_shipName = Localization.instance.Localize(component.m_name); } else { s_shipName = ((Object)((Component)val).gameObject).name.Replace("(Clone)", "").Trim(); } WearNTear component2 = ((Component)val).GetComponent<WearNTear>(); if ((Object)(object)component2 != (Object)null) { s_maxHp = component2.m_health; s_hpPct = Mathf.Clamp01(component2.GetHealthPercentage()); s_currentHp = s_hpPct * s_maxHp; } else { s_maxHp = 1000f; s_hpPct = 1f; s_currentHp = 1000f; } s_signedSpeedMs = val.GetSpeed(); Rigidbody component3 = ((Component)val).GetComponent<Rigidbody>(); float num; if (!((Object)(object)component3 != (Object)null)) { num = Mathf.Abs(s_signedSpeedMs); } else { Vector3 linearVelocity = component3.linearVelocity; num = ((Vector3)(ref linearVelocity)).magnitude; } s_linearMagnitudeMs = num; if (Time.unscaledTime - s_lastSpeedSampleTime >= 0.25f) { s_speedDelta = s_linearMagnitudeMs - s_previousSpeed; s_previousSpeed = s_linearMagnitudeMs; s_lastSpeedSampleTime = Time.unscaledTime; } s_currentSpeed = s_linearMagnitudeMs; s_isTailwindActive = val.IsWindControllActive(); if (ShipSensePlugin.LowHealthWarning.Value && s_hpPct <= ShipSensePlugin.LowHealthThreshold.Value && Time.unscaledTime - s_lastWarningTime > 20f) { s_lastWarningTime = Time.unscaledTime; if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)2, $"<color=#ef4444><b>⚠ WARNING: Ship Hull Damaged! ({s_hpPct * 100f:F0}% HP)</b></color>", 0, (Sprite)null, false, false); } } } public static void Render() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) if (!s_hasActiveShip || (int)Event.current.type != 7 || !IsHudVisible()) { return; } GUI.depth = -100; EnsureTexturesAndStyles(); float num = Mathf.Clamp(ShipSensePlugin.UiScale.Value, 0.5f, 2f); float num2 = 250f * num; float height = 80f * num; Rect rect = CalculatePanelRect(num2, height); DrawPanelBox(rect); float num3 = 10f * num; float num4 = 8f * num; float num5 = num2 - num3 * 2f; float num6 = 20f * num; Rect val = new Rect(((Rect)(ref rect)).x + num3, ((Rect)(ref rect)).y + num4, num5 * 0.58f, num6); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref rect)).x + num3 + num5 * 0.58f, ((Rect)(ref rect)).y + num4, num5 * 0.42f, num6); s_titleStyle.fontSize = Mathf.RoundToInt(13f * num); s_badgeStyle.fontSize = Mathf.RoundToInt(11f * num); GUI.Label(val, "⛵ " + s_shipName, s_titleStyle); if (ShipSensePlugin.ShowTailwindBadge.Value) { string text; Color textColor = default(Color); if (s_isTailwindActive) { text = "Tailwind: ON"; ((Color)(ref textColor))..ctor(0.35f, 0.78f, 0.98f, 1f); } else { string text2 = (((int)ShipSensePlugin.TailwindHotkey.Value != 0) ? $" ({ShipSensePlugin.TailwindHotkey.Value})" : ""); text = "Tailwind: OFF" + text2; ((Color)(ref textColor))..ctor(0.6f, 0.65f, 0.7f, 0.85f); } s_badgeStyle.normal.textColor = textColor; GUI.Label(val2, text, s_badgeStyle); } float num7 = ((Rect)(ref rect)).y + num4 + num6 + 3f * num; float num8 = 18f * num; Rect rect2 = default(Rect); ((Rect)(ref rect2))..ctor(((Rect)(ref rect)).x + num3, num7, num5, num8); if (ShipSensePlugin.ShowHealth.Value && ShipSensePlugin.ShowHealthBar.Value) { DrawHealthBar(rect2, s_hpPct, s_currentHp, s_maxHp, num); } if (ShipSensePlugin.ShowSpeed.Value) { float num9 = num7 + num8 + 5f * num; float num10 = 20f * num; Rect val3 = new Rect(((Rect)(ref rect)).x + num3, num9, num5, num10); s_speedStyle.fontSize = Mathf.RoundToInt(12f * num); string text3 = FormatSpeedText(); GUI.Label(val3, text3, s_speedStyle); } } private static string FormatSpeedText() { float num; string text; switch (ShipSensePlugin.SelectedSpeedUnit.Value) { case SpeedUnit.KilometersPerHour: num = s_linearMagnitudeMs * 3.6f; text = "km/h"; break; case SpeedUnit.MetersPerSecond: num = s_linearMagnitudeMs; text = "m/s"; break; case SpeedUnit.MilesPerHour: num = s_linearMagnitudeMs * 2.236936f; text = "mph"; break; default: num = s_linearMagnitudeMs * 1.943844f; text = "kts"; break; } string text2 = string.Empty; if (ShipSensePlugin.ShowTrendIndicator.Value) { text2 = ((s_speedDelta > 0.12f) ? " <color=#4ade80>▲</color>" : ((!(s_speedDelta < -0.12f)) ? " <color=#94a3b8>●</color>" : " <color=#f59e0b>▼</color>")); } string text3 = ((s_signedSpeedMs < -0.25f) ? " <color=#f43f5e>[Reverse]</color>" : ""); return $"Speed: <b>{num:F1} {text}</b>{text2}{text3}"; } private static void DrawHealthBar(Rect rect, float pct, float curHp, float maxHp, float scale) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; GUI.color = new Color(0.08f, 0.08f, 0.1f, 0.95f); GUI.DrawTexture(rect, (Texture)(object)s_whiteTex); float num = Mathf.Max(2f, (((Rect)(ref rect)).width - 2f) * pct); Rect val = new Rect(((Rect)(ref rect)).x + 1f, ((Rect)(ref rect)).y + 1f, num, ((Rect)(ref rect)).height - 2f); Color color2 = default(Color); if (pct > 0.6f) { ((Color)(ref color2))..ctor(0.18f, 0.78f, 0.35f, 0.95f); } else if (pct > 0.3f) { ((Color)(ref color2))..ctor(0.95f, 0.65f, 0.12f, 0.95f); } else { float num2 = 0.7f + 0.3f * Mathf.Sin(Time.unscaledTime * 6f); ((Color)(ref color2))..ctor(0.92f * num2, 0.18f, 0.18f, 0.95f); } GUI.color = color2; GUI.DrawTexture(val, (Texture)(object)s_whiteTex); GUI.color = new Color(0.35f, 0.35f, 0.4f, 0.7f); DrawBorder(rect, 1f); GUI.color = color; s_healthTextStyle.fontSize = Mathf.RoundToInt(11f * scale); string text = ShipSensePlugin.SelectedHealthFormat.Value switch { HealthFormat.CurrentAndMax => $"{Mathf.CeilToInt(curHp)} / {Mathf.CeilToInt(maxHp)} HP", HealthFormat.PercentageOnly => $"{pct * 100f:F0}% HP", _ => $"{Mathf.CeilToInt(curHp)} / {Mathf.CeilToInt(maxHp)} ({pct * 100f:F0}%)", }; GUI.Label(rect, text, s_healthTextStyle); } private static void DrawPanelBox(Rect rect) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; GUI.color = new Color(0.06f, 0.07f, 0.09f, 0.88f); GUI.DrawTexture(rect, (Texture)(object)s_whiteTex); GUI.color = new Color(0.72f, 0.58f, 0.28f, 0.75f); DrawBorder(rect, 1.5f); GUI.color = color; } private static void DrawBorder(Rect rect, float thickness) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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) GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, thickness), (Texture)(object)s_whiteTex); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + ((Rect)(ref rect)).height - thickness, ((Rect)(ref rect)).width, thickness), (Texture)(object)s_whiteTex); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), (Texture)(object)s_whiteTex); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + ((Rect)(ref rect)).width - thickness, ((Rect)(ref rect)).y, thickness, ((Rect)(ref rect)).height), (Texture)(object)s_whiteTex); } private static Rect CalculatePanelRect(float width, float height) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) float value = ShipSensePlugin.OffsetX.Value; float value2 = ShipSensePlugin.OffsetY.Value; Hud instance = Hud.instance; Rect rect = default(Rect); bool flag = (Object)(object)instance != (Object)null && (Object)(object)instance.m_shipHudRoot != (Object)null && TryGetScreenRect(instance.m_shipHudRoot.GetComponent<RectTransform>(), out rect); float num; float num2; switch (ShipSensePlugin.SelectedUiAnchor.Value) { case UiAnchor.LeftOfCompass: if (flag) { num = ((Rect)(ref rect)).x - width - 12f; num2 = ((Rect)(ref rect)).y + (((Rect)(ref rect)).height - height) * 0.5f; } else { num = (float)Screen.width - width - 190f; num2 = (float)Screen.height - height - 30f; } break; case UiAnchor.AboveCompass: if (flag) { num = ((Rect)(ref rect)).x + (((Rect)(ref rect)).width - width) * 0.5f; num2 = ((Rect)(ref rect)).y - height - 10f; } else { num = (float)Screen.width - width - 30f; num2 = (float)Screen.height - height - 180f; } break; case UiAnchor.BottomRight: num = (float)Screen.width - width - 25f; num2 = (float)Screen.height - height - 25f; break; case UiAnchor.BottomCenter: num = ((float)Screen.width - width) * 0.5f; num2 = (float)Screen.height - height - 120f; break; case UiAnchor.Custom: num = (float)Screen.width - width - 25f; num2 = (float)Screen.height - height - 25f; break; default: if (flag) { num = ((Rect)(ref rect)).x + (((Rect)(ref rect)).width - width) * 0.5f; num2 = ((Rect)(ref rect)).y + ((Rect)(ref rect)).height + 8f; if (num2 + height > (float)Screen.height - 10f) { num = ((Rect)(ref rect)).x - width - 12f; num2 = ((Rect)(ref rect)).y + (((Rect)(ref rect)).height - height) * 0.5f; } } else { num = (float)Screen.width - width - 30f; num2 = (float)Screen.height - height - 25f; } break; } num += value; num2 += value2; num = Mathf.Clamp(num, 10f, (float)Screen.width - width - 10f); num2 = Mathf.Clamp(num2, 10f, (float)Screen.height - height - 10f); return new Rect(num, num2, width, height); } private static bool TryGetScreenRect(RectTransform rectTransform, out Rect rect) { //IL_0001: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) rect = default(Rect); if ((Object)(object)rectTransform == (Object)null) { return false; } rectTransform.GetWorldCorners(s_corners); float num = float.MaxValue; float num2 = float.MaxValue; float num3 = float.MinValue; float num4 = float.MinValue; for (int i = 0; i < s_corners.Length; i++) { Vector2 val = RectTransformUtility.WorldToScreenPoint((Camera)null, s_corners[i]); num = Mathf.Min(num, val.x); num2 = Mathf.Min(num2, val.y); num3 = Mathf.Max(num3, val.x); num4 = Mathf.Max(num4, val.y); } rect = new Rect(num, (float)Screen.height - num4, num3 - num, num4 - num2); if (((Rect)(ref rect)).width > 0f) { return ((Rect)(ref rect)).height > 0f; } return false; } private static bool IsHudVisible() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 if ((Object)(object)Hud.instance == (Object)null || !Hud.instance.IsVisible()) { return false; } if (Menu.IsVisible() || ((Object)(object)Minimap.instance != (Object)null && (int)Minimap.instance.m_mode == 2)) { return false; } return true; } public static Ship FindActiveShip(Player player) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return null; } Ship controlledShip = player.GetControlledShip(); if ((Object)(object)controlledShip != (Object)null) { return controlledShip; } if (ShipSensePlugin.ShowWhenPassenger.Value) { Ship localShip = Ship.GetLocalShip(); if ((Object)(object)localShip != (Object)null) { return localShip; } Ship standingOnShip = ((Character)player).GetStandingOnShip(); if ((Object)(object)standingOnShip != (Object)null) { return standingOnShip; } Collider[] array = Physics.OverlapSphere(((Component)player).transform.position, 6f); for (int i = 0; i < array.Length; i++) { Ship componentInParent = ((Component)array[i]).GetComponentInParent<Ship>(); if ((Object)(object)componentInParent != (Object)null && componentInParent.IsPlayerInBoat(player)) { return componentInParent; } } } return null; } private static void EnsureTexturesAndStyles() { //IL_0028: 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: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)s_whiteTex == (Object)null) { s_whiteTex = Texture2D.whiteTexture; } if (s_titleStyle == null) { s_titleStyle = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)1, alignment = (TextAnchor)3 }; s_titleStyle.normal.textColor = new Color(0.95f, 0.95f, 0.98f, 1f); } if (s_badgeStyle == null) { s_badgeStyle = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)1, alignment = (TextAnchor)5 }; s_badgeStyle.normal.textColor = Color.white; } if (s_healthTextStyle == null) { s_healthTextStyle = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; s_healthTextStyle.normal.textColor = Color.white; } if (s_speedStyle == null) { s_speedStyle = new GUIStyle(GUI.skin.label) { fontStyle = (FontStyle)0, alignment = (TextAnchor)3, richText = true }; s_speedStyle.normal.textColor = new Color(0.9f, 0.92f, 0.95f, 1f); } } } public static class ShipSensePatches { [HarmonyPatch(typeof(Ship), "IsWindControllActive")] public static class Ship_IsWindControllActive_Patch { public static void Postfix(Ship __instance, ref bool __result) { if (__result || !ShipSensePlugin.Enabled.Value || !ShipSensePlugin.TailwindActive) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } if (ShipSensePlugin.RequireRudder.Value) { if ((Object)(object)localPlayer.GetControlledShip() == (Object)(object)__instance) { __result = true; } } else if ((Object)(object)localPlayer.GetControlledShip() == (Object)(object)__instance || (Object)(object)Ship.GetLocalShip() == (Object)(object)__instance) { __result = true; } } } [HarmonyPatch(typeof(EnvMan), "SetTargetWind")] public static class EnvMan_SetTargetWind_Patch { public static void Prefix(ref Vector3 dir, ref float intensity) { if (ShipSensePlugin.Enabled.Value && ShipSensePlugin.TailwindActive && ShipSensePlugin.BoostWindForce.Value) { Ship localShip = Ship.GetLocalShip(); if ((Object)(object)localShip != (Object)null && localShip.IsWindControllActive()) { intensity = Mathf.Max(intensity, ShipSensePlugin.MinWindIntensity.Value); } } } } [HarmonyPatch(typeof(ShipControlls), "GetHoverText")] public static class ShipControlls_GetHoverText_Patch { public static void Postfix(ShipControlls __instance, ref string __result) { if (!ShipSensePlugin.Enabled.Value || !ShipSensePlugin.ShowHoverHealth.Value) { return; } Ship ship = __instance.m_ship; if ((Object)(object)ship == (Object)null) { return; } WearNTear component = ((Component)ship).GetComponent<WearNTear>(); if (!((Object)(object)component == (Object)null)) { float health = component.m_health; float num = Mathf.Max(0f, component.GetHealthPercentage() * health); float num2 = component.GetHealthPercentage() * 100f; string text = ((num2 > 60f) ? "#4ade80" : ((num2 > 30f) ? "#facc15" : "#f87171")); string text2 = $"<color={text}>Hull HP: {Mathf.CeilToInt(num)} / {Mathf.CeilToInt(health)} ({num2:F0}%)</color>"; if (!string.IsNullOrEmpty(__result)) { __result = __result + "\n" + text2; } else { __result = text2; } } } } [HarmonyPatch(typeof(Hud), "UpdateShipHud")] public static class Hud_UpdateShipHud_Patch { public static void Postfix(Hud __instance, Player player, float dt) { //IL_009b: 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_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) if (!ShipSensePlugin.Enabled.Value || !ShipSensePlugin.ShowWhenPassenger.Value || (Object)(object)player == (Object)null || (Object)(object)player.GetControlledShip() != (Object)null) { return; } Ship localShip = Ship.GetLocalShip(); if (!((Object)(object)localShip == (Object)null) && __instance.IsVisible() && ShipSensePlugin.ShowCompassForPassengers.Value && (Object)(object)__instance.m_shipHudRoot != (Object)null) { __instance.m_shipHudRoot.SetActive(true); float shipYawAngle = localShip.GetShipYawAngle(); if ((Object)(object)__instance.m_shipWindIndicatorRoot != (Object)null) { ((Transform)__instance.m_shipWindIndicatorRoot).localRotation = Quaternion.Euler(0f, 0f, shipYawAngle); } float windAngle = localShip.GetWindAngle(); if ((Object)(object)__instance.m_shipWindIconRoot != (Object)null) { ((Transform)__instance.m_shipWindIconRoot).localRotation = Quaternion.Euler(0f, 0f, windAngle); } float windAngleFactor = localShip.GetWindAngleFactor(); if ((Object)(object)__instance.m_shipWindIcon != (Object)null) { ((Graphic)__instance.m_shipWindIcon).color = Color.Lerp(new Color(0.2f, 0.2f, 0.2f, 1f), Color.white, windAngleFactor); } } } } } public enum SpeedUnit { Knots, KilometersPerHour, MetersPerSecond, MilesPerHour } public enum HealthFormat { Both, CurrentAndMax, PercentageOnly } public enum UiAnchor { BelowCompass, LeftOfCompass, AboveCompass, BottomRight, BottomCenter, Custom } [BepInPlugin("com.dfg.shipsense", "ShipSense", "1.0.0")] public class ShipSensePlugin : BaseUnityPlugin { public const string ModGuid = "com.dfg.shipsense"; public const string ModName = "ShipSense"; public const string ModVersion = "1.0.0"; public static ConfigEntry<bool> Enabled; public static ConfigEntry<bool> ShowWhenPassenger; public static ConfigEntry<bool> ShowCompassForPassengers; public static ConfigEntry<bool> ShowHoverHealth; public static ConfigEntry<bool> ShowSpeed; public static ConfigEntry<SpeedUnit> SelectedSpeedUnit; public static ConfigEntry<bool> ShowTrendIndicator; public static ConfigEntry<bool> ShowHealth; public static ConfigEntry<HealthFormat> SelectedHealthFormat; public static ConfigEntry<bool> ShowHealthBar; public static ConfigEntry<bool> LowHealthWarning; public static ConfigEntry<float> LowHealthThreshold; public static ConfigEntry<bool> AlwaysTailwind; public static ConfigEntry<KeyCode> TailwindHotkey; public static ConfigEntry<bool> RequireRudder; public static ConfigEntry<bool> BoostWindForce; public static ConfigEntry<float> MinWindIntensity; public static ConfigEntry<bool> ShowTailwindBadge; public static ConfigEntry<UiAnchor> SelectedUiAnchor; public static ConfigEntry<float> OffsetX; public static ConfigEntry<float> OffsetY; public static ConfigEntry<float> UiScale; private Harmony m_harmony; public static bool TailwindActive { get; set; } = true; private void Awake() { //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Expected O, but got Unknown //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Expected O, but got Unknown //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Expected O, but got Unknown Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Enable or disable ShipSense."); ShowWhenPassenger = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "ShowWhenPassenger", true, "Show ship stats when on board even if not actively piloting at the rudder."); ShowCompassForPassengers = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "ShowCompassForPassengers", true, "Keep the vanilla sailing wind compass visible for passengers aboard the ship."); ShowHoverHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "ShowHoverHealth", true, "Show current ship HP on the hover tooltip when aiming at the rudder or hull."); ShowSpeed = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Speedometer", "ShowSpeed", true, "Show real-time sailing speed on the HUD."); SelectedSpeedUnit = ((BaseUnityPlugin)this).Config.Bind<SpeedUnit>("2 - Speedometer", "SpeedUnit", SpeedUnit.Knots, "Unit of speed to display: Knots (kts), KilometersPerHour (km/h), MetersPerSecond (m/s), or MilesPerHour (mph)."); ShowTrendIndicator = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Speedometer", "ShowTrendIndicator", true, "Show acceleration tendency arrow (▲ accelerating, ● steady, ▼ decelerating)."); ShowHealth = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Health", "ShowHealth", true, "Show ship health on the HUD."); SelectedHealthFormat = ((BaseUnityPlugin)this).Config.Bind<HealthFormat>("3 - Health", "HealthFormat", HealthFormat.Both, "Health text format: Both (e.g. 850 / 1000 [85%]), CurrentAndMax, or PercentageOnly."); ShowHealthBar = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Health", "ShowHealthBar", true, "Show a visual color-coded health bar under the ship compass."); LowHealthWarning = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Health", "LowHealthWarning", true, "Warn the player and pulse the health bar when hull drops into critical condition."); LowHealthThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Health", "LowHealthThreshold", 0.3f, "Threshold below which ship hull is considered critical (0.30 = 30%)."); AlwaysTailwind = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Tailwind", "AlwaysTailwind", true, "Enable Moder tailwind power (wind always blows forward in ship's heading)."); TailwindHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("4 - Tailwind", "TailwindHotkey", (KeyCode)289, "Hotkey to toggle tailwind on/off at will."); RequireRudder = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Tailwind", "RequireRudder", false, "If true, tailwind only engages when holding the rudder; if false, engages whenever players are aboard."); BoostWindForce = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Tailwind", "BoostWindForce", false, "If true, boosts wind to full gale force when tailwind is active. If false, preserves natural weather wind strength."); MinWindIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Tailwind", "MinWindIntensity", 1f, new ConfigDescription("Minimum wind force intensity when boost is enabled (0.5 to 1.0).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1f), Array.Empty<object>())); ShowTailwindBadge = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Tailwind", "ShowTailwindBadge", true, "Display tailwind status badge on the ship HUD."); SelectedUiAnchor = ((BaseUnityPlugin)this).Config.Bind<UiAnchor>("5 - UI", "Anchor", UiAnchor.BelowCompass, "Screen anchor position for the ShipSense HUD."); OffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("5 - UI", "OffsetX", 0f, "Custom horizontal pixel offset."); OffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("5 - UI", "OffsetY", 0f, "Custom vertical pixel offset."); UiScale = ((BaseUnityPlugin)this).Config.Bind<float>("5 - UI", "UiScale", 1f, new ConfigDescription("Scale of the ShipSense HUD panel.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>())); TailwindActive = AlwaysTailwind.Value; try { m_harmony = new Harmony("com.dfg.shipsense"); m_harmony.PatchAll(); Logger.LogInfo((object)"ShipSense v1.0.0 patches applied successfully."); } catch (Exception ex) { Logger.LogError((object)("ShipSense: Error applying Harmony patches: " + ex)); } } private void Update() { //IL_0012: 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) if (!Enabled.Value) { return; } if ((int)TailwindHotkey.Value != 0 && Input.GetKeyDown(TailwindHotkey.Value)) { TailwindActive = !TailwindActive; string text = (TailwindActive ? "ShipSense: Tailwind Enabled" : "ShipSense: Tailwind Disabled"); if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false, false); } } ShipSenseHud.Update(); } private void OnGUI() { if (Enabled.Value) { ShipSenseHud.Render(); } } private void OnDestroy() { Harmony harmony = m_harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } }