Decompiled source of Njord v1.0.0

Njord/plugins/Njord.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Njord.Core;
using Njord.Patches;
using UnityEngine;
using UnityEngine.Rendering;

[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: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 Njord
{
	public static class NjordBoatController
	{
		public static string GetShipPrefabName(object ship)
		{
			Component val = (Component)((ship is Component) ? ship : null);
			if (val == null)
			{
				return "Unknown";
			}
			return ((Object)val.gameObject).name.Replace("(Clone)", "").Trim();
		}

		public static float GetBaseline(NjordSailState state, string shipName)
		{
			NjordRuntimeConfig runtimeConfig = NjordSync.RuntimeConfig;
			if (runtimeConfig == null)
			{
				return 0f;
			}
			return state switch
			{
				NjordSailState.Forward => runtimeConfig.BaseForwardForce, 
				NjordSailState.Half => runtimeConfig.HalfSailForce, 
				NjordSailState.Full => runtimeConfig.FullSailForce, 
				_ => 0f, 
			};
		}

		public static float ApplyAcceleration(float baseline, float dt)
		{
			NjordRuntimeConfig runtimeConfig = NjordSync.RuntimeConfig;
			if (runtimeConfig == null)
			{
				return 0f;
			}
			float num = baseline * runtimeConfig.AccelerationMultiplier;
			if (float.IsNaN(num) || float.IsInfinity(num))
			{
				return 0f;
			}
			return num;
		}

		public static float GetSailMult(NjordSailState state)
		{
			NjordRuntimeConfig runtimeConfig = NjordSync.RuntimeConfig;
			if (runtimeConfig == null)
			{
				return 1f;
			}
			return state switch
			{
				NjordSailState.Forward => runtimeConfig.SailForwardForce, 
				NjordSailState.Half => runtimeConfig.HalfSailForce, 
				NjordSailState.Full => runtimeConfig.FullSailForce, 
				_ => 1f, 
			};
		}

		public static float GetReverseForce(float dt)
		{
			NjordRuntimeConfig runtimeConfig = NjordSync.RuntimeConfig;
			if (runtimeConfig == null)
			{
				return 0f;
			}
			float num = runtimeConfig.BaseReverseForce * runtimeConfig.ReverseKick;
			if (float.IsNaN(num) || float.IsInfinity(num))
			{
				return 0f;
			}
			return num;
		}
	}
	public static class Njord_ShipControlTracker
	{
		private static Dictionary<ZDOID, long> _controlMap;

		public const float READY_DELAY = 0.35f;

		public static long CurrentController { get; private set; }

		private static Dictionary<ZDOID, long> ControlMap
		{
			get
			{
				if (_controlMap == null)
				{
					_controlMap = new Dictionary<ZDOID, long>();
				}
				return _controlMap;
			}
		}

		public static float ReadyTimer { get; private set; }

		public static bool SteeringGateReady { get; private set; }

		public static long GetControllerForShip(object shipObj)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (shipObj == null)
			{
				return 0L;
			}
			Ship val = (Ship)((shipObj is Ship) ? shipObj : null);
			if (val == null)
			{
				return 0L;
			}
			ZNetView component = ((Component)val).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return 0L;
			}
			ZDO zDO = component.GetZDO();
			if (zDO == null)
			{
				return 0L;
			}
			ZDOID uid = zDO.m_uid;
			if (ControlMap.TryGetValue(uid, out var value))
			{
				return value;
			}
			return 0L;
		}

		public static void SetControl(Ship ship, long playerID)
		{
			//IL_002f: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ship == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)ship).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return;
			}
			ZDO zDO = component.GetZDO();
			if (zDO != null)
			{
				ZDOID uid = zDO.m_uid;
				ControlMap[uid] = playerID;
				CurrentController = playerID;
				Njord_Telemetry.ClearErrors();
				if (NjordConfig.Debug_Enable.Value)
				{
					NjordDebug.Debug($"[ControlTracker] Player {playerID} now controls {((Object)ship).name} ({uid}).");
				}
			}
		}

		public static void ClearControl(Ship ship)
		{
			//IL_002f: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ship == (Object)null)
			{
				return;
			}
			ZNetView component = ((Component)ship).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return;
			}
			ZDO zDO = component.GetZDO();
			if (zDO != null)
			{
				ZDOID uid = zDO.m_uid;
				ControlMap[uid] = 0L;
				CurrentController = 0L;
				Njord_DebugHUD.Instance?.TriggerBoatDestroyedLore(ship);
				if (NjordConfig.Debug_Enable.Value)
				{
					NjordDebug.Debug($"[ControlTracker] Control cleared for {((Object)ship).name} ({uid}).");
				}
			}
		}

		public static void UpdateController(long controller, float dt)
		{
			CurrentController = controller;
			if (controller != 0L)
			{
				ReadyTimer += dt;
				if (ReadyTimer >= 0.35f)
				{
					SteeringGateReady = true;
				}
			}
			else
			{
				ReadyTimer = 0f;
				SteeringGateReady = false;
			}
		}
	}
	public static class NjordDebug
	{
		private static bool _startupPrinted;

		public static void Startup()
		{
			if (!_startupPrinted)
			{
				_startupPrinted = true;
				Plugin.Log.LogInfo((object)"⚓ [Njord] The longship wakes. The sea remembers your hand.");
			}
		}

		public static void Info(string msg)
		{
			if (NjordConfig.Debug_Enable.Value)
			{
				Plugin.Log.LogInfo((object)("[Njord] " + msg));
			}
		}

		public static void Debug(string msg)
		{
			if (NjordConfig.Debug_Enable.Value)
			{
				Plugin.Log.LogDebug((object)("[Njord] " + msg));
			}
		}

		public static void Warn(string msg)
		{
			if (NjordConfig.Debug_Enable.Value)
			{
				Plugin.Log.LogWarning((object)("[Njord] " + msg));
			}
		}

		public static void Error(string msg)
		{
			Plugin.Log.LogError((object)("[Njord] " + msg));
		}
	}
	public class Njord_DebugHUD : MonoBehaviour
	{
		public static Njord_DebugHUD Instance;

		public static bool IsVisible = true;

		public static Vector2 HudPosition = new Vector2(20f, 20f);

		public static float HudWidth = 360f;

		public static float HudHeight = 480f;

		public static bool IsDragging = false;

		public static Vector2 DragStartMouse;

		public static Vector2 DragStartHud;

		public static GUIStyle HeaderStyle;

		public static GUIStyle SectionHeaderStyle;

		public static GUIStyle LabelStyle;

		public static GUIStyle SmallLabelStyle;

		public static GUIStyle HpBarBackgroundStyle;

		public static GUIStyle HpBarFillStyle;

		public static Color BackgroundColor = new Color(0f, 0f, 0f, 0.55f);

		public static Color HeaderColor = new Color(0.9f, 0.8f, 0.5f, 1f);

		public static Color SectionColor = new Color(0.85f, 0.75f, 0.55f, 1f);

		public static Color TextColor = new Color(0.95f, 0.9f, 0.8f, 1f);

		public static Color HpBarBackgroundColor = new Color(0.2f, 0.05f, 0.05f, 0.8f);

		public static Color HpBarFillColor = new Color(0.1f, 0.7f, 0.1f, 0.9f);

		private float fadeOutTimer;

		private const float FadeDuration = 2f;

		private bool fadingOut;

		private string fadeLore = "";

		public static void Ensure()
		{
			//IL_0013: 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_001e: Expected O, but got Unknown
			if (!((Object)(object)Instance != (Object)null))
			{
				GameObject val = new GameObject("Njord_DebugHUD");
				Object.DontDestroyOnLoad((Object)val);
				Instance = val.AddComponent<Njord_DebugHUD>();
				HudPosition.x = Plugin.HudPositionX.Value;
				HudPosition.y = Plugin.HudPositionY.Value;
			}
		}

		public void Update()
		{
			if (Input.GetKeyDown((KeyCode)288))
			{
				IsVisible = !IsVisible;
			}
		}

		private bool PlayerIsControllingShip()
		{
			return Njord_ShipControlTracker.CurrentController != 0;
		}

		public void TriggerBoatDestroyedLore(Ship ship)
		{
			fadingOut = true;
			fadeOutTimer = 2f;
			string text = (Object.op_Implicit((Object)(object)ship) ? ((Object)ship).name : "The vessel");
			fadeLore = text + " sinks beneath the waves.\nNjord marks its passing.";
		}

		public void InitializeStyles()
		{
			//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_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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00af: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Expected O, but got Unknown
			if (Event.current != null)
			{
				if (HeaderStyle == null)
				{
					GUIStyle val = new GUIStyle(GUI.skin.label)
					{
						fontSize = 16,
						fontStyle = (FontStyle)1
					};
					val.normal.textColor = HeaderColor;
					HeaderStyle = val;
				}
				if (SectionHeaderStyle == null)
				{
					GUIStyle val2 = new GUIStyle(GUI.skin.label)
					{
						fontSize = 13,
						fontStyle = (FontStyle)1
					};
					val2.normal.textColor = SectionColor;
					SectionHeaderStyle = val2;
				}
				if (LabelStyle == null)
				{
					GUIStyle val3 = new GUIStyle(GUI.skin.label)
					{
						fontSize = 12
					};
					val3.normal.textColor = TextColor;
					LabelStyle = val3;
				}
				if (SmallLabelStyle == null)
				{
					GUIStyle val4 = new GUIStyle(GUI.skin.label)
					{
						fontSize = 11
					};
					val4.normal.textColor = TextColor;
					SmallLabelStyle = val4;
				}
				if (HpBarBackgroundStyle == null)
				{
					Texture2D val5 = new Texture2D(1, 1);
					val5.SetPixel(0, 0, HpBarBackgroundColor);
					val5.Apply();
					HpBarBackgroundStyle = new GUIStyle(GUI.skin.box);
					HpBarBackgroundStyle.normal.background = val5;
				}
				if (HpBarFillStyle == null)
				{
					Texture2D val6 = new Texture2D(1, 1);
					val6.SetPixel(0, 0, HpBarFillColor);
					val6.Apply();
					HpBarFillStyle = new GUIStyle(GUI.skin.box);
					HpBarFillStyle.normal.background = val6;
				}
			}
		}

		public void OnGUI()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0687: Unknown result type (might be due to invalid IL or missing references)
			if (!IsVisible || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			if (fadingOut)
			{
				fadeOutTimer -= Time.deltaTime;
				float num = Mathf.Clamp01(fadeOutTimer / 2f);
				GUI.color = new Color(0f, 0f, 0f, 1f - num);
				GUI.Box(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), GUIContent.none);
				GUI.color = new Color(1f, 1f, 1f, num);
				GUI.Label(new Rect(40f, 40f, 800f, 200f), fadeLore, HeaderStyle);
				GUI.color = Color.white;
				if (fadeOutTimer <= 0f)
				{
					fadingOut = false;
				}
			}
			else if (PlayerIsControllingShip())
			{
				InitializeStyles();
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(HudPosition.x, HudPosition.y, HudWidth, HudHeight);
				GUI.color = BackgroundColor;
				GUI.Box(val, GUIContent.none);
				GUI.color = Color.white;
				GUILayout.BeginArea(val);
				GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
				GUILayout.Label("⚓ NJORD ENGINE READOUT ⚓", HeaderStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(4f);
				GUILayout.Label("Vessel: " + Njord_Telemetry.VesselName, LabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Status: " + (Njord_Telemetry.IsFloating ? "Floating ✓" : "Not Floating ✗") + "   Steering Gate: " + (Njord_Telemetry.GateReady ? "Open ✓" : "Closed ✗"), SmallLabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(4f);
				GUILayout.Label("── Waterline ─────────────────────────────", SectionHeaderStyle, Array.Empty<GUILayoutOption>());
				string text = (Njord_Telemetry.WaterError ? "—" : Njord_Telemetry.WaterLevel.ToString("F2"));
				string text2 = (Njord_Telemetry.WaterError ? "—" : Njord_Telemetry.BoatY.ToString("F2"));
				string arg = (Njord_Telemetry.DepthError ? "—" : Njord_Telemetry.Depth.ToString("F3"));
				GUILayout.Label("Water Level:   " + text, LabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Boat Y:        " + text2, LabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Depth:         {arg}   (Disable: {Njord_Telemetry.DisableLevel:F3})", LabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Readiness:     {Njord_Telemetry.ReadinessTimer:F2} / {Njord_Telemetry.ReadinessMax:F2}", LabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(4f);
				GUILayout.Label("── Hull Integrity ───────────────────────", SectionHeaderStyle, Array.Empty<GUILayoutOption>());
				float hPCurrent = Njord_Telemetry.HPCurrent;
				float num2 = Mathf.Max(Njord_Telemetry.HPMax, 1f);
				float num3 = Mathf.Clamp01(hPCurrent / num2);
				GUILayout.Label($"HP: {hPCurrent:F0} / {num2:F0}  ({num3 * 100f:F1}%)", LabelStyle, Array.Empty<GUILayoutOption>());
				Rect lastRect = GUILayoutUtility.GetLastRect();
				float num4 = ((Rect)(ref val)).width - 20f;
				float num5 = 10f;
				Rect val2 = default(Rect);
				((Rect)(ref val2))..ctor(10f, ((Rect)(ref lastRect)).yMax + 2f, num4, num5);
				GUI.Box(val2, GUIContent.none, HpBarBackgroundStyle);
				GUI.Box(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y, ((Rect)(ref val2)).width * num3, ((Rect)(ref val2)).height), GUIContent.none, HpBarFillStyle);
				GUILayout.Space(22f);
				GUILayout.Label("── Steering ─────────────────────────────", SectionHeaderStyle, Array.Empty<GUILayoutOption>());
				string text3 = (Njord_Telemetry.RudderError ? "—" : Njord_Telemetry.RudderVanilla.ToString("F2"));
				string text4 = (Njord_Telemetry.RudderError ? "—" : Njord_Telemetry.RudderNjord.ToString("F2"));
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label("Vanilla: " + text3, LabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
				GUILayout.Label("Njord: " + text4, LabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Mult: {Njord_Telemetry.SteeringMultiplier:F2}x", LabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
				GUILayout.Label($"Gain: {Njord_Telemetry.SteeringGainPerSecond:+0.00;-0.00;0.00}", LabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
				GUILayout.Space(4f);
				GUILayout.Label("── Speed ────────────────────────────────", SectionHeaderStyle, Array.Empty<GUILayoutOption>());
				string text5 = (Njord_Telemetry.SpeedError ? "—" : Njord_Telemetry.NjordSpeedCurr.ToString("F1"));
				string text6 = (Njord_Telemetry.SpeedError ? "—" : Njord_Telemetry.MortalSpeedCurr.ToString("F1"));
				string text7 = (Njord_Telemetry.SpeedError ? "—" : (Njord_Telemetry.NjordSpeedCurr - Njord_Telemetry.MortalSpeedCurr).ToString("0.0"));
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label("Njord: " + text5 + " m/s", LabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) });
				GUILayout.Label("Mortal: " + text6 + " m/s", LabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
				GUILayout.Label("Gift of the Deep: " + text7 + " m/s", LabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(4f);
				GUILayout.Label("── Wind ─────────────────────────────────", SectionHeaderStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label($"UI Blend:        {Njord_Telemetry.WindUIBlend:F2}", LabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label($"UI Color:        ({Njord_Telemetry.WindUIColor.r:F2}, {Njord_Telemetry.WindUIColor.g:F2}, {Njord_Telemetry.WindUIColor.b:F2})", LabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(6f);
				GUILayout.Label("Press F7 to toggle HUD (drag anywhere to move)", SmallLabelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				GUILayout.EndArea();
				HandleDragging(val);
			}
		}

		public void HandleDragging(Rect areaRect)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Invalid comparison between Unknown and I4
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Invalid comparison between Unknown and I4
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Event current = Event.current;
			if (current != null)
			{
				if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref areaRect)).Contains(current.mousePosition))
				{
					IsDragging = true;
					DragStartMouse = current.mousePosition;
					DragStartHud = HudPosition;
					current.Use();
				}
				if (IsDragging && (int)current.type == 3 && current.button == 0)
				{
					Vector2 val = current.mousePosition - DragStartMouse;
					HudPosition = DragStartHud + val;
					current.Use();
				}
				if (IsDragging && ((int)current.type == 1 || (int)current.rawType == 1))
				{
					IsDragging = false;
					Plugin.HudPositionX.Value = HudPosition.x;
					Plugin.HudPositionY.Value = HudPosition.y;
					current.Use();
				}
			}
		}
	}
	public class NjordBootstrap : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <InitRoutine>d__3 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InitRoutine>d__3(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					NjordDebug.Info("\ud83d\udf01 Njord bootstrap: initializing sync and HUD.");
					NjordSync.Initialize();
					Njord_DebugHUD.Ensure();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static bool _initialized;

		public static void Ensure()
		{
			//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_0018: Expected O, but got Unknown
			if (!_initialized)
			{
				GameObject val = new GameObject("Njord_Bootstrap");
				Object.DontDestroyOnLoad((Object)val);
				val.AddComponent<NjordBootstrap>();
				_initialized = true;
			}
		}

		private void Start()
		{
			((MonoBehaviour)this).StartCoroutine(InitRoutine());
		}

		[IteratorStateMachine(typeof(<InitRoutine>d__3))]
		private IEnumerator InitRoutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <InitRoutine>d__3(0);
		}
	}
	[BepInPlugin("wubarrk.njord", "Njord", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static Plugin Instance;

		internal static Harmony Harmony;

		internal static ManualLogSource Log;

		public static ConfigEntry<float> HudPositionX;

		public static ConfigEntry<float> HudPositionY;

		private void Awake()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"The sea stirs. The runes awaken.");
			NjordConfig.Bind(((BaseUnityPlugin)this).Config);
			HudPositionX = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "HudPositionX", 40f, "Njord HUD X position.");
			HudPositionY = ((BaseUnityPlugin)this).Config.Bind<float>("HUD", "HudPositionY", 200f, "Njord HUD Y position.");
			NjordSync.InitializeFromConfig();
			Harmony = new Harmony("wubarrk.njord");
			NjordPatchCaller.ApplyPatches();
			NjordBootstrap.Ensure();
			Log.LogInfo((object)"Njord, god of the sea, obeys your command.");
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)289))
			{
				NjordSync.ReloadRuntimeConfig();
				NjordDebug.Info("Njord config reloaded from disk.");
				MessageHud instance = MessageHud.instance;
				if (instance != null)
				{
					instance.ShowMessage((MessageType)1, "Njord config reloaded", 0, (Sprite)null, false);
				}
			}
		}
	}
	public static class NjordRuneVFX
	{
		private static bool _initialized;

		private static GameObject _prefab;

		private static Material _material;

		public static void DiscoverShaderIfNeeded()
		{
			//IL_0029: 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)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			if (_initialized)
			{
				return;
			}
			_initialized = true;
			if (NjordConfig.Debug_Enable.Value)
			{
				NjordDebug.Debug("[VFX] Initializing NjordRuneVFX…");
			}
			Texture2D val = NjordRuneTextureGenerator.GenerateRune(NjordSync.RuntimeConfig.VFX_Color);
			if ((Object)(object)val == (Object)null)
			{
				NjordDebug.Error("[VFX] Rune texture generation failed.");
				return;
			}
			_material = NjordRuneVFX_Helper.GetOrCreateRuneMaterial(val, NjordSync.RuntimeConfig.VFX_Color);
			if ((Object)(object)_material == (Object)null)
			{
				NjordDebug.Error("[VFX] Failed to create rune material (no suitable shader).");
				return;
			}
			if (_material.HasProperty("_EmissionColor"))
			{
				Color vFX_Color = NjordSync.RuntimeConfig.VFX_Color;
				_material.SetColor("_EmissionColor", vFX_Color * 3f);
			}
			_material.SetInt("_SrcBlend", 1);
			_material.SetInt("_DstBlend", 1);
			_material.SetInt("_ZWrite", 0);
			_material.DisableKeyword("_ALPHATEST_ON");
			_material.EnableKeyword("_ALPHABLEND_ON");
			_material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
			_material.renderQueue = 3000;
			_prefab = BuildPrefab(_material);
			if ((Object)(object)_prefab == (Object)null)
			{
				NjordDebug.Error("[VFX] Failed to build rune prefab.");
			}
			else if (NjordConfig.Debug_Enable.Value)
			{
				NjordDebug.Debug("[VFX] NjordRuneVFX initialized successfully.");
			}
		}

		public static void Spawn(Vector3 pos, Color color)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			if (!(NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig()).VFX_Enable)
			{
				return;
			}
			if (!_initialized)
			{
				DiscoverShaderIfNeeded();
			}
			if ((Object)(object)_prefab == (Object)null)
			{
				return;
			}
			pos.y += 0.35f;
			MeshRenderer component = Object.Instantiate<GameObject>(_prefab, pos, Quaternion.identity).GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null && (Object)(object)((Renderer)component).material != (Object)null)
			{
				Material material = ((Renderer)component).material;
				if (material.HasProperty("_Color"))
				{
					material.SetColor("_Color", color);
				}
				if (material.HasProperty("_TintColor"))
				{
					material.SetColor("_TintColor", color * 2f);
				}
				if (material.HasProperty("_EmissionColor"))
				{
					material.SetColor("_EmissionColor", color * 3f);
				}
				if (NjordConfig.Debug_Enable.Value)
				{
					NjordDebug.Debug($"[VFX] Spawned glowing rune at {pos}");
				}
			}
		}

		public static void Spawn(Vector3 pos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Spawn(pos, NjordSync.RuntimeConfig.VFX_Color);
		}

		private static GameObject BuildPrefab(Material mat)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Expected O, but got Unknown
			GameObject val = new GameObject("NjordRuneVFX_Quad");
			MeshFilter val2 = val.AddComponent<MeshFilter>();
			MeshRenderer obj = val.AddComponent<MeshRenderer>();
			val2.sharedMesh = BuildQuad();
			((Renderer)obj).sharedMaterial = mat;
			TrailRenderer obj2 = val.AddComponent<TrailRenderer>();
			obj2.time = 0.8f;
			obj2.startWidth = 0.45f;
			obj2.endWidth = 0f;
			obj2.minVertexDistance = 0.05f;
			obj2.emitting = true;
			((Renderer)obj2).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj2).receiveShadows = false;
			obj2.alignment = (LineAlignment)0;
			((Renderer)obj2).material = mat;
			val.AddComponent<NjordRuneVFX_Fader>();
			val.AddComponent<NjordRuneVFX_Billboard>();
			val.transform.localScale = Vector3.one * 1.35f;
			if (NjordConfig.Debug_Enable.Value)
			{
				NjordDebug.Debug("[VFX] Rune prefab constructed.");
			}
			return val;
		}

		private static Mesh BuildQuad()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//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_0039: 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_0054: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00bd: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			Mesh val = new Mesh();
			val.vertices = (Vector3[])(object)new Vector3[4]
			{
				new Vector3(-0.5f, -0.5f, 0f),
				new Vector3(0.5f, -0.5f, 0f),
				new Vector3(-0.5f, 0.5f, 0f),
				new Vector3(0.5f, 0.5f, 0f)
			};
			val.uv = (Vector2[])(object)new Vector2[4]
			{
				new Vector2(0f, 0f),
				new Vector2(1f, 0f),
				new Vector2(0f, 1f),
				new Vector2(1f, 1f)
			};
			val.triangles = new int[6] { 0, 2, 1, 2, 3, 1 };
			val.RecalculateNormals();
			val.RecalculateBounds();
			return val;
		}
	}
	public class NjordRuneVFX_Billboard : MonoBehaviour
	{
		private void LateUpdate()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Camera.main != (Object)null)
			{
				((Component)this).transform.rotation = Quaternion.LookRotation(((Component)Camera.main).transform.forward);
			}
		}
	}
	public class NjordRuneVFX_Fader : MonoBehaviour
	{
		private float _age;

		private const float Lifetime = 1.5f;

		private const float FadeOut = 0.75f;

		private Material _mat;

		private Color _baseColor;

		private Vector3 _burstVelocity;

		private void Awake()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			MeshRenderer component = ((Component)this).GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				_mat = ((Renderer)component).material;
				if ((Object)(object)_mat != (Object)null)
				{
					_baseColor = _mat.GetColor("_Color");
				}
			}
			_burstVelocity = Random.insideUnitSphere * 1.5f;
			_burstVelocity.y = Mathf.Abs(_burstVelocity.y) + 0.3f;
		}

		private void Update()
		{
			//IL_0019: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00dc: 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_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			_age += Time.deltaTime;
			Transform transform = ((Component)this).transform;
			transform.position -= ((Component)this).transform.forward * (2.5f * Time.deltaTime);
			if (_age < 0.15f)
			{
				Transform transform2 = ((Component)this).transform;
				transform2.position += _burstVelocity * Time.deltaTime;
			}
			if ((Object)(object)_mat != (Object)null)
			{
				float num = Mathf.Clamp01((_age - 0.75f) / 0.75f);
				float a = Mathf.Lerp(1f, 0f, num);
				Color baseColor = _baseColor;
				baseColor.a = a;
				if (_mat.HasProperty("_Color"))
				{
					_mat.SetColor("_Color", baseColor);
				}
				if (_mat.HasProperty("_TintColor"))
				{
					_mat.SetColor("_TintColor", baseColor * 2f);
				}
				if (_mat.HasProperty("_EmissionColor"))
				{
					_mat.SetColor("_EmissionColor", baseColor * 3f);
				}
			}
			if (_age >= 1.5f)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
	public static class NjordRuneVFX_Helper
	{
		private static readonly Dictionary<Shader, Material> _materialCache = new Dictionary<Shader, Material>();

		private static bool _initialized = false;

		private static void Init()
		{
			if (!_initialized)
			{
				_initialized = true;
				NjordDebug.Info("\ud83d\udf01 VFX‑Forge: Seeking glowing, additive, unlit shaders worthy of Njord.");
			}
		}

		public static Material GetOrCreateRuneMaterial(Texture2D runeTex, Color color)
		{
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			Init();
			Shader val = null;
			float num = float.MinValue;
			Material[] array = Resources.FindObjectsOfTypeAll<Material>();
			foreach (Material val2 in array)
			{
				if ((Object)(object)val2 == (Object)null || (Object)(object)val2.shader == (Object)null)
				{
					continue;
				}
				Shader shader = val2.shader;
				if (!((Object)(object)shader == (Object)null) && val2.HasProperty("_Color") && val2.HasProperty("_EmissionColor"))
				{
					string text = ((Object)shader).name.ToLower();
					float num2 = 0f;
					if (text.Contains("particle"))
					{
						num2 += 3f;
					}
					if (text.Contains("add"))
					{
						num2 += 3f;
					}
					if (text.Contains("unlit"))
					{
						num2 += 2f;
					}
					if (text.Contains("transparent"))
					{
						num2 += 1.5f;
					}
					if (num2 > num)
					{
						num = num2;
						val = shader;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				NjordDebug.Error("\ud83d\udf01 VFX‑Forge: No glowing shader found. The runes refuse to shine.");
				return null;
			}
			if (_materialCache.TryGetValue(val, out var value))
			{
				return value;
			}
			Material val3 = new Material(val);
			if (val3.HasProperty("_MainTex"))
			{
				val3.SetTexture("_MainTex", (Texture)(object)runeTex);
			}
			if (val3.HasProperty("_Color"))
			{
				val3.SetColor("_Color", color);
			}
			if (val3.HasProperty("_EmissionColor"))
			{
				val3.SetColor("_EmissionColor", color * 3f);
			}
			val3.SetInt("_SrcBlend", 1);
			val3.SetInt("_DstBlend", 1);
			val3.SetInt("_ZWrite", 0);
			val3.DisableKeyword("_ALPHATEST_ON");
			val3.EnableKeyword("_ALPHABLEND_ON");
			val3.EnableKeyword("_ALPHAPREMULTIPLY_ON");
			val3.renderQueue = 3000;
			_materialCache[val] = val3;
			NjordDebug.Info("\ud83d\udf01 VFX‑Forge: Forged glowing additive rune material from " + ((Object)val).name + ".");
			return val3;
		}
	}
	public static class NjordSeaDogEngineVFXTriggers
	{
		public static readonly Dictionary<object, long> LastController = new Dictionary<object, long>();

		public static readonly Dictionary<object, string> LastSpeed = new Dictionary<object, string>();

		public static readonly Dictionary<object, float> LastVfxTime = new Dictionary<object, float>();

		public static Transform GetStern(Ship ship)
		{
			if ((Object)(object)ship == (Object)null)
			{
				return null;
			}
			Transform transform = ((Component)ship).transform;
			Transform val = transform.Find("SurfaceEffects/SpeedWake/rudder");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Transform val2 = transform.Find("SurfaceEffects/SpeedWake/aft_particles");
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
			Transform val3 = transform.Find("SurfaceEffects/SpeedWake/Trail");
			if ((Object)(object)val3 != (Object)null)
			{
				return val3;
			}
			Transform val4 = transform.Find("ship/visual_new/rudder_socket_Cube.004");
			if ((Object)(object)val4 != (Object)null)
			{
				return val4;
			}
			val4 = transform.Find("ship/visual_worn/rudder_socket_Cube.004");
			if ((Object)(object)val4 != (Object)null)
			{
				return val4;
			}
			val4 = transform.Find("ship/visual_broken/rudder_socket_Cube.004");
			if ((Object)(object)val4 != (Object)null)
			{
				return val4;
			}
			return transform;
		}

		public static void Process(Ship ship, NjordSailState state, string speedStr, long controller, float now, Transform tf, bool debug, NjordRuntimeConfig cfg)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: 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)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: 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_015d: Unknown result type (might be due to invalid IL or missing references)
			if (!cfg.VFX_Enable)
			{
				return;
			}
			if (!LastVfxTime.TryGetValue(ship, out var value))
			{
				value = 0f;
			}
			if (!LastController.TryGetValue(ship, out var value2))
			{
				value2 = 0L;
			}
			if (!LastSpeed.TryGetValue(ship, out var value3))
			{
				value3 = "Stop";
			}
			if (controller != value2)
			{
				LastController[ship] = controller;
				if (controller != 0L)
				{
					if (debug)
					{
						NjordDebug.Debug("[SeaDog][VFX] Control change: spawning control rune");
					}
					NjordRuneVFX.DiscoverShaderIfNeeded();
					LastVfxTime[ship] = now;
					NjordRuneVFX.Spawn(GetStern(ship).position + Vector3.up * 1.2f, cfg.VFX_Color);
				}
			}
			if (speedStr != value3)
			{
				LastSpeed[ship] = speedStr;
				if (speedStr == "Half" || speedStr == "Full")
				{
					if (debug)
					{
						NjordDebug.Debug("[SeaDog][VFX] Sail state change to " + speedStr + ": spawning burst");
					}
					NjordRuneVFX.DiscoverShaderIfNeeded();
					LastVfxTime[ship] = now;
					Vector3 val = GetStern(ship).position + Vector3.up * 1.5f;
					for (int i = 0; i < 4; i++)
					{
						Vector3 insideUnitSphere = Random.insideUnitSphere;
						insideUnitSphere.y = Mathf.Abs(insideUnitSphere.y) + 0.3f;
						NjordRuneVFX.Spawn(val + insideUnitSphere * 0.2f, cfg.VFX_Color);
					}
				}
			}
			if ((state == NjordSailState.Half || state == NjordSailState.Full) && now - value > 0.3f)
			{
				if (debug)
				{
					NjordDebug.Debug($"[SeaDog][VFX] Trail spawn: dt={now - value:0.00}");
				}
				NjordRuneVFX.DiscoverShaderIfNeeded();
				LastVfxTime[ship] = now;
				Transform stern = GetStern(ship);
				NjordRuneVFX.Spawn(stern.position - stern.forward * 0.5f + Vector3.up * 1.5f, cfg.VFX_Color);
			}
		}
	}
}
namespace Njord.Patches
{
	[HarmonyPatch(typeof(Player), "StartDoodadControl")]
	public static class NjordDoodadControlRune
	{
		private static void Postfix(Player __instance, IDoodadController shipControl)
		{
			if ((Object)(object)__instance == (Object)null || shipControl == null)
			{
				return;
			}
			ShipControlls val = (ShipControlls)(object)((shipControl is ShipControlls) ? shipControl : null);
			if (val == null)
			{
				return;
			}
			Ship ship = val.m_ship;
			if (!((Object)(object)ship == (Object)null))
			{
				long playerID = __instance.GetPlayerID();
				Njord_ShipControlTracker.SetControl(ship, playerID);
				if (NjordConfig.Debug_Enable.Value)
				{
					NjordDebug.Debug($"[Helm‑Bind] Player {playerID} takes helm of {((Object)ship).name}.");
				}
			}
		}
	}
	[HarmonyPatch(typeof(ShipControlls), "OnUseStop")]
	public static class NjordDoodadReleaseRune
	{
		private static void Postfix(ShipControlls __instance, Player player)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)player == (Object)null)
			{
				return;
			}
			Ship ship = __instance.m_ship;
			if (!((Object)(object)ship == (Object)null))
			{
				Njord_ShipControlTracker.ClearControl(ship);
				if (NjordConfig.Debug_Enable.Value)
				{
					NjordDebug.Debug("[Helm‑Release] Helm released for " + ((Object)ship).name + ".");
				}
			}
		}
	}
	[HarmonyPatch]
	public static class NjordSeaDogEngine
	{
		private static float _telemetryTimer;

		private const float TELEMETRY_INTERVAL = 0.2f;

		private static float _prevNjordSpeed;

		private static float _prevVanillaSpeed;

		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("Ship");
			if (type == null)
			{
				NjordDebug.Error("NjordSeaDogEngine: Ship type not found.");
				return null;
			}
			MethodInfo methodInfo = AccessTools.Method(type, "CustomFixedUpdate", (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				NjordDebug.Error("NjordSeaDogEngine: CustomFixedUpdate not found on Ship.");
			}
			return methodInfo;
		}

		public static float Safe(float v)
		{
			if (!float.IsNaN(v) && !float.IsInfinity(v))
			{
				return v;
			}
			return 0f;
		}

		private static void Prefix(object __instance, float fixedDeltaTime)
		{
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			if (__instance == null || fixedDeltaTime <= 0f)
			{
				return;
			}
			bool value = NjordConfig.Debug_Enable.Value;
			if (value)
			{
				NjordDebug.Debug($"[SeaDog] Tick dt={fixedDeltaTime:0.000}");
			}
			Type type = __instance.GetType();
			object obj = AccessTools.Field(type, "m_nview")?.GetValue(__instance);
			if (obj == null)
			{
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(obj.GetType(), "IsValid", (Type[])null, (Type[])null);
			if (methodInfo != null && !(bool)methodInfo.Invoke(obj, null))
			{
				return;
			}
			object? obj2 = AccessTools.Field(type, "m_body")?.GetValue(__instance);
			Rigidbody val = (Rigidbody)((obj2 is Rigidbody) ? obj2 : null);
			if (val == null || (Object)(object)val == (Object)null || float.IsNaN(val.mass) || val.mass <= 0f)
			{
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(type, "m_lastDepth");
			if (fieldInfo != null && (float)fieldInfo.GetValue(__instance) <= -9000f)
			{
				return;
			}
			long controllerForShip = Njord_ShipControlTracker.GetControllerForShip(__instance);
			Njord_ShipControlTracker.UpdateController(controllerForShip, fixedDeltaTime);
			bool flag = controllerForShip != 0;
			AccessTools.Field(type, "m_sailForceFactor")?.SetValue(__instance, 0f);
			AccessTools.Field(type, "m_sailForceOffset")?.SetValue(__instance, 0f);
			AccessTools.Field(type, "m_backwardForce")?.SetValue(__instance, 0f);
			AccessTools.Field(type, "m_sailForce")?.SetValue(__instance, Vector3.zero);
			string text = AccessTools.Method(type, "GetSpeedSetting", (Type[])null, (Type[])null)?.Invoke(__instance, null)?.ToString() ?? "Stop";
			NjordSailState njordSailState = text switch
			{
				"Back" => NjordSailState.Backward, 
				"Half" => NjordSailState.Half, 
				"Full" => NjordSailState.Full, 
				"Slow" => NjordSailState.Forward, 
				"Stop" => NjordSailState.Forward, 
				_ => NjordSailState.Forward, 
			};
			string shipPrefabName = NjordBoatController.GetShipPrefabName(__instance);
			float v = NjordBoatController.GetBaseline(njordSailState, shipPrefabName);
			if (text == "Stop")
			{
				v = 0f;
			}
			v = Safe(v);
			float num = Safe(NjordBoatController.ApplyAcceleration(v, fixedDeltaTime));
			float sailMult = NjordBoatController.GetSailMult(njordSailState);
			sailMult = Safe(sailMult);
			float num2 = Safe(num * sailMult * 0.85f);
			float num3 = Safe(NjordBoatController.GetReverseForce(fixedDeltaTime));
			num2 = Mathf.Clamp(num2, 0f, 2000f);
			num3 = Mathf.Clamp(num3, 0f, 2000f);
			object? obj3 = AccessTools.Property(type, "transform")?.GetValue(__instance);
			Transform val2 = (Transform)((obj3 is Transform) ? obj3 : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			Vector3 val3;
			switch (njordSailState)
			{
			case NjordSailState.Backward:
				val3 = -val2.forward * num3;
				break;
			case NjordSailState.Forward:
			case NjordSailState.Half:
			case NjordSailState.Full:
				val3 = val2.forward * num2;
				break;
			default:
				val3 = Vector3.zero;
				break;
			}
			Vector3 val4 = val3;
			if (((Vector3)(ref val4)).sqrMagnitude > 0.0001f)
			{
				val.AddForce(val4 * val.mass * fixedDeltaTime, (ForceMode)1);
			}
			if (!flag)
			{
				return;
			}
			Ship val5 = (Ship)((__instance is Ship) ? __instance : null);
			if (val5 == null)
			{
				return;
			}
			if (value)
			{
				NjordDebug.Debug($"[SeaDog] Controlled ship tick: speedState={text}, vel={val5.GetSpeed():0.0}");
			}
			_telemetryTimer += fixedDeltaTime;
			if (_telemetryTimer >= 0.2f)
			{
				_telemetryTimer = 0f;
				Vector3 position = ((Component)val5).transform.position;
				WaterVolume val6 = null;
				float waterLevel = Floating.GetWaterLevel(position, ref val6);
				float num4 = position.y - waterLevel - val5.m_waterLevelOffset;
				bool floating = num4 <= val5.m_disableLevel;
				WearNTear component = ((Component)val5).GetComponent<WearNTear>();
				if ((Object)(object)component != (Object)null)
				{
					object? obj4 = AccessTools.Field(typeof(WearNTear), "m_nview")?.GetValue(component);
					ZNetView val7 = (ZNetView)((obj4 is ZNetView) ? obj4 : null);
					if ((Object)(object)val7 != (Object)null && val7.IsValid())
					{
						float num5 = Mathf.Max(1f, Safe(component.m_health));
						float @float = val7.GetZDO().GetFloat(ZDOVars.s_health, num5);
						@float = Mathf.Max(0f, Safe(@float));
						Njord_Telemetry.SetHP(@float, num5);
						if (value)
						{
							NjordDebug.Debug($"[SeaDog][Telem] HP={@float:0.0}/{num5:0.0}");
						}
					}
					else
					{
						Njord_Telemetry.SetHP(0f, 1f);
						if (value)
						{
							NjordDebug.Debug("[SeaDog][Telem] HP=0/1 (no valid m_nview)");
						}
					}
				}
				else
				{
					Njord_Telemetry.SetHP(0f, 1f);
					if (value)
					{
						NjordDebug.Debug("[SeaDog][Telem] HP=0/1 (no WearNTear)");
					}
				}
				float num6 = Safe(val5.GetSpeed());
				float num7 = Safe(v);
				Njord_Telemetry.UpdateBasic(val5, waterLevel, num4, floating, Njord_ShipControlTracker.ReadyTimer, Njord_ShipControlTracker.SteeringGateReady);
				Njord_Telemetry.UpdateShip(val5, Njord_ShipControlTracker.SteeringGateReady, Njord_ShipControlTracker.ReadyTimer, 0.35f, val5.m_disableLevel, 0.2f);
				Njord_Telemetry.UpdateSpeed(_prevNjordSpeed, num6, _prevVanillaSpeed, num7);
				_prevNjordSpeed = num6;
				_prevVanillaSpeed = num7;
			}
			NjordSeaDogEngineVFXTriggers.Process(val5, njordSailState, text, controllerForShip, Time.time, val2, value, NjordSync.RuntimeConfig ?? NjordRuntimeConfig.FromConfig());
		}
	}
	[HarmonyPatch(typeof(EnvMan), "UpdateWind")]
	public static class NjordTheWindsCall
	{
		[HarmonyPostfix]
		public static void Postfix(EnvMan __instance)
		{
			//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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			NjordRuntimeConfig runtimeConfig = NjordSync.RuntimeConfig;
			if (runtimeConfig != null)
			{
				Vector3 windDir = __instance.GetWindDir();
				float windIntensity = __instance.GetWindIntensity();
				float num = Mathf.Clamp01(windIntensity * runtimeConfig.WindBlend);
				Color color = default(Color);
				((Color)(ref color))..ctor(0.5f + 0.5f * Mathf.Abs(windDir.x), 0.5f + 0.5f * Mathf.Abs(windDir.z), 0.7f, 1f);
				Njord_Telemetry.SetWindUI(num, color);
				if (NjordConfig.Debug_Enable.Value)
				{
					NjordDebug.Debug($"[Wind] mag={windIntensity:0.00}, blend={num:0.00}");
				}
			}
		}
	}
	[HarmonyPatch(typeof(ZNet), "Awake")]
	public static class Njord_ZNet_Awake_Patch
	{
		[CompilerGenerated]
		private sealed class <InitHUD>d__1 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <InitHUD>d__1(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					NjordDebug.Info("\ud83d\udf01 The crisp salty air fills your lungs..");
					Njord_DebugHUD.Ensure();
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[HarmonyPostfix]
		public static void Postfix(ZNet __instance)
		{
			NjordDebug.Info("⚒ The longship stirs. ZNet awakens. Njord’s runes gather.");
			NjordSync.Initialize();
			((MonoBehaviour)__instance).StartCoroutine(InitHUD());
		}

		[IteratorStateMachine(typeof(<InitHUD>d__1))]
		private static IEnumerator InitHUD()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <InitHUD>d__1(0);
		}
	}
	[HarmonyPatch(typeof(Ship), "ApplyControlls")]
	public static class Patch_Ship_ApplyControlls
	{
		[HarmonyPostfix]
		public static void Postfix(Ship __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				_ = Time.fixedDeltaTime;
				Type type = ((object)__instance).GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "m_rudder") ?? AccessTools.Field(type, "m_rudderValue");
				float num = 0f;
				if (fieldInfo != null)
				{
					num = (float)fieldInfo.GetValue(__instance);
				}
				float steeringMultiplier = NjordSync.RuntimeConfig.SteeringMultiplier;
				float njord = num * steeringMultiplier;
				Njord_Telemetry.ReportRudder(num, njord, steeringMultiplier);
			}
		}
	}
}
namespace Njord.Core
{
	public static class NjordConfig
	{
		public static ConfigEntry<float> SteeringMultiplier;

		public static ConfigEntry<float> AccelerationMultiplier;

		public static ConfigEntry<float> BaseForwardForce;

		public static ConfigEntry<float> BaseReverseForce;

		public static ConfigEntry<float> SailForwardForce;

		public static ConfigEntry<float> HalfSailForce;

		public static ConfigEntry<float> FullSailForce;

		public static ConfigEntry<float> ReverseKick;

		public static ConfigEntry<float> WindBlend;

		public static ConfigEntry<bool> VFX_Enable;

		public static ConfigEntry<Color> VFX_Color;

		public static ConfigEntry<bool> Debug_Enable;

		public static void Bind(ConfigFile file)
		{
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			SteeringMultiplier = file.Bind<float>("Steering", "SteeringMultiplier", 1.85f, "Multiplier applied to rudder steering. Range: 0.1 – 5.0");
			AccelerationMultiplier = file.Bind<float>("Acceleration", "AccelerationMultiplier", 2.2f, "Acceleration multiplier. Range: 0.1 – 5.0");
			BaseForwardForce = file.Bind<float>("Acceleration", "BaseForwardForce", 1f, "Base forward force. Range: 0.1 – 20.0");
			BaseReverseForce = file.Bind<float>("Acceleration", "BaseReverseForce", 1f, "Base reverse force. Range: 0.1 – 10.0");
			SailForwardForce = file.Bind<float>("Sails", "SailForwardForce", 0.3f, "Forward force when sails are down. Range: 0.1 – 2.0");
			HalfSailForce = file.Bind<float>("Sails", "HalfSailForce", 1.6f, "Forward force at half sail. Range: 0.1 – 3.0");
			FullSailForce = file.Bind<float>("Sails", "FullSailForce", 2.8f, "Forward force at full sail. Range: 0.1 – 5.0");
			ReverseKick = file.Bind<float>("Sails", "ReverseKick", 1.25f, "Reverse kick multiplier. Range: 0.1 – 3.0");
			WindBlend = file.Bind<float>("Wind", "WindBlend", 1f, "Blend factor for wind influence. Range: 0.0 – 1.0");
			VFX_Enable = file.Bind<bool>("VFX", "VFX_Enable", false, "Enable rune VFX.");
			VFX_Color = file.Bind<Color>("VFX", "VFX_Color", new Color(0.3f, 0.6f, 1f, 1f), "Rune VFX color.");
			Debug_Enable = file.Bind<bool>("Debug", "Debug_Enable", false, "Enable Njord debug logs (local only).");
		}
	}
	public class NjordRuntimeConfig
	{
		public float SteeringMultiplier;

		public float AccelerationMultiplier;

		public float BaseForwardForce;

		public float BaseReverseForce;

		public float SailForwardForce;

		public float HalfSailForce;

		public float FullSailForce;

		public float ReverseKick;

		public float WindBlend;

		public bool VFX_Enable;

		public Color VFX_Color;

		private static float Safe(float v, float min, float max)
		{
			if (float.IsNaN(v) || float.IsInfinity(v))
			{
				return min;
			}
			return Mathf.Clamp(v, min, max);
		}

		public void Sanitize()
		{
			SteeringMultiplier = Safe(SteeringMultiplier, 0.1f, 5f);
			AccelerationMultiplier = Safe(AccelerationMultiplier, 0.1f, 5f);
			BaseForwardForce = Safe(BaseForwardForce, 0.1f, 20f);
			BaseReverseForce = Safe(BaseReverseForce, 0.1f, 10f);
			SailForwardForce = Safe(SailForwardForce, 0.1f, 2f);
			HalfSailForce = Safe(HalfSailForce, 0.1f, 3f);
			FullSailForce = Safe(FullSailForce, 0.1f, 5f);
			ReverseKick = Safe(ReverseKick, 0.1f, 3f);
			WindBlend = Safe(WindBlend, 0f, 1f);
			VFX_Color.r = Mathf.Clamp01(VFX_Color.r);
			VFX_Color.g = Mathf.Clamp01(VFX_Color.g);
			VFX_Color.b = Mathf.Clamp01(VFX_Color.b);
			VFX_Color.a = Mathf.Clamp01(VFX_Color.a);
		}

		public static NjordRuntimeConfig FromConfig()
		{
			//IL_00ab: 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)
			NjordRuntimeConfig njordRuntimeConfig = new NjordRuntimeConfig();
			njordRuntimeConfig.SteeringMultiplier = NjordConfig.SteeringMultiplier.Value;
			njordRuntimeConfig.AccelerationMultiplier = NjordConfig.AccelerationMultiplier.Value;
			njordRuntimeConfig.BaseForwardForce = NjordConfig.BaseForwardForce.Value;
			njordRuntimeConfig.BaseReverseForce = NjordConfig.BaseReverseForce.Value;
			njordRuntimeConfig.SailForwardForce = NjordConfig.SailForwardForce.Value;
			njordRuntimeConfig.HalfSailForce = NjordConfig.HalfSailForce.Value;
			njordRuntimeConfig.FullSailForce = NjordConfig.FullSailForce.Value;
			njordRuntimeConfig.ReverseKick = NjordConfig.ReverseKick.Value;
			njordRuntimeConfig.WindBlend = NjordConfig.WindBlend.Value;
			njordRuntimeConfig.VFX_Enable = NjordConfig.VFX_Enable.Value;
			njordRuntimeConfig.VFX_Color = NjordConfig.VFX_Color.Value;
			njordRuntimeConfig.Sanitize();
			return njordRuntimeConfig;
		}
	}
	public enum NjordSailState
	{
		Forward,
		Half,
		Full,
		Backward
	}
	public static class NjordSync
	{
		private const string RPC_NAME = "Njord_Config";

		public static NjordRuntimeConfig RuntimeConfig { get; private set; } = new NjordRuntimeConfig();


		public static void InitializeFromConfig()
		{
			RuntimeConfig = NjordRuntimeConfig.FromConfig();
		}

		public static void ReloadRuntimeConfig()
		{
			RuntimeConfig = NjordRuntimeConfig.FromConfig();
		}

		public static void Initialize()
		{
			if (!((Object)(object)ZNet.instance == (Object)null))
			{
				RegisterRpc();
				if (ZNet.instance.IsServer())
				{
					BroadcastConfig();
				}
			}
		}

		private static void RegisterRpc()
		{
			if (ZRoutedRpc.instance != null)
			{
				ZRoutedRpc.instance.Register<ZPackage>("Njord_Config", (Action<long, ZPackage>)RPC_ReceiveConfig);
			}
		}

		private static void BroadcastConfig()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			if (ZRoutedRpc.instance != null)
			{
				ZPackage val = new ZPackage();
				WriteConfig(val, RuntimeConfig);
				ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "Njord_Config", new object[1] { val });
			}
		}

		private static void RPC_ReceiveConfig(long sender, ZPackage pkg)
		{
			NjordRuntimeConfig njordRuntimeConfig = new NjordRuntimeConfig();
			ReadConfig(pkg, njordRuntimeConfig);
			njordRuntimeConfig.Sanitize();
			RuntimeConfig = njordRuntimeConfig;
		}

		private static void WriteConfig(ZPackage pkg, NjordRuntimeConfig cfg)
		{
			cfg.Sanitize();
			pkg.Write(cfg.SteeringMultiplier);
			pkg.Write(cfg.AccelerationMultiplier);
			pkg.Write(cfg.BaseForwardForce);
			pkg.Write(cfg.BaseReverseForce);
			pkg.Write(cfg.SailForwardForce);
			pkg.Write(cfg.HalfSailForce);
			pkg.Write(cfg.FullSailForce);
			pkg.Write(cfg.ReverseKick);
			pkg.Write(cfg.WindBlend);
			pkg.Write(cfg.VFX_Enable);
			pkg.Write(cfg.VFX_Color.r);
			pkg.Write(cfg.VFX_Color.g);
			pkg.Write(cfg.VFX_Color.b);
			pkg.Write(cfg.VFX_Color.a);
		}

		private static void ReadConfig(ZPackage pkg, NjordRuntimeConfig cfg)
		{
			//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)
			cfg.SteeringMultiplier = pkg.ReadSingle();
			cfg.AccelerationMultiplier = pkg.ReadSingle();
			cfg.BaseForwardForce = pkg.ReadSingle();
			cfg.BaseReverseForce = pkg.ReadSingle();
			cfg.SailForwardForce = pkg.ReadSingle();
			cfg.HalfSailForce = pkg.ReadSingle();
			cfg.FullSailForce = pkg.ReadSingle();
			cfg.ReverseKick = pkg.ReadSingle();
			cfg.WindBlend = pkg.ReadSingle();
			cfg.VFX_Enable = pkg.ReadBool();
			float num = pkg.ReadSingle();
			float num2 = pkg.ReadSingle();
			float num3 = pkg.ReadSingle();
			float num4 = pkg.ReadSingle();
			cfg.VFX_Color = new Color(num, num2, num3, num4);
		}
	}
	public static class Njord_Telemetry
	{
		public static string VesselName = "Unknown";

		public static bool GateReady = false;

		public static bool IsFloating = false;

		public static float WaterLevel = 0f;

		public static float BoatY = 0f;

		public static float Depth = 0f;

		public static float DisableLevel = 0f;

		public static float ReadinessTimer = 0f;

		public static float ReadinessMax = 0f;

		public static float HPCurrent = 0f;

		public static float HPMax = 1f;

		public static float RudderVanilla = 0f;

		public static float RudderNjord = 0f;

		public static float SteeringMultiplier = 1f;

		public static float SteeringGainPerSecond = 0f;

		private static float _lastRudder = 0f;

		private static float _lastRudderTime = 0f;

		public static float SpeedCurrent = 0f;

		public static float SpeedVanillaBaseline = 0f;

		public static float SpeedGainPerSecond = 0f;

		private static float _lastSpeed = 0f;

		private static float _lastSpeedTime = 0f;

		public static float NjordSpeedPrev = 0f;

		public static float NjordSpeedCurr = 0f;

		public static float MortalSpeedPrev = 0f;

		public static float MortalSpeedCurr = 0f;

		public static float WindUIBlend = 0f;

		public static Color WindUIColor = Color.white;

		public static bool HasError = false;

		public static bool DepthError = false;

		public static bool WaterError = false;

		public static bool SpeedError = false;

		public static bool RudderError = false;

		public static void ClearErrors()
		{
			HasError = (DepthError = (WaterError = (SpeedError = (RudderError = false))));
		}

		public static void UpdateBasic(Ship ship, float waterLevel, float depth, bool floating, float readinessTimer, bool gateReady)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)ship))
			{
				return;
			}
			VesselName = ((Object)ship).name;
			GateReady = gateReady;
			IsFloating = floating;
			ClearErrors();
			if (float.IsNaN(waterLevel) || float.IsInfinity(waterLevel))
			{
				WaterError = true;
				HasError = true;
				waterLevel = ((Component)ship).transform.position.y;
			}
			WaterLevel = waterLevel;
			BoatY = ((Component)ship).transform.position.y;
			if (float.IsNaN(depth) || float.IsInfinity(depth))
			{
				DepthError = true;
				HasError = true;
				depth = 0f;
			}
			Depth = depth;
			DisableLevel = ship.m_disableLevel;
			ReadinessTimer = readinessTimer;
			ReadinessMax = 0.35f;
			float time = Time.time;
			if (_lastSpeedTime > 0f)
			{
				float num = time - _lastSpeedTime;
				if (num > 0f)
				{
					SpeedGainPerSecond = (SpeedCurrent - _lastSpeed) / num;
				}
			}
			_lastSpeed = SpeedCurrent;
			_lastSpeedTime = time;
		}

		public static void UpdateShip(Ship ship, bool gateReady, float readinessTimer, float readinessMax, float disableLevel, float dt)
		{
		}

		public static void SetHP(float hp, float maxHp)
		{
			HPCurrent = Mathf.Max(0f, hp);
			HPMax = Mathf.Max(1f, maxHp);
		}

		public static void ReportRudder(float vanilla, float njord, float mult)
		{
			if (float.IsNaN(njord))
			{
				RudderError = true;
				HasError = true;
				njord = 0f;
			}
			RudderVanilla = vanilla;
			RudderNjord = njord;
			SteeringMultiplier = mult;
			float time = Time.time;
			if (_lastRudderTime > 0f)
			{
				float num = time - _lastRudderTime;
				if (num > 0f)
				{
					SteeringGainPerSecond = (njord - _lastRudder) / num;
				}
			}
			_lastRudder = njord;
			_lastRudderTime = time;
		}

		public static void SetWindUI(float blend, Color color)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			WindUIBlend = Mathf.Clamp01(blend);
			WindUIColor = color;
		}

		public static void SetVanillaSpeedBaseline(float baseline)
		{
			SpeedVanillaBaseline = baseline;
		}

		public static void UpdateSpeed(float prevNjord, float currNjord, float prevMortal, float currMortal)
		{
			if (float.IsNaN(currNjord))
			{
				SpeedError = true;
				HasError = true;
				currNjord = 0f;
			}
			NjordSpeedPrev = prevNjord;
			NjordSpeedCurr = currNjord;
			MortalSpeedPrev = prevMortal;
			MortalSpeedCurr = currMortal;
			SpeedCurrent = currNjord;
			SpeedVanillaBaseline = currMortal;
			float time = Time.time;
			if (_lastSpeedTime > 0f)
			{
				float num = time - _lastSpeedTime;
				if (num > 0f)
				{
					SpeedGainPerSecond = (currNjord - _lastSpeed) / num;
				}
			}
			_lastSpeed = currNjord;
			_lastSpeedTime = time;
		}
	}
	public static class NjordPatchCaller
	{
		private static Harmony harmony;

		public static void ApplyPatches()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			if (harmony == null)
			{
				harmony = new Harmony("wubarrk.njord");
			}
			NjordDebug.Info("When Njord stirs, the runes awaken…");
			BindRune("Njord’s Fang‑Rune", typeof(NjordSeaDogEngine), "The deep bares its fangs and drives the longship onward.", "The Fang‑Rune cracks, but the sea remembers its path.");
			BindRune("Hrafn‑Skygg Rune", typeof(NjordTheWindsCall), "The ravens whisper the winds’ hidden counsel.", "The Raven‑Sight Rune dims, yet the sky still watches.");
			BindRune("Stýri‑Hjarta Rune", typeof(Patch_Ship_ApplyControlls), "The helm‑heart beats in rhythm with mortal will.", "The Helm‑Heart falters, but the rudder keeps its vigil.");
			BindRune("Band‑Njörðr Rune", typeof(NjordDoodadControlRune), "Njord knots the helmsman’s spirit to the vessel’s wyrd.", "The Binding Rune slips, yet the helm awaits another hand.");
			BindRune("Leys‑Njörðr Rune", typeof(NjordDoodadReleaseRune), "Njord loosens the knot; the helm drifts free into quiet waters.", "The Loosening Rune fades, but the sea releases its hold.");
			NjordDebug.Info("The longship answers the call of the deep.");
		}

		private static void BindRune(string runeName, Type patchType, string successSaga, string failureSaga)
		{
			NjordDebug.Info("Invoking " + runeName + "…");
			try
			{
				harmony.PatchAll(patchType);
				NjordDebug.Info(successSaga);
			}
			catch (Exception ex)
			{
				NjordDebug.Warn(failureSaga ?? "");
				NjordDebug.Warn("Rune‑scribe’s note: " + ex.Message);
			}
		}
	}
	public static class NjordRuneTextureGenerator
	{
		private const int Size = 128;

		public static Texture2D GenerateRune(Color color)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			int runeIndex = Mathf.Abs(((object)(Color)(ref color)).GetHashCode()) % 5;
			return GenerateRune(color, runeIndex);
		}

		public static Texture2D GenerateRune(Color color, int runeIndex)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false);
			((Texture)val).filterMode = (FilterMode)1;
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0f, 0f, 0f, 0f);
			Color c = color * 0.4f;
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					val.SetPixel(j, i, val2);
				}
			}
			switch (runeIndex)
			{
			case 0:
				DrawLine(val, 20, 20, 108, 108, c, 6);
				DrawLine(val, 108, 20, 20, 108, c, 6);
				DrawLine(val, 20, 20, 108, 108, color, 3);
				DrawLine(val, 108, 20, 20, 108, color, 3);
				break;
			case 1:
				DrawLine(val, 64, 16, 64, 112, c, 6);
				DrawLine(val, 64, 16, 64, 112, color, 3);
				DrawLine(val, 64, 64, 32, 96, c, 5);
				DrawLine(val, 64, 64, 96, 96, c, 5);
				DrawLine(val, 64, 64, 32, 96, color, 2);
				DrawLine(val, 64, 64, 96, 96, color, 2);
				break;
			case 2:
				DrawLine(val, 40, 20, 40, 108, c, 6);
				DrawLine(val, 40, 20, 40, 108, color, 3);
				DrawLine(val, 40, 96, 96, 112, c, 5);
				DrawLine(val, 40, 96, 96, 112, color, 2);
				DrawLine(val, 40, 72, 96, 88, c, 5);
				DrawLine(val, 40, 72, 96, 88, color, 2);
				break;
			case 3:
				DrawLine(val, 40, 20, 40, 112, c, 6);
				DrawLine(val, 40, 20, 40, 112, color, 3);
				DrawLine(val, 40, 96, 88, 112, c, 5);
				DrawLine(val, 88, 112, 88, 80, c, 5);
				DrawLine(val, 88, 80, 40, 96, c, 5);
				DrawLine(val, 40, 96, 88, 112, color, 2);
				DrawLine(val, 88, 112, 88, 80, color, 2);
				DrawLine(val, 88, 80, 40, 96, color, 2);
				break;
			default:
				DrawLine(val, 64, 16, 64, 112, c, 8);
				DrawLine(val, 64, 16, 64, 112, color, 4);
				break;
			}
			val.Apply();
			return val;
		}

		private static void DrawLine(Texture2D tex, int x0, int y0, int x1, int y1, Color c, int thickness)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Abs(x1 - x0);
			int num2 = Mathf.Abs(y1 - y0);
			int num3 = ((x0 < x1) ? 1 : (-1));
			int num4 = ((y0 < y1) ? 1 : (-1));
			int num5 = num - num2;
			while (true)
			{
				DrawCircle(tex, x0, y0, thickness, c);
				if (x0 != x1 || y0 != y1)
				{
					int num6 = 2 * num5;
					if (num6 > -num2)
					{
						num5 -= num2;
						x0 += num3;
					}
					if (num6 < num)
					{
						num5 += num;
						y0 += num4;
					}
					continue;
				}
				break;
			}
		}

		private static void DrawCircle(Texture2D tex, int cx, int cy, int r, Color c)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			for (int i = -r; i <= r; i++)
			{
				for (int j = -r; j <= r; j++)
				{
					if (j * j + i * i <= r * r)
					{
						int num = cx + j;
						int num2 = cy + i;
						if (num >= 0 && num < 128 && num2 >= 0 && num2 < 128)
						{
							tex.SetPixel(num, num2, c);
						}
					}
				}
			}
		}
	}
}