Decompiled source of GuakRogueWaves v2.9.0

Eden.RogueWaves.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Eden.RogueWaves;

[BepInPlugin("eden.valheim.roguewaves", "Guak Rogue Waves", "2.9.0")]
public class RogueWavesPlugin : BaseUnityPlugin
{
	private sealed class WaveVisual
	{
		private const int SurfaceCols = 17;

		private const int SurfaceRows = 9;

		public readonly long Id;

		private readonly GameObject root;

		private readonly Mesh surfaceMesh;

		private readonly MeshRenderer surfaceRenderer;

		private readonly Vector3[] surfaceVertices;

		private readonly Vector2[] surfaceUvs;

		private readonly int[] surfaceTriangles;

		private readonly ParticleSystem sprayParticles;

		private readonly ParticleSystemRenderer sprayRenderer;

		public WaveVisual(long id)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			//IL_0122: 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)
			Id = id;
			root = new GameObject("GuakRogueWaveVisual_" + id);
			((Object)root).hideFlags = (HideFlags)52;
			GameObject val = new GameObject("crest_surface");
			((Object)val).hideFlags = (HideFlags)52;
			val.transform.SetParent(root.transform, false);
			MeshFilter val2 = val.AddComponent<MeshFilter>();
			surfaceRenderer = val.AddComponent<MeshRenderer>();
			((Renderer)surfaceRenderer).receiveShadows = false;
			((Renderer)surfaceRenderer).shadowCastingMode = (ShadowCastingMode)0;
			surfaceMesh = new Mesh();
			((Object)surfaceMesh).name = "GuakRogueWaveCrestMesh_" + id;
			surfaceMesh.MarkDynamic();
			val2.sharedMesh = surfaceMesh;
			surfaceVertices = (Vector3[])(object)new Vector3[153];
			surfaceUvs = (Vector2[])(object)new Vector2[surfaceVertices.Length];
			surfaceTriangles = BuildSurfaceTriangles();
			for (int i = 0; i < 9; i++)
			{
				for (int j = 0; j < 17; j++)
				{
					int num = i * 17 + j;
					ref Vector2 reference = ref surfaceUvs[num];
					reference = new Vector2((float)j / 16f, (float)i / 8f);
				}
			}
			surfaceMesh.vertices = surfaceVertices;
			surfaceMesh.uv = surfaceUvs;
			surfaceMesh.triangles = surfaceTriangles;
			((Renderer)surfaceRenderer).enabled = false;
			GameObject val3 = new GameObject("spray");
			((Object)val3).hideFlags = (HideFlags)52;
			val3.transform.SetParent(root.transform, false);
			sprayParticles = val3.AddComponent<ParticleSystem>();
			sprayRenderer = val3.GetComponent<ParticleSystemRenderer>();
			ConfigureSprayParticles();
		}

		private void ConfigureSprayParticles()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: 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)
			if ((Object)(object)sprayParticles == (Object)null)
			{
				return;
			}
			MainModule main = sprayParticles.main;
			((MainModule)(ref main)).loop = true;
			((MainModule)(ref main)).playOnAwake = false;
			((MainModule)(ref main)).simulationSpace = (ParticleSystemSimulationSpace)1;
			((MainModule)(ref main)).maxParticles = 420;
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(0.9f, 2.1f);
			((MainModule)(ref main)).startSpeed = new MinMaxCurve(1.4f, 5.2f);
			((MainModule)(ref main)).startSize = new MinMaxCurve(0.11f, 0.4f);
			((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(0.8f, 0.94f, 1f, 0.46f));
			((MainModule)(ref main)).gravityModifier = new MinMaxCurve(0.1f);
			EmissionModule emission = sprayParticles.emission;
			((EmissionModule)(ref emission)).enabled = true;
			((EmissionModule)(ref emission)).rateOverTime = new MinMaxCurve(0f);
			ShapeModule shape = sprayParticles.shape;
			((ShapeModule)(ref shape)).enabled = true;
			((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)5;
			((ShapeModule)(ref shape)).scale = new Vector3(32f, 2f, 6f);
			if ((Object)(object)sprayRenderer != (Object)null)
			{
				sprayRenderer.renderMode = (ParticleSystemRenderMode)0;
				((Renderer)sprayRenderer).receiveShadows = false;
				((Renderer)sprayRenderer).shadowCastingMode = (ShadowCastingMode)0;
				if ((Object)(object)visualFoamMaterial != (Object)null)
				{
					((Renderer)sprayRenderer).sharedMaterial = visualFoamMaterial;
				}
			}
			sprayParticles.Stop();
		}

		public void Update(RogueWave wave, double now, float sea)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_004d: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_00b8: 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_00ec: 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_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 crestCenter = wave.GetCrestCenter(now);
			float visualFade = wave.GetVisualFade(now);
			float num = Mathf.Clamp(wave.Length * 0.08f, 6f, wave.IsGiga ? 40f : 24f);
			float height = wave.GetHeight(crestCenter, now);
			float height2 = wave.GetHeight(crestCenter + wave.Direction * num, now);
			float height3 = wave.GetHeight(crestCenter - wave.Direction * num, now);
			height = Mathf.Max(height, Mathf.Max(height2, height3));
			float num2 = Mathf.Max(0.08f, height * (wave.IsGiga ? 0.84f : 0.74f));
			root.transform.rotation = Quaternion.LookRotation(wave.Direction, Vector3.up);
			root.transform.position = new Vector3(crestCenter.x, sea + 0.03f, crestCenter.z);
			UpdateSurface(wave, now, crestCenter, visualFade);
			if ((Object)(object)sprayParticles != (Object)null)
			{
				((Component)sprayParticles).transform.localPosition = new Vector3(0f, num2 + (wave.IsGiga ? 1f : 0.45f), 0f);
			}
			UpdateSpray(wave, now, crestCenter, wave.VisualHalfWidth, visualFade, height);
		}

		private static int[] BuildSurfaceTriangles()
		{
			int[] array = new int[768];
			int num = 0;
			for (int i = 0; i < 8; i++)
			{
				for (int j = 0; j < 16; j++)
				{
					int num2 = i * 17 + j;
					int num3 = num2 + 1;
					int num4 = num2 + 17;
					int num5 = num4 + 1;
					array[num++] = num2;
					array[num++] = num4;
					array[num++] = num3;
					array[num++] = num3;
					array[num++] = num4;
					array[num++] = num5;
				}
			}
			return array;
		}

		private void UpdateSurface(RogueWave wave, double now, Vector3 crest, float fade)
		{
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: 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_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			if (!AllowSurfaceVisuals() || !(cfgVisualSurfaceAlpha.Value > 0.001f) || !((Object)(object)visualSurfaceMaterial != (Object)null) || !(fade > 0.001f) || !(wave.DepthScale > 0.05f))
			{
				if ((Object)(object)surfaceRenderer != (Object)null)
				{
					((Renderer)surfaceRenderer).enabled = false;
				}
				return;
			}
			if ((Object)(object)surfaceRenderer != (Object)null)
			{
				if ((Object)(object)((Renderer)surfaceRenderer).sharedMaterial != (Object)(object)visualSurfaceMaterial)
				{
					((Renderer)surfaceRenderer).sharedMaterial = visualSurfaceMaterial;
				}
				((Renderer)surfaceRenderer).enabled = true;
			}
			float num = Mathf.Clamp(wave.VisualHalfWidth * (wave.IsGiga ? 0.88f : 0.74f), wave.IsGiga ? 160f : 55f, wave.IsGiga ? 480f : 230f);
			float num2 = Mathf.Clamp(wave.VisualHalfLength * (wave.IsGiga ? 1.05f : 0.95f), wave.IsGiga ? 90f : 26f, wave.IsGiga ? 230f : 92f);
			for (int i = 0; i < 9; i++)
			{
				float num3 = (float)i / 8f;
				float num4 = Mathf.Lerp(0f - num2, num2, num3);
				float num5 = Mathf.Clamp01(1f - Mathf.Abs(num4) / num2);
				for (int j = 0; j < 17; j++)
				{
					float num6 = (float)j / 16f;
					float num7 = Mathf.Lerp(0f - num, num, num6);
					float num8 = Mathf.Clamp01(1f - Mathf.Abs(num7) / num);
					float num9 = Mathf.Sqrt(Mathf.Clamp01(num8 * 1.55f)) * Mathf.Sqrt(Mathf.Clamp01(num5 * 1.85f));
					Vector3 worldPos = crest + wave.Right * num7 + wave.Direction * num4;
					float num10 = Mathf.Max(0f, wave.GetHeight(worldPos, now));
					float num11 = ((num10 > 0.06f) ? (num10 * num9 * fade) : 0.015f);
					ref Vector3 reference = ref surfaceVertices[i * 17 + j];
					reference = new Vector3(num7, num11 + 0.02f, num4);
				}
			}
			surfaceMesh.vertices = surfaceVertices;
			surfaceMesh.uv = surfaceUvs;
			surfaceMesh.triangles = surfaceTriangles;
			surfaceMesh.RecalculateNormals();
			surfaceMesh.RecalculateBounds();
		}

		private void UpdateSpray(RogueWave wave, double now, Vector3 crest, float halfWidth, float fade, float crestHeight)
		{
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: 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_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: 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_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sprayParticles == (Object)null)
			{
				return;
			}
			if ((!NativeFoamCueActive() && !cfgVisualParticleSprayEnabled.Value) || !(EffectiveSprayRate() > 0.001f) || !(EffectiveFoamAlpha() > 0.001f) || !(fade > 0.001f) || !(wave.DepthScale > 0.05f))
			{
				if (sprayParticles.isPlaying)
				{
					sprayParticles.Stop();
				}
				return;
			}
			if ((Object)(object)sprayRenderer != (Object)null && (Object)(object)visualFoamMaterial != (Object)null && (Object)(object)((Renderer)sprayRenderer).sharedMaterial != (Object)(object)visualFoamMaterial)
			{
				((Renderer)sprayRenderer).sharedMaterial = visualFoamMaterial;
			}
			float num = (float)(now - wave.StartTime);
			float num2 = wave.Height * Mathf.Max(0.05f, wave.DepthScale);
			float num3 = Mathf.Max(0.5f, Mathf.Max(crestHeight, num2 * 0.65f));
			float num4 = Mathf.Clamp01(num3 / (wave.IsGiga ? 18f : 11f));
			float num5 = 0.68f + Mathf.Sin(num * (wave.IsGiga ? 2f : 2.7f)) * 0.18f;
			float num6 = EffectiveSprayRate() * fade * Mathf.Clamp01(num5) * Mathf.Lerp(18f, wave.IsGiga ? 160f : 74f, num4);
			MainModule main = sprayParticles.main;
			((MainModule)(ref main)).startLifetime = new MinMaxCurve(wave.IsGiga ? 1.35f : 0.95f, wave.IsGiga ? 3.4f : 2.35f);
			((MainModule)(ref main)).startSpeed = new MinMaxCurve(wave.IsGiga ? 2.8f : 1.3f, wave.IsGiga ? 8.4f : 5.8f);
			((MainModule)(ref main)).startSize = new MinMaxCurve(wave.IsGiga ? 0.2f : 0.1f, wave.IsGiga ? 0.78f : 0.42f);
			((MainModule)(ref main)).startColor = new MinMaxGradient(new Color(0.84f, 0.95f, 1f, EffectiveFoamAlpha() * 0.78f));
			EmissionModule emission = sprayParticles.emission;
			((EmissionModule)(ref emission)).rateOverTime = new MinMaxCurve(num6);
			ShapeModule shape = sprayParticles.shape;
			float num7 = Mathf.Clamp(num3 * 0.38f, wave.IsGiga ? 6f : 3f, wave.IsGiga ? 18f : 8f);
			((ShapeModule)(ref shape)).scale = new Vector3(Mathf.Clamp(halfWidth * (wave.IsGiga ? 0.76f : 0.56f), 22f, wave.IsGiga ? 340f : 170f), num7, Mathf.Clamp(wave.Length * (wave.IsGiga ? 0.12f : 0.075f), 10f, wave.IsGiga ? 56f : 30f));
			if (!sprayParticles.isPlaying)
			{
				sprayParticles.Play();
			}
		}

		public void Destroy()
		{
			if ((Object)(object)surfaceMesh != (Object)null)
			{
				Object.Destroy((Object)(object)surfaceMesh);
			}
			if ((Object)(object)root != (Object)null)
			{
				Object.Destroy((Object)(object)root);
			}
		}
	}

	private sealed class RogueWave
	{
		public readonly long Id;

		public readonly double StartTime;

		public readonly Vector3 Origin;

		public readonly Vector3 Direction;

		public readonly float Height;

		public readonly float Duration;

		public readonly float Length;

		public readonly float Width;

		public readonly float Speed;

		public readonly bool IsGiga;

		public readonly float CullRadius;

		public readonly float SwellMult;

		public readonly float TroughMult;

		public readonly float ChopMult;

		public float DepthScale;

		public bool IsLocal;

		public float NextRebroadcastAt;

		public float SurgeSpike = 2.35f;

		public float SurgeRadius = 1.35f;

		private readonly Vector3 right;

		private readonly float sigma;

		private readonly float extent;

		private readonly float profileNorm;

		private readonly float cullRadiusSqr;

		public Vector3 Right => right;

		public float VisualHalfLength => Mathf.Clamp(Length * (IsGiga ? 0.42f : 0.28f), IsGiga ? 80f : 32f, IsGiga ? 190f : 78f);

		public float VisualHalfWidth => Mathf.Clamp(Width * (IsGiga ? 0.34f : 0.22f), IsGiga ? 190f : 75f, IsGiga ? 420f : 210f);

		public RogueWave(long id, double startTime, Vector3 origin, Vector3 direction, float height, float duration, float length, float width, float speed, bool isGiga, float swellMult, float troughMult, float chopMult)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003f: 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_004a: 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_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)
			Id = id;
			StartTime = startTime;
			Origin = origin;
			Direction = ((Vector3)(ref direction)).normalized;
			Vector3 val = Vector3.Cross(Vector3.up, Direction);
			right = ((Vector3)(ref val)).normalized;
			Height = height;
			Duration = duration;
			Length = Mathf.Max(20f, length);
			Width = Mathf.Max(40f, width);
			Speed = speed;
			IsGiga = isGiga;
			SwellMult = Mathf.Clamp(swellMult, 0.5f, 2f);
			TroughMult = Mathf.Clamp(troughMult, 0f, 2f);
			ChopMult = Mathf.Clamp(chopMult, 0f, 2f);
			DepthScale = 1f;
			sigma = Length * 0.25f;
			extent = (3.5f + 9.5f * SwellMult) * sigma;
			float num = 0.0001f;
			for (int i = 0; i <= 240; i++)
			{
				float x = (-1f + (float)i * (1f / 120f)) * extent;
				float num2 = Profile(x);
				if (num2 > num)
				{
					num = num2;
				}
			}
			profileNorm = 1f / num;
			CullRadius = Speed * Duration * 0.5f + extent + 3f * Width;
			cullRadiusSqr = CullRadius * CullRadius;
		}

		public float GetVisualFade(double time)
		{
			float num = (float)(time - StartTime);
			float num2 = (IsGiga ? 10f : 6f);
			return Mathf.Clamp01(num / num2) * Mathf.Clamp01((Duration - num) / num2);
		}

		private float Profile(float x)
		{
			float num = sigma;
			float swellMult = SwellMult;
			float num2 = (IsGiga ? 0.95f : 0.48f);
			float num3 = (IsGiga ? 0.42f : 0.18f);
			float num4 = (IsGiga ? (0.22f * num) : (0.4f * num));
			float num5 = (IsGiga ? (0.16f * num) : (0.26f * num));
			float num6 = (IsGiga ? (0.92f * num) : (1.05f * num));
			float num7 = (IsGiga ? 0.16f : 0.22f) * TroughMult;
			float num8 = (IsGiga ? 0.26f : 0.14f) * TroughMult;
			float num9 = (IsGiga ? 0.35f : 0.44f) * Gauss(x - 2.25f * num * swellMult, 3.1f * num * swellMult);
			float num10 = (0f - num7) * Gauss(x - 0.92f * num, 0.55f * num);
			float num11 = num2 * Gauss(x - 0.3f * num, num4);
			float num12 = num3 * Gauss(x - 0.08f * num, num5);
			float num13 = (IsGiga ? 1.08f : 1.18f) * Gauss(x, num6);
			float num14 = (IsGiga ? 0.45f : 0.56f) * Gauss(x + 1.55f * num * swellMult, 2.55f * num * swellMult);
			float num15 = (0f - num8) * Gauss(x + 1.18f * num, IsGiga ? (0.9f * num) : (1.05f * num));
			float num16 = 0f;
			if (ChopMult > 0.01f)
			{
				float num17 = (IsGiga ? 0.05f : 0.07f) * ChopMult;
				num16 = num17 * Mathf.Sin(x / (0.42f * num) * (float)Math.PI) * Gauss(x + 2.5f * num, 1.5f * num);
			}
			return num9 + num10 + num11 + num12 + num13 + num14 + num15 + num16;
		}

		private static float Gauss(float x, float sigma)
		{
			float num = x / sigma;
			return Mathf.Exp(-0.5f * num * num);
		}

		public bool IsExpired(double time)
		{
			double num = time - StartTime;
			if (!(num < -240.0))
			{
				return num > (double)Duration + 6.0;
			}
			return true;
		}

		public Vector3 GetCrestCenter(double time)
		{
			//IL_0039: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp((float)(time - StartTime), 0f, Duration);
			float num2 = (0f - Speed) * Duration * 0.5f + Speed * num;
			return Origin + Direction * num2;
		}

		public float GetHeight(Vector3 worldPos, double time)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)(time - StartTime);
			if (num < 0f || num > Duration)
			{
				return 0f;
			}
			Vector3 val = worldPos - Origin;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude > cullRadiusSqr)
			{
				return 0f;
			}
			float num2 = Vector3.Dot(val, Direction);
			float x = Vector3.Dot(val, right);
			float num3 = (0f - Speed) * Duration * 0.5f + Speed * num;
			float num4 = num2 - num3;
			if (Mathf.Abs(num4) > extent)
			{
				return 0f;
			}
			float num5 = Mathf.Clamp01((DepthScale - 1f) / Mathf.Max(0.05f, cfgShoreBreakHeightBoost.Value - 1f));
			float x2 = num4 * Mathf.Lerp(1f, 1.45f, num5);
			float num6 = Profile(x2);
			if (num5 > 0.001f)
			{
				num6 += num5 * (IsGiga ? 0.32f : 0.18f) * Gauss(num4 - 0.02f * sigma, 0.12f * sigma);
			}
			float num7 = Gauss(x, Width);
			float num8 = Mathf.Clamp01(num / (IsGiga ? 12f : 8f));
			float num9 = Mathf.Clamp01((Duration - num) / (IsGiga ? 12f : 9f));
			return Height * DepthScale * num6 * profileNorm * num7 * num8 * num9;
		}

		public float GetNativeSurgeStrength(Vector3 worldPos, double time, float radiusMultiplier)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_005f: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)(time - StartTime);
			if (num < 0f || num > Duration)
			{
				return 0f;
			}
			Vector3 val = worldPos - Origin;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude > cullRadiusSqr * Mathf.Max(1f, radiusMultiplier * radiusMultiplier))
			{
				return 0f;
			}
			float num2 = Vector3.Dot(val, Direction);
			float x = Vector3.Dot(val, right);
			float num3 = (0f - Speed) * Duration * 0.5f + Speed * num;
			float num4 = num2 - num3;
			float num5 = extent * Mathf.Lerp(1.1f, 1.9f, Mathf.Clamp01(radiusMultiplier - 1f));
			if (Mathf.Abs(num4) > num5)
			{
				return 0f;
			}
			float num6 = Mathf.Max(0f, Profile(num4 * (IsGiga ? 0.62f : 0.74f)) * profileNorm);
			float num7 = Gauss(num4, sigma * (IsGiga ? 3.1f : 2.45f));
			float num8 = Mathf.Clamp01(num / (IsGiga ? 18f : 10f)) * Mathf.Clamp01((Duration - num) / (IsGiga ? 18f : 10f));
			float num9 = Gauss(x, Mathf.Max(40f, Width * Mathf.Clamp(radiusMultiplier, 0.35f, 4f)));
			float num10 = Mathf.Clamp01(Height / (IsGiga ? 24f : 14f));
			float num11 = Mathf.Clamp01(num6 * 0.62f + num7 * 0.78f);
			return Mathf.Clamp01(num11 * num9 * num8 * Mathf.Lerp(0.45f, 1f, num10) * Mathf.Clamp(DepthScale, 0f, IsGiga ? 1.15f : 1f));
		}

		public float GetInfluence(Vector3 worldPos, double time)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (Height < 0.01f)
			{
				return 0f;
			}
			return Mathf.Clamp01(GetHeight(worldPos, time) / (Height * Mathf.Max(0.05f, DepthScale)));
		}

		public float GetCrestCloseness(Vector3 worldPos, double time)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_003c: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)(time - StartTime);
			if (num < 0f || num > Duration)
			{
				return 0f;
			}
			Vector3 val = worldPos - Origin;
			val.y = 0f;
			float num2 = Vector3.Dot(val, Direction);
			float x = Vector3.Dot(val, right);
			float num3 = (0f - Speed) * Duration * 0.5f + Speed * num;
			float x2 = num2 - num3;
			float num4 = Mathf.Clamp01(num / 12f) * Mathf.Clamp01((Duration - num) / 12f);
			float num5 = Mathf.Min(DepthScale, 1f);
			return Mathf.Clamp01(Gauss(x2, 0.9f * sigma) * Gauss(x, Width) * num4 * num5);
		}
	}

	public const string ModGuid = "eden.valheim.roguewaves";

	public const string ModName = "Guak Rogue Waves";

	public const string ModVersion = "2.9.0";

	private const string RpcName = "GuakRogueWaves_Wave_v2";

	private const int RpcVersion = 4;

	private const float FeetToMeters = 0.3048f;

	private const float DefaultSeaLevel = 30f;

	private const int MaxActiveWaves = 8;

	private const int MaxRememberedIds = 64;

	private const float MotionCacheMinDt = 0.05f;

	private static ConfigEntry<bool> cfgEnabled;

	private static ConfigEntry<bool> cfgSyncWaves;

	private static ConfigEntry<bool> cfgChatWarning;

	private static ConfigEntry<bool> cfgScreenShake;

	private static ConfigEntry<bool> cfgNativeOceanSurgeMode;

	private static ConfigEntry<bool> cfgLegacyAdditiveHeightProfile;

	private static ConfigEntry<bool> cfgNativeSurgeFoamCueEnabled;

	private static ConfigEntry<bool> cfgAllowExperimentalSurfaceInNativeMode;

	private static ConfigEntry<float> cfgNativeNormalWaveFactorSpike;

	private static ConfigEntry<float> cfgNativeSurgeRadiusMultiplier;

	private static ConfigEntry<float> cfgNormalMinHeightFeet;

	private static ConfigEntry<float> cfgNormalMaxHeightFeet;

	private static ConfigEntry<float> cfgNormalCrestLength;

	private static ConfigEntry<float> cfgNormalCrestWidth;

	private static ConfigEntry<float> cfgNormalMinSpeed;

	private static ConfigEntry<float> cfgNormalMaxSpeed;

	private static ConfigEntry<float> cfgNormalMinSpawnDist;

	private static ConfigEntry<float> cfgNormalMaxSpawnDist;

	private static ConfigEntry<float> cfgNormalDuration;

	private static ConfigEntry<float> cfgWaveHeightOverdrive;

	private static ConfigEntry<float> cfgRoutePredictionStrength;

	private static ConfigEntry<float> cfgHeadSeaChancePercent;

	private static ConfigEntry<float> cfgCrossSeaChancePercent;

	private static ConfigEntry<bool> cfgAllowFullWavesEverywhere;

	private static ConfigEntry<float> cfgShallowDepthMeters;

	private static ConfigEntry<float> cfgShoreSpectacleDistanceFeet;

	private static ConfigEntry<float> cfgShoreBreakDepthMeters;

	private static ConfigEntry<float> cfgShoreBreakHeightBoost;

	private static ConfigEntry<float> cfgCalmMinSeconds;

	private static ConfigEntry<float> cfgCalmMaxSeconds;

	private static ConfigEntry<float> cfgBadMinSeconds;

	private static ConfigEntry<float> cfgBadMaxSeconds;

	private static ConfigEntry<float> cfgStormMinSeconds;

	private static ConfigEntry<float> cfgStormMaxSeconds;

	private static ConfigEntry<float> cfgStormFrequencyMult;

	private static ConfigEntry<float> cfgNormalPostPassFadeSeconds;

	private static ConfigEntry<bool> cfgBoatStabilizer;

	private static ConfigEntry<float> cfgBoatStability;

	private static ConfigEntry<bool> cfgAllowNearVerticalPitch;

	private static ConfigEntry<float> cfgWaveRideSurgeForce;

	private static ConfigEntry<float> cfgWaveRidePitchForce;

	private static ConfigEntry<float> cfgWaveRideHeaveForce;

	private static ConfigEntry<float> cfgStormWindChaosMult;

	private static ConfigEntry<float> cfgThunderWeightMult;

	private static ConfigEntry<float> cfgOpenOceanChopMult;

	private static ConfigEntry<bool> cfgRoughOceanMode;

	private static ConfigEntry<float> cfgRoughOceanWaveFactor;

	private static ConfigEntry<float> cfgRoughOceanStormFactor;

	private static ConfigEntry<float> cfgRoughOceanMinWind;

	private static ConfigEntry<float> cfgRoughOceanStormMinWind;

	private static ConfigEntry<float> cfgRoughOceanBoatDifficulty;

	private static ConfigEntry<float> cfgRoughOceanShoreViewMultiplier;

	private static ConfigEntry<float> cfgOpenOceanWaveFrequencyMult;

	private static ConfigEntry<float> cfgShoreWaveFrequencyMult;

	private static ConfigEntry<bool> cfgVisualWavesEnabled;

	private static ConfigEntry<bool> cfgVisualParticleSprayEnabled;

	private static ConfigEntry<bool> cfgVisualCrestSurfaceEnabled;

	private static ConfigEntry<float> cfgVisualSurfaceAlpha;

	private static ConfigEntry<float> cfgVisualFoamAlpha;

	private static ConfigEntry<float> cfgVisualSprayRate;

	private static ConfigEntry<float> cfgVisualMaxDistance;

	private static ConfigEntry<float> cfgSwellLengthMult;

	private static ConfigEntry<float> cfgPreTroughDepthScale;

	private static ConfigEntry<float> cfgTrailingChopScale;

	private static ConfigEntry<float> cfgWaveRideRollForce;

	private static ConfigEntry<float> cfgWaveRideYawForce;

	private static ConfigEntry<bool> cfgShoreCrashEnabled;

	private static ConfigEntry<float> cfgShoreMaxHeightFeet;

	private static ConfigEntry<float> cfgShoreSearchRadius;

	private static ConfigEntry<float> cfgMinOffshoreDepth;

	private static ConfigEntry<bool> cfgWaveSetsEnabled;

	private static ConfigEntry<float> cfgWaveSetMinCount;

	private static ConfigEntry<float> cfgWaveSetMaxCount;

	private static ConfigEntry<float> cfgWaveSetSpacing;

	private static readonly Random rng = new Random();

	private static readonly List<RogueWave> waves = new List<RogueWave>();

	private static readonly Queue<long> recentIdQueue = new Queue<long>();

	private static readonly HashSet<long> recentIds = new HashSet<long>();

	private static readonly Dictionary<int, float> gigaDamageAccum = new Dictionary<int, float>();

	private static readonly Dictionary<int, int> boatClassCache = new Dictionary<int, int>();

	private static readonly Dictionary<long, WaveVisual> waveVisuals = new Dictionary<long, WaveVisual>();

	private static ManualLogSource log;

	private static Material visualFoamMaterial;

	private static Material visualSurfaceMaterial;

	private static FieldInfo shipBodyField;

	private static ZRoutedRpc registeredRpc;

	private static EnvMan weightPatchedEnvMan;

	private static float nextWaveTime;

	private static float nextDepthRefreshTime;

	private static float nextShakeTime;

	private static float lastMotionSampleTime = -1f;

	private static Vector3 lastMotionSamplePos;

	private static Vector3 smoothedPlayerVelocity = Vector3.zero;

	private static int lastWeatherTier = -1;

	private static bool shipPatchApplied;

	private static bool wavePatchApplied;

	private static bool windPatchApplied;

	private Harmony harmony;

	private static double frameNetTime;

	private static int frameNetFrame = -1;

	private static int roughOceanCacheFrame = -1;

	private static bool roughOceanCacheOpen;

	private static bool roughOceanCacheNearWater;

	private static int roughOceanCacheWeatherTier;

	private void Awake()
	{
		//IL_0a4e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a58: Expected O, but got Unknown
		log = ((BaseUnityPlugin)this).Logger;
		cfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable rogue ocean waves.");
		cfgChatWarning = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ChatWarning", false, "No effect. Kept so old config files load cleanly; the ocean itself is the warning.");
		cfgScreenShake = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ScreenShake", true, "Shake the camera while a rogue wave is passing under the local player.");
		cfgSyncWaves = ((BaseUnityPlugin)this).Config.Bind<bool>("Multiplayer", "SyncWaves", true, "Share waves with other modded players (both sending AND receiving). Off = fully local waves; other players will not see the water that moves your boat.");
		cfgNativeOceanSurgeMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Native Ocean Surge", "NativeOceanSurgeMode", true, "Default public mode. Rogue events briefly spike Valheim's own WaterVolume.CalcWave waveFactor instead of adding a separate custom water-height wall. This keeps the wave visually tied to real Valheim ocean water.");
		cfgLegacyAdditiveHeightProfile = ((BaseUnityPlugin)this).Config.Bind<bool>("Native Ocean Surge", "LegacyAdditiveHeightProfile", false, "Opt-in old behavior: add the custom long swell height profile on top of native water. Leave false for public releases to avoid invisible/fake-looking wave hits.");
		cfgNativeSurgeFoamCueEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Native Ocean Surge", "NativeSurgeFoamCueEnabled", true, "Show a non-physics foam/spray warning line during native surge events. This is the 'oh no, something is coming' cue without spawning a fake water wall.");
		cfgAllowExperimentalSurfaceInNativeMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Native Ocean Surge", "AllowExperimentalSurfaceInNativeMode", false, "Dangerous opt-in. If false, VisualCrestSurfaceEnabled is ignored while NativeOceanSurgeMode is active so old configs cannot resurrect the blue-sheet mesh bug.");
		cfgNativeNormalWaveFactorSpike = ((BaseUnityPlugin)this).Config.Bind<float>("Native Ocean Surge", "NormalWaveFactorSpike", 3f, "Peak multiplier applied to Valheim's native waveFactor during normal surge events. 1 = no native surge, 2-3 = big storm swells, higher gets chaotic. Clamped 1-6. The event SPAWNER'S value is synced to all modded clients, so everyone computes the same water.");
		cfgNativeSurgeRadiusMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Native Ocean Surge", "SurgeRadiusMultiplier", 1.25f, "How wide the native waveFactor spike reaches compared with the synced event width. Clamped 0.35-4. Synced from the event spawner.");
		cfgNormalMinHeightFeet = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "NormalMinHeightFeet", 12f, "Minimum peak height of a normal rogue wave, in feet (15 ft = 4.6 m). Height is the TRUE peak after profile normalization.");
		cfgNormalMaxHeightFeet = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "NormalMaxHeightFeet", 34f, "Maximum peak height of a normal rogue wave, in feet (45 ft = 13.7 m).");
		cfgNormalCrestLength = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "CrestLengthMeters", 170f, "Approximate full front-to-back size of the main crest. Each wave randomizes 75%-135% of this.");
		cfgNormalCrestWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "CrestWidthMeters", 620f, "Base side-to-side spread. Each wave randomizes 75%-135% of this.");
		cfgNormalMinSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "MinTravelSpeedMetersPerSecond", 8f, "Minimum travel speed of a normal wave.");
		cfgNormalMaxSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "MaxTravelSpeedMetersPerSecond", 14f, "Maximum travel speed of a normal wave.");
		cfgNormalMinSpawnDist = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "MinSpawnDistanceMeters", 95f, "Minimum distance from the player at which the crest starts.");
		cfgNormalMaxSpawnDist = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "MaxSpawnDistanceMeters", 180f, "Maximum distance from the player at which the crest starts.");
		cfgNormalDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "DurationSeconds", 58f, "How long a normal wave lives while it travels through.");
		cfgWaveHeightOverdrive = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "WaveHeightOverdrive", 1f, "Extra multiplier applied ON TOP of the configured wave heights. 1 = configured heights are literal (recommended for public play). Clamped 0.25-3.");
		cfgRoutePredictionStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "RoutePredictionStrength", 0.75f, "0..1. How strongly newly spawned waves predict the moving player's route. Higher values make waves meet boats instead of passing behind them.");
		cfgHeadSeaChancePercent = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "HeadSeaChancePercent", 35f, "Chance that a normal wave travels against your current route, forcing you to climb into it.");
		cfgCrossSeaChancePercent = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "CrossSeaChancePercent", 25f, "Chance that a normal wave crosses your current route from the side.");
		cfgAllowFullWavesEverywhere = ((BaseUnityPlugin)this).Config.Bind<bool>("Normal Waves", "AllowFullWavesEverywhere", false, "If false, waves still stop far inland, but shallow coastal water uses the shore-break boost instead of shrinking to tiny waves.");
		cfgShallowDepthMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "ShallowWaterDepthMeters", 14f, "Water depth at which waves reach full size when AllowFullWavesEverywhere is false.");
		cfgShoreSpectacleDistanceFeet = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "ShoreSpectacleDistanceFeet", 260f, "Normal waves are allowed while the local player is on/near ocean or large water within this distance. Far inland, waves stop.");
		cfgShoreBreakDepthMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "ShoreBreakDepthMeters", 8f, "Depth range where coastal waves jack up into a shore-break style wall.");
		cfgShoreBreakHeightBoost = ((BaseUnityPlugin)this).Config.Bind<float>("Normal Waves", "ShoreBreakHeightBoost", 1.75f, "Extra height multiplier in shallow coastal water so waves visibly crash near shore. 1 = off.");
		cfgCalmMinSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "NormalWeatherMinSecondsBetweenWaves", 120f, "Calm/clear weather: minimum seconds between local wave events.");
		cfgCalmMaxSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "NormalWeatherMaxSecondsBetweenWaves", 300f, "Calm/clear weather: maximum seconds between local wave events.");
		cfgBadMinSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "BadWeatherMinSecondsBetweenWaves", 65f, "Rainy/windy weather: minimum seconds between local wave events.");
		cfgBadMaxSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "BadWeatherMaxSecondsBetweenWaves", 150f, "Rainy/windy weather: maximum seconds between local wave events.");
		cfgStormMinSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "ThunderstormMinSecondsBetweenWaves", 18f, "Thunderstorm: minimum seconds between local wave events.");
		cfgStormMaxSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "ThunderstormMaxSecondsBetweenWaves", 55f, "Thunderstorm: maximum seconds between local wave events.");
		cfgStormFrequencyMult = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "StormNormalWaveFrequencyMultiplier", 1.65f, "Extra frequency multiplier applied on top of the thunderstorm timing range. 2 = twice as often. Leave 1 to use the range as-is.");
		cfgNormalPostPassFadeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "NormalPostPassFadeSeconds", 12f, "How long normal waves keep meaningful force/visual life after the crest reaches the target. Lower values make the hit pass instead of carrying boats far away.");
		cfgBoatStabilizer = ((BaseUnityPlugin)this).Config.Bind<bool>("Boat Physics", "NormalWaveBoatStabilizer", true, "Dampen violent roll/spin during NORMAL waves so they are scary but controllable.");
		cfgBoatStability = ((BaseUnityPlugin)this).Config.Bind<float>("Boat Physics", "NormalWaveBoatStability", 0.68f, "0..1. How strongly normal waves are kept from capsizing boats. Roll and spin are damped; pitch is left mostly free.");
		cfgAllowNearVerticalPitch = ((BaseUnityPlugin)this).Config.Bind<bool>("Boat Physics", "AllowNearVerticalPitch", true, "If true, pitch is barely damped so the bow can point at the sky while climbing. If false, pitch is also moderated.");
		cfgWaveRideSurgeForce = ((BaseUnityPlugin)this).Config.Bind<float>("Boat Physics", "WaveRideSurgeForce", 2.1f, "Extra forward acceleration while crossing a rogue wave face, so the boat rides/slides with the swell instead of only being lifted.");
		cfgWaveRidePitchForce = ((BaseUnityPlugin)this).Config.Bind<float>("Boat Physics", "WaveRidePitchForce", 3.1f, "Extra bow/stern force from sampled wave slope. Higher values make the ship pitch with the wave more dramatically.");
		cfgWaveRideHeaveForce = ((BaseUnityPlugin)this).Config.Bind<float>("Boat Physics", "WaveRideHeaveForce", 0.85f, "Extra vertical rise/drop force from the wave moving under the boat. Higher values make bigger dips and climbs without adding roll flips.");
		cfgStormWindChaosMult = ((BaseUnityPlugin)this).Config.Bind<float>("Storm", "StormWindChaosMultiplier", 2.45f, "Multiplies wind intensity targets during thunderstorms (affects sails, ocean physics AND the rendered waves consistently). 1 = off. Modded clients see stormier seas than unmodded ones.");
		cfgThunderWeightMult = ((BaseUnityPlugin)this).Config.Bind<float>("Storm", "ThunderstormWeightMultiplier", 2.75f, "Multiplies the weather-table weight of thunderstorm environments in the Ocean biome, making them a bit more common. 1 = off. NOTE: weather is computed per-client from a shared seed, so give every player the same value or their skies will disagree (cosmetic only, no server validation).");
		cfgOpenOceanChopMult = ((BaseUnityPlugin)this).Config.Bind<float>("Storm", "OpenOceanChopMultiplier", 2.75f, "Multiplies Valheim's native wind/wave intensity while the player is near major water, making distant ocean naturally choppier. 1 = off. Clamped 1-2.75.");
		cfgRoughOceanMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Rough Ocean", "RoughOceanMode", true, "Main mode: major water is persistently rough and unpleasant even without a giant rogue wave event.");
		cfgRoughOceanWaveFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Rough Ocean", "RoughOceanWaveFactorMultiplier", 4.55f, "Persistent multiplier for Valheim's native waveFactor near major water. 1 = vanilla; 2-4 = choppy hostile travel; 4+ = public suffering; clamped 1-6.");
		cfgRoughOceanStormFactor = ((BaseUnityPlugin)this).Config.Bind<float>("Rough Ocean", "RoughOceanStormExtraMultiplier", 1.85f, "Extra multiplier applied to RoughOceanWaveFactorMultiplier during thunderstorms. Clamped 1-2.");
		cfgRoughOceanMinWind = ((BaseUnityPlugin)this).Config.Bind<float>("Rough Ocean", "RoughOceanMinWindIntensity", 0.94f, "Minimum wind intensity target while the local player is near major water. Higher values make the sea consistently rough. Clamped 0-1.");
		cfgRoughOceanStormMinWind = ((BaseUnityPlugin)this).Config.Bind<float>("Rough Ocean", "RoughOceanStormMinWindIntensity", 1f, "Minimum wind intensity target while the local player is near major water during thunderstorms. Clamped 0-1.");
		cfgRoughOceanBoatDifficulty = ((BaseUnityPlugin)this).Config.Bind<float>("Rough Ocean", "RoughOceanBoatDifficulty", 1.85f, "Persistent open-ocean boat challenge: speed loss, cross-current shove, yaw/broach pressure and pitch chop. 0 = off; clamped 0-3.");
		cfgRoughOceanShoreViewMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Rough Ocean", "RoughOceanShoreViewMultiplier", 1f, "How much persistent rough-ocean visual chop applies while watching from shore/near large water. 0 = only open ocean; 1 = almost full open-ocean spectacle. Only affects real water samples, not dry land/buildings. Clamped 0-1.");
		cfgOpenOceanWaveFrequencyMult = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "OpenOceanWaveFrequencyMultiplier", 1.5f, "Makes rogue wave events more frequent in open ocean only. 2 = about twice as often. Clamped 1-4.");
		cfgShoreWaveFrequencyMult = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "ShoreWaveFrequencyMultiplier", 1.5f, "Makes wave events more frequent while near shore/large water but not fully open ocean, so shore bases still get spectacle. Clamped 1-4.");
		cfgVisualWavesEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "VisualWavesEnabled", false, "Legacy master switch for optional client-side crest helpers. NativeSurgeFoamCueEnabled can still show safe foam/spray while this is false.");
		cfgVisualParticleSprayEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "VisualParticleSprayEnabled", true, "Draw lightweight spray/foam particles at rogue wave crests.");
		cfgVisualCrestSurfaceEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "VisualCrestSurfaceEnabled", false, "Experimental: draw a thin translucent crest surface that follows the synced wave height. Default off because some shader/material fallbacks look like a blue wall.");
		cfgVisualSurfaceAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "VisualSurfaceAlpha", 0f, "Transparency of the crest surface helper. Lower values blend more; 0 hides the surface.");
		cfgVisualFoamAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "VisualFoamAlpha", 0.34f, "Transparency of the spray particles.");
		cfgVisualSprayRate = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "VisualSprayRate", 2.1f, "Multiplier for rogue-wave spray particle amount. 0 disables particle emission.");
		cfgVisualMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Visuals", "VisualMaxDistanceMeters", 1400f, "Do not simulate crest spray farther than this from the local player.");
		cfgSwellLengthMult = ((BaseUnityPlugin)this).Config.Bind<float>("Wave Shape", "SwellLengthMultiplier", 1.25f, "Stretches the broad approach swell and long backside drop (0.5-2). Bigger = longer, more oceanic build-up and roll-down. Travels with each wave over the network, so the spawner's shape wins everywhere.");
		cfgPreTroughDepthScale = ((BaseUnityPlugin)this).Config.Bind<float>("Wave Shape", "PreTroughDepthScale", 1.35f, "Scales the deep pre-trough (the sea pulling back before the face) and the after-trough (0-2). Higher = the water visibly recedes before the wall arrives. Never a sharp pit - the trough stays wide.");
		cfgTrailingChopScale = ((BaseUnityPlugin)this).Config.Bind<float>("Wave Shape", "TrailingChopScale", 1f, "Scales the decaying chop ripples trailing behind the crest (0-2). 0 = mirror-smooth backside.");
		cfgWaveRideRollForce = ((BaseUnityPlugin)this).Config.Bind<float>("Boat Physics", "WaveRideRollForce", 0.5f, "0-2. Low heel from the wave's side slope on normal waves. The anti-flip roll damping always outguns this.");
		cfgWaveRideYawForce = ((BaseUnityPlugin)this).Config.Bind<float>("Boat Physics", "WaveRideYawForce", 1.95f, "0-3. Off-course shove: waves push the hull sideways and try to broach the bow toward crest-parallel. Counter-steer to hold course. Rafts get shoved hardest, longships least.");
		cfgShoreCrashEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Shore Waves", "ShoreCrashEnabled", true, "When the local player is on/near land, spawn waves out in deep water traveling TOWARD the shore so they visibly roll in and break in the shallows. Never damages buildings.");
		cfgShoreMaxHeightFeet = ((BaseUnityPlugin)this).Config.Bind<float>("Shore Waves", "ShoreMaxHeightFeet", 34f, "Height cap in feet for shore-mode waves (the shore-break boost still steepens them in the shallows).");
		cfgShoreSearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Shore Waves", "ShoreSearchRadiusMeters", 300f, "How far offshore to look for deep water to launch shore waves from. If none is found (fully inland), no wave spawns.");
		cfgMinOffshoreDepth = ((BaseUnityPlugin)this).Config.Bind<float>("Shore Waves", "MinOffshoreDepthMeters", 5f, "Minimum water depth required at the offshore launch point.");
		cfgWaveSetsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Wave Sets", "WaveSetsEnabled", true, "During thunderstorms waves arrive as related sets: lead-up swells, the main wave, then an aftermath swell. Synced through the normal wave RPC.");
		cfgWaveSetMinCount = ((BaseUnityPlugin)this).Config.Bind<float>("Wave Sets", "StormWaveSetMinCount", 3f, "Minimum waves per storm set (1-4).");
		cfgWaveSetMaxCount = ((BaseUnityPlugin)this).Config.Bind<float>("Wave Sets", "StormWaveSetMaxCount", 4f, "Maximum waves per storm set (1-4).");
		cfgWaveSetSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("Wave Sets", "WaveSetSpacingSeconds", 11f, "Seconds between set members' arrivals (jittered +/-25% per member).");
		shipBodyField = AccessTools.Field(typeof(Ship), "m_body");
		harmony = new Harmony("eden.valheim.roguewaves");
		ApplyPatches();
		ScheduleNextWave(8f, 20f);
		log.LogInfo((object)("Guak Rogue Waves 2.9.0 loaded. wavePatch=" + wavePatchApplied + " shipPatch=" + shipPatchApplied + " windPatch=" + windPatchApplied));
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		ClearVisuals();
	}

	private void ApplyPatches()
	{
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Expected O, but got Unknown
		//IL_00a9: Expected O, but got Unknown
		//IL_0202: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Expected O, but got Unknown
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Expected O, but got Unknown
		try
		{
			MethodInfo method = typeof(WaterVolume).GetMethod("CalcWave", BindingFlags.Instance | BindingFlags.Public, null, new Type[4]
			{
				typeof(Vector3),
				typeof(float),
				typeof(float),
				typeof(float)
			}, null);
			if (method != null)
			{
				harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(RogueWavesPlugin).GetMethod("CalcWavePrefix", BindingFlags.Static | BindingFlags.NonPublic)), new HarmonyMethod(typeof(RogueWavesPlugin).GetMethod("CalcWavePostfix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				wavePatchApplied = true;
			}
			else
			{
				log.LogWarning((object)"WaterVolume.CalcWave(Vector3,float,float,float) not found; rogue waves disabled.");
			}
		}
		catch (Exception ex)
		{
			log.LogWarning((object)("Failed to patch WaterVolume.CalcWave: " + ex.Message));
		}
		try
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Ship), "CustomFixedUpdate", new Type[1] { typeof(float) }, (Type[])null);
			if (methodInfo == null)
			{
				methodInfo = AccessTools.Method(typeof(Ship), "FixedUpdate", Type.EmptyTypes, (Type[])null);
			}
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(RogueWavesPlugin).GetMethod("ShipTickPostfix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				shipPatchApplied = true;
			}
			else
			{
				log.LogWarning((object)"No Ship.CustomFixedUpdate/FixedUpdate found; boat stabilization and giga damage disabled.");
			}
		}
		catch (Exception ex2)
		{
			log.LogWarning((object)("Failed to patch Ship physics tick: " + ex2.Message));
		}
		try
		{
			MethodInfo methodInfo2 = AccessTools.Method(typeof(EnvMan), "SetTargetWind", new Type[2]
			{
				typeof(Vector3),
				typeof(float)
			}, (Type[])null);
			if (methodInfo2 != null)
			{
				harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(RogueWavesPlugin).GetMethod("SetTargetWindPrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				windPatchApplied = true;
			}
			else
			{
				log.LogInfo((object)"EnvMan.SetTargetWind not found; StormWindChaosMultiplier disabled (safe).");
			}
		}
		catch (Exception ex3)
		{
			log.LogWarning((object)("Failed to patch EnvMan.SetTargetWind: " + ex3.Message));
		}
	}

	private static void CalcWavePrefix(Vector3 worldPos, float depth, ref float waveFactor)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (cfgEnabled.Value && cfgNativeOceanSurgeMode.Value && !cfgLegacyAdditiveHeightProfile.Value && !(depth <= 0.05f))
			{
				float num = GetPersistentRoughOceanWaveFactorMultiplier(worldPos, depth) * GetNativeWaveFactorMultiplier(worldPos);
				if (num > 1.001f)
				{
					waveFactor = Mathf.Clamp(waveFactor * num, 0f, 14f);
				}
			}
		}
		catch (Exception)
		{
		}
	}

	private static void CalcWavePostfix(Vector3 worldPos, float depth, ref float __result)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((!cfgNativeOceanSurgeMode.Value || cfgLegacyAdditiveHeightProfile.Value) && !(depth <= 0.05f))
			{
				__result += ExtraWaveHeight(worldPos);
			}
		}
		catch (Exception)
		{
		}
	}

	private static void ShipTickPostfix(Ship __instance)
	{
		try
		{
			HandleShipPhysics(__instance);
		}
		catch (Exception)
		{
		}
	}

	private static void SetTargetWindPrefix(ref float intensity)
	{
		try
		{
			if (cfgEnabled.Value)
			{
				float value = cfgStormWindChaosMult.Value;
				if (value > 1.001f && GetWeatherTier() == 2)
				{
					intensity = Mathf.Clamp01(intensity * Mathf.Min(value, 3f));
				}
				float value2 = cfgOpenOceanChopMult.Value;
				bool flag = IsLocalPlayerNearWaterCached();
				bool flag2 = IsLocalPlayerOpenOceanCached();
				if (value2 > 1.001f && flag)
				{
					float num = (flag2 ? 1f : (Mathf.Clamp01(cfgRoughOceanShoreViewMultiplier.Value) * 0.8f));
					float num2 = intensity * Mathf.Lerp(1f, Mathf.Clamp(value2, 1f, 2.75f), num);
					float num3 = (flag2 ? 0.84f : 0.74f);
					intensity = Mathf.Clamp01(Mathf.Max(num2, Mathf.Lerp(intensity, num3, 0.45f * num)));
				}
				if (cfgRoughOceanMode.Value && flag)
				{
					float num4 = ((GetWeatherTierCachedForRoughOcean() == 2) ? Mathf.Clamp01(cfgRoughOceanStormMinWind.Value) : Mathf.Clamp01(cfgRoughOceanMinWind.Value));
					float num5 = (flag2 ? 1f : Mathf.Clamp01(cfgRoughOceanShoreViewMultiplier.Value));
					intensity = Mathf.Clamp01(Mathf.Max(intensity, Mathf.Lerp(intensity, num4, num5)));
				}
			}
		}
		catch (Exception)
		{
		}
	}

	private void Update()
	{
		//IL_00a6: 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_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		TryRegisterRpc();
		TryBoostThunderWeights();
		if (!cfgEnabled.Value)
		{
			if (waves.Count > 0)
			{
				ClearAllWaves();
			}
			if (Time.time > nextWaveTime)
			{
				ScheduleNextWave(30f, 90f);
			}
			return;
		}
		if ((Object)(object)ZNet.instance == (Object)null && waves.Count > 0)
		{
			ClearAllWaves();
			lastWeatherTier = -1;
		}
		double networkTime = GetNetworkTime();
		PruneExpiredWaves(networkTime);
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			if (Time.time > nextWaveTime)
			{
				ScheduleNextWave(8f, 18f);
			}
			return;
		}
		if (!IsNearOceanOrLargeWater(((Component)localPlayer).transform.position, Mathf.Max(20f, cfgShoreSpectacleDistanceFeet.Value) * 0.3048f))
		{
			if (waves.Count > 0)
			{
				ClearAllWaves();
			}
			if (Time.time > nextWaveTime)
			{
				ScheduleNextWave(30f, 90f);
			}
			return;
		}
		RebroadcastLocalWaves();
		UpdatePlayerMotion(localPlayer);
		int weatherTier = GetWeatherTier();
		if (weatherTier != lastWeatherTier)
		{
			lastWeatherTier = weatherTier;
			ScheduleNextWaveForTier(weatherTier);
		}
		RefreshWaveDepthScales(localPlayer);
		Vector3 position = ((Component)localPlayer).transform.position;
		if (!AnyWaveNear(position, networkTime) && Time.time >= nextWaveTime)
		{
			StartNormalWave(localPlayer, weatherTier);
			ScheduleNextWaveForTier(weatherTier);
		}
		UpdateScreenShake(localPlayer, networkTime);
		UpdateWaveVisuals(localPlayer, networkTime);
	}

	private static int GetWeatherTier()
	{
		try
		{
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return 0;
			}
			EnvSetup currentEnvironment = instance.GetCurrentEnvironment();
			if (currentEnvironment == null || string.IsNullOrEmpty(currentEnvironment.m_name))
			{
				return 0;
			}
			string text = currentEnvironment.m_name.ToLowerInvariant();
			if (text.Contains("thunder"))
			{
				return 2;
			}
			if (currentEnvironment.m_isWet || currentEnvironment.m_windMax >= 0.75f)
			{
				return 1;
			}
			return 0;
		}
		catch (Exception)
		{
			return 0;
		}
	}

	private static void ScheduleNextWaveForTier(int tier)
	{
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		float num;
		float num2;
		switch (tier)
		{
		case 2:
		{
			float num3 = Mathf.Max(0.25f, cfgStormFrequencyMult.Value);
			num = cfgStormMinSeconds.Value / num3;
			num2 = cfgStormMaxSeconds.Value / num3;
			break;
		}
		case 1:
			num = cfgBadMinSeconds.Value;
			num2 = cfgBadMaxSeconds.Value;
			break;
		default:
			num = cfgCalmMinSeconds.Value;
			num2 = cfgCalmMaxSeconds.Value;
			break;
		}
		if (IsLocalPlayerOpenOcean())
		{
			float num4 = Mathf.Clamp(cfgOpenOceanWaveFrequencyMult.Value, 1f, 4f);
			num /= num4;
			num2 /= num4;
		}
		else
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && IsNearOceanOrLargeWater(((Component)localPlayer).transform.position, Mathf.Max(20f, cfgShoreSpectacleDistanceFeet.Value) * 0.3048f))
			{
				float num5 = Mathf.Clamp(cfgShoreWaveFrequencyMult.Value, 1f, 4f);
				num /= num5;
				num2 /= num5;
			}
		}
		ScheduleNextWave(num, num2);
	}

	private static void ScheduleNextWave(float minSeconds, float maxSeconds)
	{
		float num = Mathf.Max(7f, Mathf.Min(minSeconds, maxSeconds));
		float num2 = Mathf.Max(num + 1f, Mathf.Max(minSeconds, maxSeconds));
		nextWaveTime = Time.time + Mathf.Lerp(num, num2, Next01());
	}

	private static void TryBoostThunderWeights()
	{
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Invalid comparison between Unknown and I4
		try
		{
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance == (Object)(object)weightPatchedEnvMan)
			{
				return;
			}
			weightPatchedEnvMan = instance;
			float num = Mathf.Clamp(cfgThunderWeightMult.Value, 1f, 5f);
			if (num <= 1.001f || instance.m_biomes == null)
			{
				return;
			}
			int num2 = 0;
			for (int i = 0; i < instance.m_biomes.Count; i++)
			{
				BiomeEnvSetup val = instance.m_biomes[i];
				if (val == null || (int)val.m_biome != 256 || val.m_environments == null)
				{
					continue;
				}
				for (int j = 0; j < val.m_environments.Count; j++)
				{
					EnvEntry val2 = val.m_environments[j];
					if (val2 != null && !string.IsNullOrEmpty(val2.m_environment) && val2.m_environment.ToLowerInvariant().Contains("thunder"))
					{
						val2.m_weight *= num;
						num2++;
					}
				}
			}
			if (num2 > 0 && log != null)
			{
				log.LogInfo((object)("Boosted " + num2 + " ocean thunderstorm weather weight(s) x" + num));
			}
		}
		catch (Exception)
		{
		}
	}

	private static void StartNormalWave(Player player, int tier)
	{
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_024e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: 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_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: 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_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_019a: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: 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_0234: Unknown result type (might be due to invalid IL or missing references)
		//IL_0236: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Lerp(Mathf.Min(cfgNormalMinHeightFeet.Value, cfgNormalMaxHeightFeet.Value), Mathf.Max(cfgNormalMinHeightFeet.Value, cfgNormalMaxHeightFeet.Value), Next01());
		if (tier == 2)
		{
			float num2 = Mathf.Max(cfgNormalMinHeightFeet.Value, cfgNormalMaxHeightFeet.Value);
			num = Mathf.Lerp(num, num2, 0.35f);
		}
		float num3 = Mathf.Clamp(num * 0.3048f * GetHeightOverdrive(), 0.5f, 45f);
		float configuredDuration = Mathf.Max(20f, cfgNormalDuration.Value);
		float length = RandomAround(cfgNormalCrestLength.Value, 40f);
		float width = RandomAround(cfgNormalCrestWidth.Value, 80f);
		float num4 = RandomRange(cfgNormalMinSpeed.Value, cfgNormalMaxSpeed.Value, 2f);
		float spawnDistance = Mathf.Clamp(RandomRange(cfgNormalMinSpawnDist.Value, cfgNormalMaxSpawnDist.Value, 40f), 40f, 1000f);
		configuredDuration = LimitDurationAfterTargetPass(configuredDuration, spawnDistance, num4, isGiga: false);
		if (IsPlayerShoreBound(player))
		{
			if (cfgShoreCrashEnabled.Value && FindOffshoreDeepPoint(((Component)player).transform.position, out var deepPoint))
			{
				Vector3 travelDir = ((Component)player).transform.position - deepPoint;
				travelDir.y = 0f;
				if (!(((Vector3)(ref travelDir)).sqrMagnitude < 1f))
				{
					((Vector3)(ref travelDir)).Normalize();
					Vector3 val = AdjustTargetToNearbyWater(((Component)player).transform.position, ((Component)player).transform.position);
					val.y = 0f;
					Vector3 val2 = deepPoint;
					val2.y = 0f;
					float num5 = Mathf.Max(60f, Vector3.Distance(val, val2));
					float num6 = Mathf.Min(num4, 11f);
					configuredDuration = Mathf.Max(configuredDuration, num5 / Mathf.Max(4f, num6) + 18f);
					configuredDuration = LimitDurationAfterTargetPass(configuredDuration, num5, num6, isGiga: false);
					num3 = Mathf.Min(num3, Mathf.Max(1f, cfgShoreMaxHeightFeet.Value) * 0.3048f);
					SpawnWaveMember(isGiga: false, num3, configuredDuration, length, width, num6, num5, travelDir, val, 0.0);
				}
			}
		}
		else
		{
			Vector3 travelDir2 = PickWaveTravelDirection(player, isGiga: false);
			Vector3 target = PredictWaveTarget(player, travelDir2, num4, spawnDistance, isGiga: false);
			int count = 1;
			if (cfgWaveSetsEnabled.Value && tier == 2)
			{
				count = Mathf.Clamp(Mathf.RoundToInt(RandomRange(cfgWaveSetMinCount.Value, cfgWaveSetMaxCount.Value, 1f)), 1, 4);
			}
			LaunchWaveSet(isGiga: false, count, num3, configuredDuration, length, width, num4, spawnDistance, travelDir2, target);
		}
	}

	private static void LaunchWaveSet(bool isGiga, int count, float mainHeight, float duration, float length, float width, float speed, float spawnDistance, Vector3 travelDir, Vector3 target)
	{
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: 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_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01db: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Clamp(cfgWaveSetSpacing.Value, 6f, 60f);
		if (isGiga)
		{
			if (cfgWaveSetsEnabled.Value)
			{
				float heightMeters = Mathf.Min(mainHeight * 0.42f, 12f);
				SpawnWaveMember(isGiga: false, heightMeters, duration, length * 1.35f, width, speed * 0.95f, spawnDistance, RotateFlat(travelDir, RandomSigned(6f)), target, 0.0);
				SpawnWaveMember(isGiga: true, mainHeight, duration, length, width, speed, spawnDistance, travelDir, target, num * (1.1f + Next01() * 0.4f));
				SpawnWaveMember(isGiga: false, Mathf.Min(mainHeight * 0.3f, 9f), duration, length * 1.5f, width, speed * 0.9f, spawnDistance, RotateFlat(travelDir, RandomSigned(8f)), target, num * (2.3f + Next01() * 0.5f));
			}
			else
			{
				SpawnWaveMember(isGiga: true, mainHeight, duration, length, width, speed, spawnDistance, travelDir, target, 0.0);
			}
			return;
		}
		if (count <= 1)
		{
			SpawnWaveMember(isGiga: false, mainHeight, duration, length, width, speed, spawnDistance, travelDir, target, 0.0);
			return;
		}
		int num2 = ((count >= 3) ? (count - 2) : (count - 1));
		double num3 = 0.0;
		for (int i = 0; i < count; i++)
		{
			bool flag = i == num2;
			bool flag2 = i > num2;
			float num4 = (flag ? 1f : (flag2 ? 0.45f : (0.55f + 0.12f * (float)i)));
			float num5 = (flag ? 1f : (flag2 ? 1.45f : 1.25f));
			float speed2 = (flag ? speed : (speed * (0.9f + Next01() * 0.2f)));
			Vector3 travelDir2 = (flag ? travelDir : RotateFlat(travelDir, RandomSigned(9f)));
			SpawnWaveMember(isGiga: false, mainHeight * num4, duration, length * num5, width, speed2, spawnDistance, travelDir2, target, num3);
			num3 += (double)(num * (0.85f + Next01() * 0.3f));
		}
	}

	private static bool IsPlayerShoreBound(Player player)
	{
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)Ship.GetLocalShip() != (Object)null)
			{
				return false;
			}
			WorldGenerator instance = WorldGenerator.instance;
			if (instance == null)
			{
				return false;
			}
			float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f);
			Vector3 position = ((Component)player).transform.position;
			return num - instance.GetHeight(position.x, position.z) < 3f;
		}
		catch (Exception)
		{
			return false;
		}
	}

	private static bool FindOffshoreDeepPoint(Vector3 center, out Vector3 deepPoint)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: 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)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//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_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Invalid comparison between Unknown and I4
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		deepPoint = center;
		try
		{
			WorldGenerator instance = WorldGenerator.instance;
			if (instance == null)
			{
				return false;
			}
			float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f);
			float num2 = Mathf.Clamp(cfgShoreSearchRadius.Value, 120f, 1200f);
			float num3 = Mathf.Max(2f, cfgMinOffshoreDepth.Value);
			float num4 = -1f;
			for (int i = 1; i <= 3; i++)
			{
				float num5 = num2 * (float)i / 3f;
				for (int j = 0; j < 16; j++)
				{
					float num6 = (float)j * (float)Math.PI * 2f / 16f;
					Vector3 val = center + new Vector3(Mathf.Sin(num6) * num5, 0f, Mathf.Cos(num6) * num5);
					float num7 = num - instance.GetHeight(val.x, val.z);
					if (!(num7 < num3))
					{
						bool flag = (int)instance.GetBiome(val) == 256;
						float num8 = num7 + (flag ? 10f : 0f) - num5 * 0.02f;
						if (num8 > num4)
						{
							num4 = num8;
							deepPoint = val;
						}
					}
				}
			}
			return num4 > 0f;
		}
		catch (Exception)
		{
			return false;
		}
	}

	private static float GetCfgSwell()
	{
		return Mathf.Clamp(cfgSwellLengthMult.Value, 0.5f, 2f);
	}

	private static float GetCfgTrough()
	{
		return Mathf.Clamp(cfgPreTroughDepthScale.Value, 0f, 2f);
	}

	private static float GetCfgChop()
	{
		return Mathf.Clamp(cfgTrailingChopScale.Value, 0f, 2f);
	}

	private static float LimitDurationAfterTargetPass(float configuredDuration, float spawnDistance, float speed, bool isGiga)
	{
		float num = Mathf.Max(3f, spawnDistance / Mathf.Max(1f, speed));
		float num2 = (isGiga ? 24f : Mathf.Clamp(cfgNormalPostPassFadeSeconds.Value, 5f, 35f));
		float num3 = num + num2;
		float num4 = (isGiga ? 30f : 18f);
		return Mathf.Clamp(Mathf.Min(configuredDuration, num3), num4, Mathf.Max(num4, configuredDuration));
	}

	public static void ClampWireParams(ref float height, ref float duration, ref float length, ref float width, ref float speed)
	{
		height = Mathf.Clamp(height, 0f, 60f);
		duration = Mathf.Clamp(duration, 5f, 600f);
		length = Mathf.Clamp(length, 20f, 2000f);
		width = Mathf.Clamp(width, 40f, 5000f);
		speed = Mathf.Clamp(speed, 1f, 60f);
	}

	private static void SpawnWaveMember(bool isGiga, float heightMeters, float duration, float length, float width, float speed, float spawnDistance, Vector3 travelDir, Vector3 target, double startDelay)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		if (!isGiga)
		{
			ClampWireParams(ref heightMeters, ref duration, ref length, ref width, ref speed);
			Vector3 origin = target + travelDir * (speed * duration * 0.5f - spawnDistance);
			long id = DateTime.UtcNow.Ticks ^ ((long)rng.Next() << 32) ^ rng.Next();
			RogueWave rogueWave = new RogueWave(id, GetNetworkTime() + startDelay, origin, travelDir, heightMeters, duration, length, width, speed, isGiga, GetCfgSwell(), GetCfgTrough(), GetCfgChop());
			rogueWave.SurgeSpike = Mathf.Clamp(cfgNativeNormalWaveFactorSpike.Value, 1f, 6f);
			rogueWave.SurgeRadius = Mathf.Clamp(cfgNativeSurgeRadiusMultiplier.Value, 0.35f, 4f);
			rogueWave.IsLocal = true;
			rogueWave.NextRebroadcastAt = Time.time + 8f;
			rogueWave.DepthScale = ComputeDepthScale(rogueWave, GetNetworkTime());
			AcceptWave(rogueWave, local: true);
			BroadcastWave(rogueWave);
		}
	}

	private static void UpdatePlayerMotion(Player player)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: 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_005c: 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_0062: 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_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: 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_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		Vector3 position = ((Component)player).transform.position;
		position.y = 0f;
		float time = Time.time;
		if (lastMotionSampleTime < 0f)
		{
			lastMotionSampleTime = time;
			lastMotionSamplePos = position;
			smoothedPlayerVelocity = Vector3.zero;
			return;
		}
		float num = time - lastMotionSampleTime;
		if (!(num < 0.05f))
		{
			Vector3 val = (position - lastMotionSamplePos) / Mathf.Max(0.001f, num);
			val.y = 0f;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude > 18f)
			{
				val *= 18f / magnitude;
			}
			smoothedPlayerVelocity = Vector3.Lerp(smoothedPlayerVelocity, val, 0.18f);
			lastMotionSampleTime = time;
			lastMotionSamplePos = position;
		}
	}

	private static Vector3 PickWaveTravelDirection(Player player, bool isGiga)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: 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_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		Vector3 routeDirection = GetRouteDirection(player);
		if (((Vector3)(ref routeDirection)).sqrMagnitude < 0.001f)
		{
			float num = Next01() * 360f * ((float)Math.PI / 180f);
			((Vector3)(ref routeDirection))..ctor(Mathf.Sin(num), 0f, Mathf.Cos(num));
		}
		float num2 = Mathf.Clamp(cfgHeadSeaChancePercent.Value, 0f, 100f) * 0.01f;
		float num3 = Mathf.Clamp(cfgCrossSeaChancePercent.Value, 0f, 100f) * 0.01f;
		if (isGiga)
		{
			num2 = Mathf.Max(num2, 0.58f);
			num3 = Mathf.Max(num3, 0.22f);
		}
		float num4 = Next01();
		Vector3 val = RotateFlat(degrees: (num4 < num2) ? (180f + RandomSigned(28f)) : ((num4 < num2 + num3) ? (((Next01() < 0.5f) ? (-1f) : 1f) * RandomRange(65f, 115f, 65f)) : ((!(num4 < num2 + num3 + (isGiga ? 0.12f : 0.18f))) ? (Next01() * 360f) : RandomSigned(30f))), dir: routeDirection);
		if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
		{
			return Vector3.forward;
		}
		return ((Vector3)(ref val)).normalized;
	}

	private static Vector3 PredictWaveTarget(Player player, Vector3 travelDir, float speed, float spawnDistance, bool isGiga)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//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_0066: 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_005b: 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_0099: 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_009b: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: 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_00ad: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: 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_00ce: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: 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)
		Vector3 position = ((Component)player).transform.position;
		position.y = 0f;
		float num = Mathf.Clamp01(cfgRoutePredictionStrength.Value);
		Vector3 val = smoothedPlayerVelocity;
		val.y = 0f;
		if (num <= 0.001f || ((Vector3)(ref val)).sqrMagnitude < 0.2f)
		{
			if (!isGiga)
			{
				return AdjustTargetToNearbyWater(position, ((Component)player).transform.position);
			}
			return position;
		}
		float num2 = spawnDistance / Mathf.Max(1f, speed);
		float num3 = (isGiga ? 34f : 24f);
		float num4 = Mathf.Clamp(num2 * num, 0f, num3);
		Vector3 val2 = Vector3.Project(val, travelDir);
		Vector3 val3 = val - val2;
		Vector3 val4 = position + val2 * num4 + val3 * num4 * 0.72f;
		val4.y = position.y;
		if (!isGiga)
		{
			val4 = AdjustTargetToNearbyWater(val4, ((Component)player).transform.position);
		}
		return val4;
	}

	private static Vector3 AdjustTargetToNearbyWater(Vector3 target, Vector3 playerPos)
	{
		//IL_0009: 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_004e: 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_002d: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		try
		{
			WorldGenerator instance = WorldGenerator.instance;
			if (instance == null)
			{
				return target;
			}
			float sea = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f);
			if (IsOceanOrDeepWater(instance, target, sea))
			{
				return target;
			}
			if (TryFindNearbyWaterTarget(playerPos, sea, out var target2))
			{
				return target2;
			}
		}
		catch (Exception)
		{
		}
		return target;
	}

	private static bool TryFindNearbyWaterTarget(Vector3 center, float sea, out Vector3 target)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: 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_00c0: 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_00cc: Invalid comparison between Unknown and I4
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		target = center;
		WorldGenerator instance = WorldGenerator.instance;
		if (instance == null)
		{
			return false;
		}
		float num = -9999f;
		Vector3 val = center;
		float num2 = Mathf.Max(80f, cfgShoreSpectacleDistanceFeet.Value);
		float num3 = num2 * 0.3048f;
		float[] array = new float[5] { 25f, 45f, 70f, 105f, 0f };
		array[4] = Mathf.Min(num3, 150f);
		float[] array2 = array;
		for (int i = 0; i < array2.Length; i++)
		{
			float num4 = Mathf.Clamp(array2[i], 12f, num3);
			for (int j = 0; j < 24; j++)
			{
				float num5 = (float)j * (float)Math.PI * 2f / 24f;
				Vector3 val2 = center + new Vector3(Mathf.Sin(num5) * num4, 0f, Mathf.Cos(num5) * num4);
				bool flag = (int)instance.GetBiome(val2) == 256;
				float num6 = sea - instance.GetHeight(val2.x, val2.z);
				if (flag || !(num6 < 3f))
				{
					float num7 = num6 + (flag ? 14f : 0f) - Mathf.Abs(num4 - 65f) * 0.04f;
					if (num7 > num)
					{
						num = num7;
						val = val2;
					}
				}
			}
		}
		if (num > -999f)
		{
			target = val;
			target.y = center.y;
			return true;
		}
		return false;
	}

	private static Vector3 GetRouteDirection(Player player)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = smoothedPlayerVelocity;
		val.y = 0f;
		if (((Vector3)(ref val)).sqrMagnitude > 0.25f)
		{
			return ((Vector3)(ref val)).normalized;
		}
		if ((Object)(object)player != (Object)null)
		{
			Vector3 forward = ((Component)player).transform.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude > 0.001f)
			{
				return ((Vector3)(ref forward)).normalized;
			}
		}
		return Vector3.forward;
	}

	private static Vector3 RotateFlat(Vector3 dir, float degrees)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		float num = degrees * ((float)Math.PI / 180f);
		float num2 = Mathf.Sin(num);
		float num3 = Mathf.Cos(num);
		return new Vector3(dir.x * num3 + dir.z * num2, 0f, (0f - dir.x) * num2 + dir.z * num3);
	}

	private static float RandomSigned(float maxAbs)
	{
		return (Next01() * 2f - 1f) * maxAbs;
	}

	private static void RebroadcastLocalWaves()
	{
		double networkTime = GetNetworkTime();
		for (int i = 0; i < waves.Count; i++)
		{
			RogueWave rogueWave = waves[i];
			if (rogueWave.IsLocal && !rogueWave.IsExpired(networkTime) && Time.time >= rogueWave.NextRebroadcastAt)
			{
				rogueWave.NextRebroadcastAt = Time.time + 8f;
				BroadcastWave(rogueWave);
			}
		}
	}

	private static float RandomAround(float baseValue, float min)
	{
		return Mathf.Max(min, baseValue * (0.75f + Next01() * 0.6f));
	}

	private static float RandomRange(float a, float b, float floor)
	{
		return Mathf.Max(floor, Mathf.Lerp(Mathf.Min(a, b), Mathf.Max(a, b), Next01()));
	}

	private static float GetHeightOverdrive()
	{
		return Mathf.Clamp(cfgWaveHeightOverdrive.Value, 0.25f, 3f);
	}

	private static float Next01()
	{
		return (float)rng.NextDouble();
	}

	private static void ClearAllWaves()
	{
		waves.Clear();
		gigaDamageAccum.Clear();
		boatClassCache.Clear();
		recentIds.Clear();
		recentIdQueue.Clear();
		ClearVisuals();
	}

	private static void AcceptWave(RogueWave wave, bool local)
	{
		//IL_0085: 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_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		if (wave == null || recentIds.Contains(wave.Id))
		{
			return;
		}
		recentIds.Add(wave.Id);
		recentIdQueue.Enqueue(wave.Id);
		while (recentIdQueue.Count > 64)
		{
			recentIds.Remove(recentIdQueue.Dequeue());
		}
		while (waves.Count >= 8)
		{
			double networkTime = GetNetworkTime();
			Vector3 worldPos = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).transform.position : Vector3.zero);
			int index = 0;
			float num = float.MaxValue;
			for (int i = 0; i < waves.Count; i++)
			{
				float num2 = (waves[i].IsExpired(networkTime) ? (-1f) : waves[i].GetInfluence(worldPos, networkTime));
				if (num2 < num)
				{
					num = num2;
					index = i;
				}
			}
			DestroyVisual(waves[index].Id);
			waves.RemoveAt(index);
		}
		waves.Add(wave);
	}

	private static void PruneExpiredWaves(double now)
	{
		for (int num = waves.Count - 1; num >= 0; num--)
		{
			if (waves[num].IsExpired(now))
			{
				DestroyVisual(waves[num].Id);
				waves.RemoveAt(num);
			}
		}
		if (waves.Count == 0 && gigaDamageAccum.Count > 0)
		{
			gigaDamageAccum.Clear();
		}
	}

	private static bool AnyWaveNear(Vector3 pos, double now)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: 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_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < waves.Count; i++)
		{
			RogueWave rogueWave = waves[i];
			if (!rogueWave.IsExpired(now))
			{
				if (rogueWave.GetInfluence(pos, now) > 0.08f)
				{
					return true;
				}
				Vector3 val = pos - rogueWave.GetCrestCenter(now);
				val.y = 0f;
				float num = (rogueWave.IsGiga ? 260f : 115f);
				if (((Vector3)(ref val)).sqrMagnitude < num * num)
				{
					return true;
				}
			}
		}
		return false;
	}

	private static void RefreshWaveDepthScales(Player player)
	{
		if (!(Time.time < nextDepthRefreshTime))
		{
			nextDepthRefreshTime = Time.time + 1f;
			double networkTime = GetNetworkTime();
			for (int i = 0; i < waves.Count; i++)
			{
				waves[i].DepthScale = ComputeDepthScale(waves[i], networkTime);
			}
		}
	}

	private static float ComputeDepthScale(RogueWave wave, double now)
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Invalid comparison between Unknown and I4
		//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
		if (cfgAllowFullWavesEverywhere.Value)
		{
			return 1f;
		}
		try
		{
			WorldGenerator instance = WorldGenerator.instance;
			if (instance == null)
			{
				return 1f;
			}
			Vector3 crestCenter = wave.GetCrestCenter(now);
			float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f);
			float height = instance.GetHeight(crestCenter.x, crestCenter.z);
			float num2 = num - height;
			if (num2 <= 0.1f)
			{
				return 0f;
			}
			bool flag = (int)instance.GetBiome(crestCenter) == 256;
			float num3 = Mathf.Max(2f, cfgShallowDepthMeters.Value);
			float num4 = Mathf.Clamp01(num2 / num3);
			float num5 = (flag ? 0.72f : 0.58f);
			float num6 = Mathf.Lerp(num5, 1f, num4);
			if (!flag)
			{
				num6 = Mathf.Min(num6, 0.95f);
			}
			float num7 = Mathf.Max(1f, cfgShoreBreakDepthMeters.Value);
			if (num2 <= num7 && IsNearOceanOrLargeWater(crestCenter, Mathf.Max(20f, cfgShoreSpectacleDistanceFeet.Value) * 0.3048f))
			{
				float num8 = Mathf.Clamp01(num2 / num7);
				float num9 = Mathf.Lerp(Mathf.Clamp(cfgShoreBreakHeightBoost.Value, 1f, 2.5f), 1f, num8);
				num6 = Mathf.Max(num6, flag ? 0.85f : 0.7f) * num9;
			}
			return Mathf.Clamp(num6, 0f, 2.25f);
		}
		catch (Exception)
		{
			return 1f;
		}
	}

	private static bool IsSurroundedByOcean(Vector3 center, float radius)
	{
		//IL_0071: 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_007c: Invalid comparison between Unknown and I4
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Invalid comparison between Unknown and I4
		//IL_004c: 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)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Invalid comparison between Unknown and I4
		try
		{
			WorldGenerator instance = WorldGenerator.instance;
			if (instance != null)
			{
				if ((int)instance.GetBiome(center) != 256)
				{
					return false;
				}
				Vector3 val = default(Vector3);
				for (int i = 0; i < 8; i++)
				{
					float num = (float)i * (float)Math.PI * 0.25f;
					((Vector3)(ref val))..ctor(Mathf.Sin(num) * radius, 0f, Mathf.Cos(num) * radius);
					if ((int)instance.GetBiome(center + val) != 256)
					{
						return false;
					}
				}
				return true;
			}
			return (int)Heightmap.FindBiome(center) == 256;
		}
		catch (Exception)
		{
			return false;
		}
	}

	private static bool IsLocalPlayerOpenOcean()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return false;
		}
		return IsSurroundedByOcean(((Component)localPlayer).transform.position, 120f);
	}

	private static bool IsNearOceanOrLargeWater(Vector3 center, float radius)
	{
		//IL_0009: 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_0014: Invalid comparison between Unknown and I4
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: 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)
		try
		{
			WorldGenerator instance = WorldGenerator.instance;
			if (instance == null)
			{
				return (int)Heightmap.FindBiome(center) == 256;
			}
			float sea = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f);
			if (IsOceanOrDeepWater(instance, center, sea))
			{
				return true;
			}
			float[] array = new float[2]
			{
				radius * 0.5f,
				radius
			};
			Vector3 val = default(Vector3);
			for (int i = 0; i < array.Length; i++)
			{
				float num = Mathf.Max(4f, array[i]);
				for (int j = 0; j < 16; j++)
				{
					float num2 = (float)j * (float)Math.PI * 0.125f;
					((Vector3)(ref val))..ctor(Mathf.Sin(num2) * num, 0f, Mathf.Cos(num2) * num);
					if (IsOceanOrDeepWater(instance, center + val, sea))
					{
						return true;
					}
				}
			}
		}
		catch (Exception)
		{
		}
		return false;
	}

	private static bool IsOceanOrDeepWater(WorldGenerator gen, Vector3 pos, float sea)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Invalid comparison between Unknown and I4
		if ((int)gen.GetBiome(pos) == 256)
		{
			return true;
		}
		float height = gen.GetHeight(pos.x, pos.z);
		return sea - height >= 3f;
	}

	private static bool TryGetWaterDepth(Vector3 pos, out float depth)
	{
		depth = 999f;
		try
		{
			WorldGenerator instance = WorldGenerator.instance;
			if (instance == null)
			{
				return false;
			}
			float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f);
			depth = num - instance.GetHeight(pos.x, pos.z);
			return true;
		}
		catch (Exception)
		{
			return false;
		}
	}

	public static float ComputeWaterMask(float depth, bool oceanBiome)
	{
		if (float.IsNaN(depth) || depth <= 0.85f)
		{
			return 0f;
		}
		if (oceanBiome && depth >= 2f)
		{
			return 1f;
		}
		float num = (depth - 0.85f) / 3.75f;
		if (num >= 1f)
		{
			return 1f;
		}
		return num * num * (3f - 2f * num);
	}

	private static float GetWaterInteractionMask(Vector3 pos)
	{
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Invalid comparison between Unknown and I4
		try
		{
			WorldGenerator instance = WorldGenerator.instance;
			if (instance == null)
			{
				return 0f;
			}
			float num = (((Object)(object)ZoneSystem.instance != (Object)null) ? ZoneSystem.instance.m_waterLevel : 30f);
			float depth = num - instance.GetHeight(pos.x, pos.z);
			return ComputeWaterMask(depth, (int)instance.GetBiome(pos) == 256);
		}
		catch (Exception)
		{
			return 0f;
		}
	}

	private static float GetPersistentRoughOceanStrength(Vector3 pos)
	{
		//IL_0022: 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_002d: Invalid comparison between Unknown and I4
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!cfgRoughOceanMode.Value)
			{
				return 0f;
			}
			WorldGenerator instance = WorldGenerator.instance;
			if (instance == null || (int)instance.GetBiome(pos) != 256)
			{
				return 0f;
			}
			if (!TryGetWaterDepth(pos, out var depth) || depth <= 2f)
			{
				return 0f;
			}
			float num = ComputeWaterMask(depth, oceanBiome: true);
			float num2 = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01((depth - 2f) / 10f));
			int weatherTier = GetWeatherTier();
			return Mathf.Clamp01(num * num2) * weatherTier switch
			{
				1 => 1.15f, 
				2 => 1.45f, 
				_ => 1f, 
			};
		}
		catch (Exception)
		{
			return 0f;
		}
	}

	private static float GetPersistentRoughOceanWaveFactorMultiplier(Vector3 worldPos, float liveDepth)
	{
		try
		{
			if (!cfgRoughOceanMode.Value || liveDepth <= 0.85f)
			{
				return 1f;
			}
			if (!IsLocalPlayerNearWaterCached())
			{
				return 1f;
			}
			float num = ComputeWaterMask(liveDepth, oceanBiome: true);
			if (num <= 0.001f)
			{
				return 1f;
			}
			float num2 = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01((liveDepth - 0.85f) / 4f));
			float num3 = Mathf.Clamp01(num * num2);
			if (num3 <= 0.001f)
			{
				return 1f;
			}
			float num4 = Mathf.Clamp(cfgRoughOceanWaveFactor.Value, 1f, 6f);
			if (GetWeatherTierCachedForRoughOcean() == 2)
			{
				num4 *= Mathf.Clamp(cfgRoughOceanStormFactor.Value, 1f, 2f);
			}
			float num5 = (IsLocalPlayerOpenOceanCached() ? 1f : Mathf.Clamp01(cfgRoughOceanShoreViewMultiplier.Value));
			return Mathf.Lerp(1f, Mathf.Clamp(num4, 1f, 8f), num3 * num5);
		}
		catch (Exception)
		{
			return 1f;
		}
	}

	private static float GetNativeWaveFactorMultiplier(Vector3 worldPos)
	{
		//IL_001e: 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)
		if (waves.Count == 0 || !cfgEnabled.Value)
		{
			return 1f;
		}
		float waterInteractionMask = GetWaterInteractionMask(worldPos);
		if (waterInteractionMask <= 0.001f)
		{
			return 1f;
		}
		double networkTimeCached = GetNetworkTimeCached();
		float num = 0f;
		for (int i = 0; i < waves.Count; i++)
		{
			RogueWave rogueWave = waves[i];
			float nativeSurgeStrength = rogueWave.GetNativeSurgeStrength(worldPos, networkTimeCached, rogueWave.SurgeRadius);
			if (!(nativeSurgeStrength <= 0.001f))
			{
				num = Mathf.Max(num, (rogueWave.SurgeSpike - 1f) * nativeSurgeStrength);
			}
		}
		return Mathf.Clamp(1f + num * waterInteractionMask, 1f, 8f);
	}

	public static float ExtraWaveHeight(Vector3 worldPos)
	{
		//IL_001e: 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)
		if (waves.Count == 0 || !cfgEnabled.Value)
		{
			return 0f;
		}
		float waterInteractionMask = GetWaterInteractionMask(worldPos);
		if (waterInteractionMask <= 0.001f)
		{
			return 0f;
		}
		double networkTimeCached = GetNetworkTimeCached();
		float num = 0f;
		for (int i = 0; i < waves.Count; i++)
		{
			num += waves[i].GetHeight(worldPos, networkTimeCached);
		}
		return num * waterInteractionMask;
	}

	private static void HandleShipPhysics(Ship ship)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(