Decompiled source of ArcaneDecor WaterGardens KoiFish v1.0.0

plugins/ArcaneDecorWaterGardensKoiFish/WaterGardensKoi.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using RunicLilyPads;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("KoiSmoke")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("WaterGardensKoi")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ArcaneDecor:WaterGardens:KoiFish")]
[assembly: AssemblyTitle("ArcaneDecor:WaterGardens:KoiFish")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WaterGardensKoi
{
	internal static class KoiAssets
	{
		internal sealed class Data
		{
			internal Mesh Mesh;

			internal Material Material;
		}

		internal static readonly string[] Names = new string[5] { "ogon", "sanke", "kohaku", "orange", "gold" };

		private static readonly Data[] Cache = new Data[5];

		internal static Vector3 Pivot(int index)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(0f, 0f, 0.35f - (float)index * 0.16f);
		}

		private static Stream Open(string name)
		{
			return typeof(Plugin).Assembly.GetManifestResourceStream("Koi." + name);
		}

		internal static void Preload()
		{
			Load(3);
			Load(4);
			Load(2);
		}

		internal static Data Load(int index)
		{
			//IL_00af: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: 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_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Expected O, but got Unknown
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Expected O, but got Unknown
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Expected O, but got Unknown
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			if (Cache[index] != null)
			{
				return Cache[index];
			}
			string text = Names[index];
			Data data = new Data();
			using (Stream input = Open(text + ".meshbin"))
			{
				using BinaryReader binaryReader = new BinaryReader(input);
				if (binaryReader.ReadInt32() != 1464290609)
				{
					throw new InvalidDataException(text);
				}
				int num = binaryReader.ReadInt32();
				int num2 = binaryReader.ReadInt32();
				Vector3[] array = (Vector3[])(object)new Vector3[num];
				Vector3[] array2 = (Vector3[])(object)new Vector3[num];
				Vector2[] array3 = (Vector2[])(object)new Vector2[num];
				int[] array4 = new int[num2];
				BoneWeight[] array5 = (BoneWeight[])(object)new BoneWeight[num];
				for (int i = 0; i < num; i++)
				{
					array[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
					array2[i] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
					array3[i] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
					float num3 = (float)KoiMath.BoneCoordinate(array[i].z);
					int num4 = Mathf.FloorToInt(num3);
					int boneIndex = Mathf.Min(num4 + 1, 5);
					float num5 = num3 - (float)num4;
					int num6 = i;
					BoneWeight val = default(BoneWeight);
					((BoneWeight)(ref val)).boneIndex0 = num4;
					((BoneWeight)(ref val)).boneIndex1 = boneIndex;
					((BoneWeight)(ref val)).weight0 = 1f - num5;
					((BoneWeight)(ref val)).weight1 = num5;
					array5[num6] = val;
				}
				for (int j = 0; j < num2; j++)
				{
					array4[j] = binaryReader.ReadInt32();
				}
				Matrix4x4[] array6 = (Matrix4x4[])(object)new Matrix4x4[6];
				for (int k = 0; k < 6; k++)
				{
					int num7 = k;
					Matrix4x4 val2 = Matrix4x4.TRS(Pivot(k), Quaternion.identity, Vector3.one);
					array6[num7] = ((Matrix4x4)(ref val2)).inverse;
				}
				data.Mesh = new Mesh
				{
					name = "Koi " + text,
					indexFormat = (IndexFormat)1,
					vertices = array,
					normals = array2,
					uv = array3,
					triangles = array4,
					boneWeights = array5,
					bindposes = array6
				};
				data.Mesh.RecalculateBounds();
				data.Mesh.RecalculateTangents();
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab("Fish1");
			Renderer val3 = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponentInChildren<Renderer>(true) : null);
			if (!Object.op_Implicit((Object)(object)val3))
			{
				throw new InvalidOperationException("Native Fish1 material unavailable.");
			}
			data.Material = new Material(val3.sharedMaterial);
			using (Stream stream = Open(text + ".jpg"))
			{
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				Texture2D val4 = new Texture2D(2, 2, (TextureFormat)3, true);
				if (!ImageConversion.LoadImage(val4, memoryStream.ToArray(), true))
				{
					throw new InvalidDataException("Koi texture " + text);
				}
				data.Material.mainTexture = (Texture)(object)val4;
				data.Material.SetColor("_Color", Color.white);
			}
			Cache[index] = data;
			return data;
		}

		internal static Transform[] Build(Transform parent, int variety)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			Data data = Load(variety);
			Transform[] array = (Transform[])(object)new Transform[6];
			for (int i = 0; i < 6; i++)
			{
				array[i] = new GameObject("body_" + i).transform;
				array[i].SetParent(parent, false);
				array[i].localPosition = Pivot(i);
			}
			SkinnedMeshRenderer obj = ((Component)parent).gameObject.AddComponent<SkinnedMeshRenderer>();
			obj.sharedMesh = data.Mesh;
			((Renderer)obj).sharedMaterial = data.Material;
			obj.bones = array;
			obj.rootBone = parent;
			obj.quality = (SkinQuality)2;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).localBounds = new Bounds(Vector3.zero, new Vector3(1.2f, 0.8f, 1.3f));
			obj.updateWhenOffscreen = false;
			return array;
		}
	}
	internal static class KoiMath
	{
		internal static double Aspect(int shape)
		{
			if (shape != 1)
			{
				return 1.0;
			}
			return 0.65;
		}

		internal static double Radius(int shape, double angle)
		{
			switch (shape)
			{
			case 2:
				angle = Math.Atan2(Math.Sin(angle), Math.Cos(angle));
				return 1.0 - 0.4 * Math.Exp((0.0 - angle) * angle / 0.32);
			case 3:
				return 0.9 + 0.07 * Math.Sin(3.0 * angle) + 0.03 * Math.Cos(5.0 * angle);
			default:
				return 1.0;
			}
		}

		internal static double Distance(int shape, double x, double z, double width)
		{
			x /= width * 0.5;
			z /= width * 0.5 * Aspect(shape);
			return Math.Sqrt(x * x + z * z) / Radius(shape, Math.Atan2(z, x));
		}

		internal static void Orbit(int shape, double width, double time, int index, double seed, out double x, out double z)
		{
			double num = time * (0.12 + (double)index * 0.009) * (double)((index % 2 == 0) ? 1 : (-1)) + (double)index * 1.8 + seed;
			double num2 = width * 0.5 * Radius(shape, num) * (0.51 + 0.08 * Math.Sin(time * 0.09 + (double)index));
			x = Math.Cos(num) * num2;
			z = Math.Sin(num) * num2 * Aspect(shape);
		}

		internal static double Blend(double elapsed, double seconds)
		{
			double num = Math.Max(0.0, Math.Min(1.0, elapsed / seconds));
			return num * num * (3.0 - 2.0 * num);
		}

		internal static double BoneCoordinate(double z)
		{
			return Math.Max(0.0, Math.Min(5.0, (0.35 - z) / 0.16));
		}
	}
	internal sealed class KoiMenuBridge : MonoBehaviour
	{
		private static TMP_FontAsset fallbackFont;

		private static readonly FieldInfo FontField = AccessTools.Field(typeof(PondMenu), "font");

		private static readonly FieldInfo Panel = AccessTools.Field(typeof(PondMenu), "panel");

		private static readonly FieldInfo Canvas = AccessTools.Field(typeof(PondMenu), "canvas");

		internal static KoiMenuBridge Active;

		internal KoiSchool School;

		internal KoiSettings Draft;

		private PondMenu expanded;

		private TMP_Text buttonLabel;

		internal static void EnsureFont(PondMenu menu)
		{
			object? value = FontField.GetValue(menu);
			TMP_FontAsset val = (TMP_FontAsset)((value is TMP_FontAsset) ? value : null);
			if (val != null && Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)fallbackFont))
			{
				Font val2 = null;
				Font[] array = Resources.FindObjectsOfTypeAll<Font>();
				foreach (Font val3 in array)
				{
					if (((Object)val3).name.IndexOf("Norse", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						val2 = val3;
						break;
					}
				}
				if (!Object.op_Implicit((Object)(object)val2))
				{
					val2 = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
				}
				fallbackFont = TMP_FontAsset.CreateFontAsset(val2);
				if (!Object.op_Implicit((Object)(object)fallbackFont))
				{
					fallbackFont = TMP_FontAsset.CreateFontAsset(Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf"));
				}
				if (!Object.op_Implicit((Object)(object)fallbackFont))
				{
					throw new InvalidOperationException("No usable menu font available.");
				}
				((Object)fallbackFont).name = "WaterGardens Koi menu fallback";
			}
			FontField.SetValue(menu, fallbackFont);
		}

		internal static void Attach(PondMenu menu, GardenPiece pond)
		{
			//IL_0024: 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_005e: Expected O, but got Unknown
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: 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_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			KoiSchool component = ((Component)pond).GetComponent<KoiSchool>();
			if (Object.op_Implicit((Object)(object)component) && pond.Shape >= 0)
			{
				KoiMenuBridge koiMenuBridge = ((GameObject)Canvas.GetValue(menu)).AddComponent<KoiMenuBridge>();
				koiMenuBridge.School = component;
				koiMenuBridge.Draft = component.Options.Copy();
				Active = koiMenuBridge;
				RectTransform val = (RectTransform)Panel.GetValue(menu);
				GameObject val2 = new GameObject("Fish menu toggle", new Type[3]
				{
					typeof(RectTransform),
					typeof(Image),
					typeof(Button)
				});
				RectTransform val3 = (RectTransform)val2.transform;
				((Transform)val3).SetParent((Transform)(object)val, false);
				Vector2 val4 = default(Vector2);
				((Vector2)(ref val4))..ctor(0f, 1f);
				val3.pivot = val4;
				Vector2 anchorMin = (val3.anchorMax = val4);
				val3.anchorMin = anchorMin;
				val3.anchoredPosition = new Vector2(420f, -18f);
				val3.sizeDelta = new Vector2(138f, 38f);
				((Graphic)val2.GetComponent<Image>()).color = new Color(0.22f, 0.27f, 0.28f, 1f);
				Button component2 = val2.GetComponent<Button>();
				((Selectable)component2).targetGraphic = (Graphic)(object)val2.GetComponent<Image>();
				((UnityEvent)component2.onClick).AddListener(new UnityAction(koiMenuBridge.Toggle));
				GameObject val6 = new GameObject("Fish", new Type[2]
				{
					typeof(RectTransform),
					typeof(TextMeshProUGUI)
				});
				RectTransform val7 = (RectTransform)val6.transform;
				((Transform)val7).SetParent((Transform)(object)val3, false);
				val7.anchorMin = Vector2.zero;
				val7.anchorMax = Vector2.one;
				anchorMin = (val7.offsetMax = Vector2.zero);
				val7.offsetMin = anchorMin;
				koiMenuBridge.buttonLabel = val6.GetComponent<TMP_Text>();
				TMP_Text componentInChildren = ((Component)val).GetComponentInChildren<TMP_Text>();
				koiMenuBridge.buttonLabel.font = componentInChildren.font;
				koiMenuBridge.buttonLabel.fontSize = 20f;
				koiMenuBridge.buttonLabel.alignment = (TextAlignmentOptions)514;
				koiMenuBridge.buttonLabel.text = "Fish >";
				componentInChildren.rectTransform.sizeDelta = new Vector2(392f, 38f);
			}
		}

		internal void Toggle()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			if (expanded != null)
			{
				Collapse();
				return;
			}
			expanded = new PondMenu(412f);
			((RectTransform)Panel.GetValue(expanded)).anchoredPosition = new Vector2(616f, -16f);
			expanded.Heading("FISH", 18f, 30, 40f);
			float num = 78f;
			expanded.Range("Orange Koi", 0f, 10f, (float)Draft.Orange, (Action<float>)delegate(float v)
			{
				Draft.Orange = Mathf.RoundToInt(v);
			}, (Func<string>)(() => Draft.Orange.ToString()), ref num);
			expanded.Range("Golden Koi", 0f, 10f, (float)Draft.Golden, (Action<float>)delegate(float v)
			{
				Draft.Golden = Mathf.RoundToInt(v);
			}, (Func<string>)(() => Draft.Golden.ToString()), ref num);
			expanded.Range("Kohaku (white and orange)", 0f, 10f, (float)Draft.Kohaku, (Action<float>)delegate(float v)
			{
				Draft.Kohaku = Mathf.RoundToInt(v);
			}, (Func<string>)(() => Draft.Kohaku.ToString()), ref num);
			expanded.Range("Fish size", 1f, 3f, Draft.Scale, (Action<float>)delegate(float v)
			{
				Draft.Scale = Mathf.Round(v * 10f) / 10f;
			}, (Func<string>)(() => Draft.Scale.ToString("0.0") + "x"), ref num);
			Slider[] componentsInChildren = ((Component)(RectTransform)Panel.GetValue(expanded)).GetComponentsInChildren<Slider>();
			foreach (Slider val in componentsInChildren)
			{
				if (val.maxValue == 10f)
				{
					val.wholeNumbers = true;
				}
			}
			expanded.Heading("Use the pond's Save button to apply fish settings.", 310f, 18, 42f);
			expanded.Action("Collapse fish menu", 362f, (Action)Collapse);
			buttonLabel.text = "Fish <";
		}

		private void Collapse()
		{
			PondMenu obj = expanded;
			if (obj != null)
			{
				obj.Dispose();
			}
			expanded = null;
			if (Object.op_Implicit((Object)(object)buttonLabel))
			{
				buttonLabel.text = "Fish >";
			}
		}

		private void OnDisable()
		{
			Collapse();
			if ((Object)(object)Active == (Object)(object)this)
			{
				Active = null;
			}
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class FishMenuFontPatch
	{
		private static void Postfix(PondMenu __instance)
		{
			KoiMenuBridge.EnsureFont(__instance);
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class FishMenuPatch
	{
		private static void Postfix(PondMenu __instance, GardenPiece target)
		{
			KoiMenuBridge.Attach(__instance, target);
		}
	}
	[HarmonyPatch(typeof(GardenPiece), "Save")]
	internal static class FishSavePatch
	{
		private static void Postfix(GardenPiece __instance, bool __result)
		{
			KoiMenuBridge active = KoiMenuBridge.Active;
			if (__result && Object.op_Implicit((Object)(object)active) && Object.op_Implicit((Object)(object)active.School) && (Object)(object)active.School.Pond == (Object)(object)__instance)
			{
				active.School.QueueOptions(active.Draft);
			}
		}
	}
	public sealed class KoiSchool : MonoBehaviour
	{
		internal static readonly List<KoiSchool> Schools = new List<KoiSchool>();

		internal readonly List<PondFood> Food = new List<PondFood>();

		private static readonly FieldInfo SettingsField = typeof(GardenPiece).GetField("Settings", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly float[] Amplitudes = new float[6] { 0f, 1f, 3f, 7f, 14f, 23f };

		private static readonly Func<Vector3, float> Surface = (Func<Vector3, float>)Delegate.CreateDelegate(typeof(Func<Vector3, float>), typeof(GardenPiece).Assembly.GetType("RunicLilyPads.PondNetwork").GetMethod("WaterLevel", BindingFlags.Static | BindingFlags.NonPublic));

		internal GardenPiece Pond;

		internal float Width = 6f;

		internal float Depth = 1.2f;

		internal float Water;

		internal KoiSettings Options = new KoiSettings();

		private ZNetView view;

		internal Transform[] fish;

		private Transform[][] bones;

		private Vector3[] returnFrom;

		private float next;

		private double seed;

		private double returnStart = -10.0;

		private bool near;

		private string lastOptions = "";

		private KoiSettings pending;

		private float pendingUntil;

		private PondFood previousFood;

		private bool previousFed;

		private KoiSplash splash;

		internal int Count => Options.Total;

		internal static double Clock
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)ZNet.instance))
				{
					return Time.timeAsDouble;
				}
				return (double)ZNet.instance.GetTime().Ticks / 10000000.0;
			}
		}

		internal bool Live
		{
			get
			{
				if (Object.op_Implicit((Object)(object)Pond) && Object.op_Implicit((Object)(object)view))
				{
					return view.IsValid();
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_001f: 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)
			Pond = ((Component)this).GetComponent<GardenPiece>();
			view = ((Component)this).GetComponent<ZNetView>();
			seed = (double)((Component)this).transform.position.x * 0.163 + (double)((Component)this).transform.position.z * 0.087;
			Schools.Add(this);
		}

		private void OnDestroy()
		{
			Schools.Remove(this);
			foreach (PondFood item in Food)
			{
				if (Object.op_Implicit((Object)(object)item))
				{
					item.School = null;
				}
			}
		}

		internal void QueueOptions(KoiSettings settings)
		{
			if (settings.Valid)
			{
				pending = settings.Copy();
				pendingUntil = Time.time + 5f;
			}
		}

		internal bool Inside(Vector3 point, float margin = 1f)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			return KoiMath.Distance(Pond.Shape, Local(point).x, Local(point).z, Width) < (double)margin;
		}

		private Vector3 Local(Vector3 point)
		{
			//IL_000b: 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_001f: 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_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_0035: Unknown result type (might be due to invalid IL or missing references)
			return Quaternion.Inverse(Quaternion.Euler(0f, ((Component)this).transform.eulerAngles.y, 0f)) * (point - ((Component)this).transform.position);
		}

		internal static KoiSchool At(Vector3 point)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			KoiSchool koiSchool = null;
			foreach (KoiSchool school in Schools)
			{
				if (Object.op_Implicit((Object)(object)school) && school.Live && school.Inside(point) && point.y <= school.Water + 2f && point.y >= school.Water - school.Depth - 0.5f && (!Object.op_Implicit((Object)(object)koiSchool) || school.Water > koiSchool.Water))
				{
					koiSchool = school;
				}
			}
			return koiSchool;
		}

		internal void ReadSettings()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			GardenSettings val = (GardenSettings)SettingsField.GetValue(Pond);
			Width = val.Width;
			Depth = val.Depth;
			float num = Surface(((Component)this).transform.position);
			Water = (float.IsNegativeInfinity(num) ? (((Component)this).transform.position.y - 0.15f) : num);
			string text = view.GetZDO().GetString("koi_settings_v1", "");
			if (text != lastOptions && KoiSettings.TryDecode(text, out var value))
			{
				Options = value;
				lastOptions = text;
				Rebuild();
			}
		}

		internal Vector3 KeepInside(Vector3 point, int index)
		{
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: 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_00eb: 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_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Local(point);
			float num = (float)KoiMath.Distance(Pond.Shape, val.x, val.z, Width);
			float num2 = Mathf.Clamp(0.95f - Length(index) * 0.55f / (Width * 0.5f * (float)KoiMath.Aspect(Pond.Shape) * ((Pond.Shape == 2) ? 0.6f : ((Pond.Shape == 3) ? 0.8f : 1f))), 0.15f, 0.9f);
			if (num > num2)
			{
				val.x *= num2 / num;
				val.z *= num2 / num;
				Vector3 result = ((Component)this).transform.position + Quaternion.Euler(0f, ((Component)this).transform.eulerAngles.y, 0f) * val;
				result.y = point.y;
				return result;
			}
			return point;
		}

		internal Vector3 Orbit(int index, double time)
		{
			//IL_002a: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			KoiMotion.Wander(Pond.Shape, Width, time, index, seed, out var x, out var z);
			Vector3 val = KeepInside(((Component)this).transform.position + Quaternion.Euler(0f, ((Component)this).transform.eulerAngles.y, 0f) * new Vector3((float)x, 0f, (float)z), index);
			float num = Surface(val);
			if (float.IsNegativeInfinity(num))
			{
				num = Water;
			}
			float num2 = Mathf.Min(Depth * 0.55f, 0.65f);
			float num3 = Mathf.Min(0.025f * Options.Scale, Depth * 0.15f);
			val.y = num - Mathf.Lerp(num2, num3, (float)KoiMotion.SurfaceBlend(time, index, seed));
			return val;
		}

		internal PondFood Target()
		{
			//IL_0054: 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)
			PondFood pondFood = null;
			foreach (PondFood item in Food)
			{
				if (Object.op_Implicit((Object)(object)item) && item.StartTicks > 0 && (!Object.op_Implicit((Object)(object)pondFood) || item.StartTicks < pondFood.StartTicks || (item.StartTicks == pondFood.StartTicks && ((Component)item).transform.position.x < ((Component)pondFood).transform.position.x)))
				{
					pondFood = item;
				}
			}
			return pondFood;
		}

		internal float Length(int index)
		{
			return (0.44f + (float)(index % 3) * 0.025f) * Options.Scale;
		}

		private Vector3 Destination(int index, PondFood food)
		{
			//IL_0046: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)index * MathF.PI * 2f / (float)Mathf.Max(1, Count);
			float num2 = Mathf.Min(0.25f * Options.Scale, Width * 0.12f);
			Vector3 point = ((Component)food).transform.position + new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * num2;
			point.y = Water - 0.04f;
			return KeepInside(point, index);
		}

		internal double GatherDuration(PondFood food)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)food))
			{
				return 0.0;
			}
			double time = (double)food.StartTicks / 10000000.0;
			double num = 1.5;
			for (int i = 0; i < Count; i++)
			{
				num = Math.Max(num, (double)Vector3.Distance(Orbit(i, time), Destination(i, food)) / (0.65 * (double)Options.Scale));
			}
			return num;
		}

		internal double FeedingElapsed(PondFood food, double now)
		{
			return now - (double)food.StartTicks / 10000000.0 - food.GatherSeconds;
		}

		internal bool Feeding(PondFood food, double now)
		{
			if (Object.op_Implicit((Object)(object)food) && Count > 0 && FeedingElapsed(food, now) >= 0.0)
			{
				return FeedingElapsed(food, now) < 3.0;
			}
			return false;
		}

		internal Vector3 Position(int index, double time, PondFood food = null)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)food))
			{
				food = Target();
			}
			if (!Object.op_Implicit((Object)(object)food))
			{
				Vector3 val = Orbit(index, time);
				if (returnFrom != null && index < returnFrom.Length && time - returnStart < 1.5)
				{
					return Vector3.Lerp(returnFrom[index], val, (float)KoiMath.Blend(time - returnStart, 1.5));
				}
				return val;
			}
			double num = (double)food.StartTicks / 10000000.0;
			Vector3 val2 = Destination(index, food);
			Vector3 point = Vector3.Lerp(Orbit(index, num), val2, (float)KoiMath.Blend(time - num, food.GatherSeconds));
			double num2 = FeedingElapsed(food, time);
			if (num2 >= 0.0 && num2 < 3.0)
			{
				point.y = Water + (-0.04f + 0.012f * (float)Math.Sin(num2 * 3.0 + (double)index * 1.7)) * Options.Scale;
			}
			return KeepInside(point, index);
		}

		internal bool ReadyToEat(PondFood food, double now)
		{
			if (Object.op_Implicit((Object)(object)food) && (Object)(object)Target() == (Object)(object)food && Count > 0)
			{
				return FeedingElapsed(food, now) >= 3.0;
			}
			return false;
		}

		private void Rebuild()
		{
			if (fish != null)
			{
				Transform[] array = fish;
				foreach (Transform val in array)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						Object.Destroy((Object)(object)((Component)val).gameObject);
					}
				}
			}
			fish = null;
			bones = null;
			returnFrom = null;
			previousFood = null;
			previousFed = false;
			if (near && Count > 0)
			{
				Build();
			}
		}

		private void Build()
		{
			//IL_005d: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			fish = (Transform[])(object)new Transform[Count];
			bones = new Transform[Count][];
			returnFrom = (Vector3[])(object)new Vector3[Count];
			for (int i = 0; i < Count; i++)
			{
				fish[i] = new GameObject("pond_koi_" + KoiAssets.Names[Options.Variety(i)]).transform;
				fish[i].SetParent(((Component)this).transform, false);
				fish[i].localScale = Vector3.one * Length(i);
				bones[i] = KoiAssets.Build(fish[i], Options.Variety(i));
			}
			if (!Object.op_Implicit((Object)(object)splash))
			{
				splash = ((Component)this).gameObject.AddComponent<KoiSplash>();
			}
		}

		private void Update()
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Invalid comparison between Unknown and I4
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: 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_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0393: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			if (!Live)
			{
				return;
			}
			if (pending != null)
			{
				if (Time.time > pendingUntil)
				{
					pending = null;
				}
				else if (view.IsOwner())
				{
					view.GetZDO().Set("koi_settings_v1", pending.Encode());
					pending = null;
					next = 0f;
				}
			}
			if (Time.time >= next)
			{
				next = Time.time + 0.5f;
				ReadSettings();
				int num;
				if ((int)SystemInfo.graphicsDeviceType != 4 && Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					Vector3 val = ((Component)Player.m_localPlayer).transform.position - ((Component)this).transform.position;
					num = ((((Vector3)(ref val)).sqrMagnitude < 3600f) ? 1 : 0);
				}
				else
				{
					num = 0;
				}
				bool flag = (byte)num != 0;
				near = flag;
				if (flag && fish == null && Count > 0)
				{
					Build();
				}
				if (fish != null)
				{
					Transform[] array = fish;
					foreach (Transform val2 in array)
					{
						if (((Component)val2).gameObject.activeSelf != flag)
						{
							((Component)val2).gameObject.SetActive(flag);
						}
					}
				}
			}
			if (!near || fish == null)
			{
				if (Object.op_Implicit((Object)(object)splash))
				{
					splash.Stop();
				}
				return;
			}
			double clock = Clock;
			PondFood pondFood = Target();
			bool flag2 = Feeding(pondFood, clock);
			if (previousFed && !flag2)
			{
				for (int j = 0; j < fish.Length; j++)
				{
					returnFrom[j] = fish[j].position;
				}
				returnStart = clock;
			}
			if ((Object)(object)pondFood != (Object)(object)previousFood && Object.op_Implicit((Object)(object)previousFood))
			{
				for (int k = 0; k < fish.Length; k++)
				{
					returnFrom[k] = fish[k].position;
				}
				returnStart = clock;
			}
			previousFood = pondFood;
			previousFed = flag2;
			if (Object.op_Implicit((Object)(object)splash))
			{
				if (flag2)
				{
					splash.Show(((Component)pondFood).transform.position, Water, Options.Scale, Count);
				}
				else
				{
					splash.Stop();
				}
			}
			for (int l = 0; l < Count; l++)
			{
				Vector3 val3 = KoiMotion.Adjust(Position(l, clock, pondFood), this, l);
				Vector3 val4 = KoiMotion.Direction(Position(l, clock + 0.08, pondFood) - val3, this, l, val3);
				if (Object.op_Implicit((Object)(object)pondFood) && ((Vector3)(ref val4)).sqrMagnitude < 1E-05f)
				{
					val4 = ((Component)pondFood).transform.position - val3;
					val4.y = 0f;
				}
				if (flag2)
				{
					val4.y = 0f;
					float num2 = (float)Math.Sin(clock * 3.0 + (double)l * 1.7) * 8f;
					fish[l].rotation = KoiMotion.Turn(Quaternion.LookRotation((((Vector3)(ref val4)).sqrMagnitude > 1E-05f) ? val4 : Vector3.forward, Vector3.up) * Quaternion.Euler(num2, 0f, 0f), this, l);
				}
				else if (((Vector3)(ref val4)).sqrMagnitude > 1E-06f)
				{
					fish[l].rotation = KoiMotion.Turn(Quaternion.LookRotation(val4, Vector3.up), this, l);
				}
				fish[l].position = val3;
				for (int m = 0; m < 6; m++)
				{
					bones[l][m].localRotation = Quaternion.Euler(0f, (float)Math.Sin(clock * (double)(flag2 ? 8 : 7) - (double)l * 0.8 - (double)m * 0.7) * Amplitudes[m] * (flag2 ? 0.8f : 1f), 0f);
				}
			}
		}
	}
	public sealed class PondFood : MonoBehaviour
	{
		internal KoiSchool School;

		internal long StartTicks;

		internal double GatherSeconds = 2.0;

		private ZNetView view;

		private ItemDrop item;

		private Rigidbody body;

		private float next;

		private bool eating;

		private long measuredTicks;

		private int measuredCount;

		private float measuredScale;

		private void Awake()
		{
			view = ((Component)this).GetComponent<ZNetView>();
			item = ((Component)this).GetComponent<ItemDrop>();
			body = ((Component)this).GetComponent<Rigidbody>();
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)School))
			{
				School.Food.Remove(this);
			}
		}

		private void Update()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			if (Time.time < next || !Object.op_Implicit((Object)(object)view) || !view.IsValid())
			{
				return;
			}
			next = Time.time + 0.15f;
			KoiSchool koiSchool = KoiSchool.At(((Component)this).transform.position);
			if ((Object)(object)koiSchool != (Object)(object)School)
			{
				if (Object.op_Implicit((Object)(object)School))
				{
					School.Food.Remove(this);
				}
				School = koiSchool;
				if (Object.op_Implicit((Object)(object)School))
				{
					School.Food.Add(this);
				}
				measuredTicks = 0L;
			}
			if (!Object.op_Implicit((Object)(object)School) || School.Count == 0 || ((Component)this).transform.position.y > School.Water + 0.15f)
			{
				if (Object.op_Implicit((Object)(object)body))
				{
					body.useGravity = true;
				}
				if (view.IsOwner() && view.GetZDO().GetLong("koi_food_time", 0L) != 0L)
				{
					view.GetZDO().Set("koi_food_time", 0L);
				}
				StartTicks = 0L;
				measuredTicks = 0L;
				return;
			}
			ZDO zDO = view.GetZDO();
			StartTicks = zDO.GetLong("koi_food_time", 0L);
			if (view.IsOwner())
			{
				if (StartTicks == 0L || zDO.GetInt("koi_food_version", 0) < 2)
				{
					StartTicks = ZNet.instance.GetTime().Ticks;
					zDO.Set("koi_food_time", StartTicks);
					zDO.Set("koi_food_version", 2);
				}
				Vector3 val = ((Component)this).transform.position;
				val.y = School.Water + 0.01f;
				if (!School.Inside(val, 0.7f))
				{
					Vector3 val2 = ((Component)School).transform.position - val;
					val2.y = 0f;
					val += ((Vector3)(ref val2)).normalized * 0.05f;
				}
				if (Object.op_Implicit((Object)(object)body))
				{
					body.useGravity = false;
					body.linearVelocity = Vector3.zero;
					body.angularVelocity = Vector3.zero;
					body.position = val;
				}
				else
				{
					((Component)this).transform.position = val;
				}
			}
			if (view.IsOwner() && (StartTicks != measuredTicks || measuredCount != School.Count || measuredScale != School.Options.Scale))
			{
				measuredTicks = StartTicks;
				measuredCount = School.Count;
				measuredScale = School.Options.Scale;
				GatherSeconds = School.GatherDuration(this);
				zDO.Set("koi_gather_seconds", (float)GatherSeconds);
			}
			else
			{
				GatherSeconds = zDO.GetFloat("koi_gather_seconds", 2f);
			}
			if (view.IsOwner() && !eating && item.CanEat() && School.ReadyToEat(this, KoiSchool.Clock))
			{
				eating = true;
				bool flag = item.m_itemData.m_stack > 1;
				if (item.RemoveOne() && flag)
				{
					StartTicks = ZNet.instance.GetTime().Ticks;
					zDO.Set("koi_food_time", StartTicks);
				}
				eating = false;
			}
		}
	}
	internal sealed class KoiSettings
	{
		internal int Orange = 1;

		internal int Golden = 1;

		internal int Kohaku = 1;

		internal float Scale = 1f;

		internal int Total => Orange + Golden + Kohaku;

		internal bool Valid
		{
			get
			{
				if (Orange >= 0 && Orange <= 10 && Golden >= 0 && Golden <= 10 && Kohaku >= 0 && Kohaku <= 10 && !float.IsNaN(Scale) && !float.IsInfinity(Scale) && Scale >= 1f)
				{
					return Scale <= 3f;
				}
				return false;
			}
		}

		internal KoiSettings Copy()
		{
			return (KoiSettings)MemberwiseClone();
		}

		internal int Variety(int index)
		{
			if (index >= Orange)
			{
				if (index >= Orange + Golden)
				{
					return 2;
				}
				return 4;
			}
			return 3;
		}

		internal string Encode()
		{
			return string.Join("|", Orange, Golden, Kohaku, Scale.ToString("R", CultureInfo.InvariantCulture));
		}

		internal static bool TryDecode(string raw, out KoiSettings value)
		{
			value = new KoiSettings();
			if (string.IsNullOrEmpty(raw))
			{
				return true;
			}
			if (raw.Length > 80)
			{
				return false;
			}
			string[] array = raw.Split('|');
			if (array.Length == 4 && int.TryParse(array[0], out value.Orange) && int.TryParse(array[1], out value.Golden) && int.TryParse(array[2], out value.Kohaku) && float.TryParse(array[3], NumberStyles.Float, CultureInfo.InvariantCulture, out value.Scale))
			{
				return value.Valid;
			}
			return false;
		}
	}
	public sealed class KoiSplash : MonoBehaviour
	{
		private const int PoolSize = 3;

		private GameObject[] pool;

		private ParticleSystem[][] particles;

		private int slot;

		private float pulse;

		private void Awake()
		{
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = PrefabManager.Instance.GetPrefab("Fish1");
			Fish val = ((prefab != null) ? prefab.GetComponent<Fish>() : null);
			GameObject val2 = null;
			if (Object.op_Implicit((Object)(object)val))
			{
				EffectData[] effectPrefabs = val.m_jumpEffects.m_effectPrefabs;
				foreach (EffectData val3 in effectPrefabs)
				{
					if (Object.op_Implicit((Object)(object)val3.m_prefab) && Object.op_Implicit((Object)(object)val3.m_prefab.GetComponentInChildren<ParticleSystem>(true)))
					{
						val2 = val3.m_prefab;
						break;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)val2))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"Native fish splash unavailable; feeding bob animation remains active.");
				}
				return;
			}
			pool = (GameObject[])(object)new GameObject[3];
			particles = new ParticleSystem[3][];
			for (int j = 0; j < 3; j++)
			{
				pool[j] = Object.Instantiate<GameObject>(val2, ((Component)this).transform);
				((Object)pool[j]).name = "koi_feeding_splash_" + j;
				MonoBehaviour[] componentsInChildren = pool[j].GetComponentsInChildren<MonoBehaviour>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren[i]);
				}
				AudioSource[] componentsInChildren2 = pool[j].GetComponentsInChildren<AudioSource>(true);
				for (int i = 0; i < componentsInChildren2.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren2[i]);
				}
				particles[j] = pool[j].GetComponentsInChildren<ParticleSystem>(true);
				ParticleSystem[] array = particles[j];
				foreach (ParticleSystem obj in array)
				{
					obj.Stop(true, (ParticleSystemStopBehavior)0);
					MainModule main = obj.main;
					((MainModule)(ref main)).playOnAwake = false;
					((MainModule)(ref main)).loop = false;
					((MainModule)(ref main)).maxParticles = Mathf.Min(((MainModule)(ref main)).maxParticles, 160);
				}
			}
		}

		internal void Show(Vector3 point, float water, float scale, int count)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00b6: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			if (pool != null && !(Time.time < pulse))
			{
				pulse = Time.time + Mathf.Lerp(0.35f, 0.16f, Mathf.Clamp01((float)count / 30f));
				float num = (float)slot * 2.4f + Time.time;
				point.y = water + 0.01f;
				pool[slot].transform.position = point + new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num)) * 0.18f * scale;
				pool[slot].transform.localScale = Vector3.one * 0.5f * scale;
				ParticleSystem[] array = particles[slot];
				for (int i = 0; i < array.Length; i++)
				{
					array[i].Play(true);
				}
				slot = (slot + 1) % 3;
			}
		}

		internal void Stop()
		{
			if (particles == null)
			{
				return;
			}
			ParticleSystem[][] array = particles;
			foreach (ParticleSystem[] array2 in array)
			{
				foreach (ParticleSystem val in array2)
				{
					if (Object.op_Implicit((Object)(object)val) && val.IsAlive(true))
					{
						val.Stop(true, (ParticleSystemStopBehavior)0);
					}
				}
			}
		}

		private void OnDisable()
		{
			Stop();
		}
	}
	[BepInPlugin("chazman.WaterGardensKoi", "ArcaneDecor:WaterGardens:KoiFish", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "chazman.WaterGardensKoi";

		internal const string FoodName = "WaterGardensKoiPellets";

		internal static Material PelletMaterial;

		internal static ManualLogSource Log;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			harmony = new Harmony("chazman.WaterGardensKoi");
			harmony.PatchAll();
			PrefabManager.OnVanillaPrefabsAvailable += Register;
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Register;
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		private void Register()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Register;
			try
			{
				RegisterFood();
				KoiAssets.Preload();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Pond fish controls and native-toss Koi Food ready.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Koi registration failed: " + ex));
			}
		}

		private void RegisterFood()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_00fe: 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_0135: 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_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			GameObject prefab = PrefabManager.Instance.GetPrefab("Raspberry");
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				throw new InvalidOperationException("Native Raspberry unavailable.");
			}
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("WaterGardensKoiPellets", prefab);
			ItemDrop component = val.GetComponent<ItemDrop>();
			SharedData shared = component.m_itemData.m_shared;
			shared.m_name = "Koi Food";
			shared.m_description = "Round koi pellets. Put in a toolbar slot and use to toss one pile. Place a supply pile with the Water Garden hammer menu, then pick it up.";
			shared.m_itemType = (ItemType)1;
			shared.m_weight = 0.05f;
			shared.m_maxStackSize = 50;
			shared.m_food = (shared.m_foodStamina = (shared.m_foodEitr = 0f));
			shared.m_damages = default(DamageTypes);
			shared.m_useDurability = false;
			shared.m_attack = new Attack();
			shared.m_secondaryAttack = new Attack();
			PelletMaterial = new Material(prefab.GetComponentInChildren<Renderer>(true).sharedMaterial);
			PelletMaterial.mainTexture = (Texture)(object)Texture2D.whiteTexture;
			PelletMaterial.SetColor("_Color", new Color(0.38f, 0.24f, 0.1f));
			ReplaceVisuals(val);
			component.m_autoPickup = false;
			shared.m_icons = (Sprite[])(object)new Sprite[1] { PelletIcon() };
			val.AddComponent<PondFood>();
			ItemConfig val2 = new ItemConfig
			{
				Name = shared.m_name,
				Description = shared.m_description,
				Amount = 10,
				CraftingStation = null
			};
			val2.AddRequirement("Raspberry", 1, 0);
			val2.AddRequirement("Mushroom", 1, 0);
			if (!ItemManager.Instance.AddItem(new CustomItem(val, false, val2)))
			{
				throw new InvalidOperationException("Koi Food registration rejected.");
			}
			RegisterPile(val);
		}

		private void RegisterPile(GameObject food)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: 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)
			//IL_0147: 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_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Expected O, but got Unknown
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Expected O, but got Unknown
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("piece_watergardens_koi_food", "Pickable_Mushroom");
			GameObject val2 = ReplaceVisuals(val);
			Pickable component = val.GetComponent<Pickable>();
			component.m_itemPrefab = food;
			component.m_amount = 10;
			component.m_dontScale = true;
			component.m_respawnTimeMinutes = 0f;
			component.m_hideWhenPicked = val2;
			component.m_overrideName = "Koi Food";
			component.m_spawnOffset = 0.2f;
			component.m_useInteractAnimation = true;
			component.m_extraDrops = new DropTable();
			component.m_harvestable = false;
			component.m_aggravateRange = 0f;
			Piece obj = val.GetComponent<Piece>() ?? val.AddComponent<Piece>();
			obj.m_usage = (UsageTagFlags)0;
			obj.m_groundOnly = false;
			obj.m_groundPiece = false;
			obj.m_noInWater = false;
			obj.m_canBeRemoved = true;
			obj.m_icon = food.GetComponent<ItemDrop>().m_itemData.m_shared.m_icons[0];
			WearNTear obj2 = val.GetComponent<WearNTear>() ?? val.AddComponent<WearNTear>();
			obj2.m_supports = false;
			obj2.m_health = 100f;
			obj2.m_burnable = false;
			obj2.m_new = (obj2.m_worn = (obj2.m_broken = val2));
			obj2.m_autoCreateFragments = false;
			obj2.m_fragmentRoots = Array.Empty<GameObject>();
			obj2.m_noSupportWear = (obj2.m_noRoofWear = false);
			PieceConfig val3 = new PieceConfig
			{
				Name = "Koi Food",
				Description = "A small supply pile of round koi pellets. Pick it up to receive 10 Koi Food, then use a toolbar slot to toss one pile.",
				PieceTable = "Hammer",
				Category = "Water Garden",
				Enabled = true
			};
			val3.AddRequirement("Raspberry", 1, true);
			val3.AddRequirement("Mushroom", 1, true);
			if (!PieceManager.Instance.AddPiece(new CustomPiece(val, false, val3)))
			{
				throw new InvalidOperationException("Hammer Koi Food registration rejected.");
			}
		}

		private static Sprite PelletIcon()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_011d: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			Color[] array = (Color[])(object)new Color[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					bool flag = false;
					Vector2[] array2 = (Vector2[])(object)new Vector2[3]
					{
						new Vector2(23f, 23f),
						new Vector2(42f, 28f),
						new Vector2(29f, 42f)
					};
					foreach (Vector2 val2 in array2)
					{
						Vector2 val3 = new Vector2((float)j, (float)i) - val2;
						if (((Vector2)(ref val3)).sqrMagnitude < 95f)
						{
							flag = true;
						}
					}
					array[i * 64 + j] = (Color)(flag ? new Color(0.65f, 0.43f, 0.18f, 1f) : Color.clear);
				}
			}
			val.SetPixels(array);
			val.Apply();
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
		}

		private static GameObject ReplaceVisuals(GameObject root)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].enabled = false;
			}
			ParticleSystem[] componentsInChildren2 = root.GetComponentsInChildren<ParticleSystem>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			GameObject val = new GameObject("koi_pellets");
			val.transform.SetParent(root.transform, false);
			for (int j = 0; j < 9; j++)
			{
				GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
				((Object)obj).name = "round_pellet";
				obj.transform.SetParent(val.transform, false);
				obj.transform.localScale = Vector3.one * 0.052f;
				obj.transform.localPosition = new Vector3(Mathf.Sin((float)j * 2.4f) * 0.075f, 0.027f + ((j > 5) ? 0.035f : 0f), Mathf.Cos((float)j * 2.4f) * 0.075f);
				Object.DestroyImmediate((Object)(object)obj.GetComponent<Collider>());
				obj.GetComponent<Renderer>().sharedMaterial = PelletMaterial;
			}
			return val;
		}
	}
	[HarmonyPatch(typeof(GardenPiece), "Start")]
	internal static class AttachKoi
	{
		private static void Postfix(GardenPiece __instance)
		{
			if (__instance.Shape >= 0 && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent("RiverGardenSection")) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<KoiSchool>()))
			{
				((Component)__instance).gameObject.AddComponent<KoiSchool>();
			}
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UseItem")]
	internal static class TossKoiFood
	{
		private static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui)
		{
			object obj;
			if (item == null)
			{
				obj = null;
			}
			else
			{
				GameObject dropPrefab = item.m_dropPrefab;
				obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
			}
			if ((string?)obj != "WaterGardensKoiPellets" || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || fromInventoryGui)
			{
				return true;
			}
			inventory = inventory ?? __instance.GetInventory();
			if (inventory == __instance.GetInventory() && inventory.ContainsItem(item) && item.m_stack > 0)
			{
				__instance.DropItem(inventory, item, 1);
			}
			return false;
		}
	}
	internal static class KoiMotion
	{
		internal static Quaternion Turn(Quaternion desired, KoiSchool school, int index)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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)
			return Quaternion.RotateTowards(school.fish[index].rotation, desired, 120f * Mathf.Min(Time.deltaTime, 0.05f));
		}

		internal static Vector3 Direction(Vector3 original, KoiSchool school, int index, Vector3 next)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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)
			Vector3 result = next - school.fish[index].position;
			if (!(((Vector3)(ref result)).sqrMagnitude > 1E-08f))
			{
				return original;
			}
			return result;
		}

		internal static Vector3 Adjust(Vector3 desired, KoiSchool school, int index)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_0025: 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_0151: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: 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_0067: 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_0081: 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_00b2: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: 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)
			Transform[] fish = school.fish;
			if (fish == null || index >= fish.Length || !Object.op_Implicit((Object)(object)fish[index]))
			{
				return desired;
			}
			Vector3 position = fish[index].position;
			Vector3 val = Vector3.zero;
			List<Player> allPlayers = Player.GetAllPlayers();
			for (int i = 0; i < allPlayers.Count; i++)
			{
				Player val2 = allPlayers[i];
				if (!Object.op_Implicit((Object)(object)val2) || ((Character)val2).IsDead())
				{
					continue;
				}
				Vector3 position2 = ((Component)val2).transform.position;
				if (position2.y > school.Water + 0.12f || position2.y < school.Water - school.Depth - 1.8f || !school.Inside(position2))
				{
					continue;
				}
				Vector3 val3 = position - position2;
				val3.y = 0f;
				float magnitude = ((Vector3)(ref val3)).magnitude;
				if (!(magnitude >= 1.6f))
				{
					if (magnitude < 0.025f)
					{
						float num = (float)index * 2.39996f;
						((Vector3)(ref val3))..ctor(Mathf.Cos(num), 0f, Mathf.Sin(num));
					}
					else
					{
						val3 /= magnitude;
					}
					float num2 = 1f - magnitude / 1.6f;
					val += val3 * (1.6f * num2 * num2);
				}
			}
			desired = school.KeepInside(desired + Vector3.ClampMagnitude(val, 1.6f), index);
			desired = Vector3.Lerp(position, desired, 1f - Mathf.Exp(-3f * Mathf.Min(Time.deltaTime, 0.05f)));
			return Vector3.MoveTowards(position, desired, (0.8f + 0.35f * school.Options.Scale) * Mathf.Min(Time.deltaTime, 0.05f));
		}

		internal static double Random(double seed, int index, long step, int channel)
		{
			long num = (long)(seed * 100003.0) ^ ((index + 1) * -7046029254386353131L) ^ (step * -4658895280553007687L) ^ ((channel + 1) * -7723592293110705685L);
			long num2 = (num ^ (num >>> 30)) * -4658895280553007687L;
			long num3 = (num2 ^ (num2 >>> 27)) * -7723592293110705685L;
			return (double)((ulong)(num3 ^ (num3 >>> 31)) >> 11) * 1.1102230246251565E-16;
		}

		internal static void Point(double seed, int index, long step, out double x, out double z)
		{
			double num = Random(seed, index, step, 0) * Math.PI * 2.0;
			double num2 = Math.Sqrt(Random(seed, index, step, 1)) * 0.86;
			x = Math.Cos(num) * num2;
			z = Math.Sin(num) * num2;
		}

		internal static void Wander(int shape, double width, double time, int index, double seed, out double x, out double z)
		{
			double num = 5.0 + Random(seed, index, 0L, 2) * 5.0;
			double num2 = time / num + Random(seed, index, 0L, 3) * 100.0;
			long num3 = (long)Math.Floor(num2);
			num2 -= (double)num3;
			double num4 = 1.0 - num2;
			double num5 = num4 * num4 * num4 / 6.0;
			double num6 = (3.0 * num2 * num2 * num2 - 6.0 * num2 * num2 + 4.0) / 6.0;
			double num7 = (-3.0 * num2 * num2 * num2 + 3.0 * num2 * num2 + 3.0 * num2 + 1.0) / 6.0;
			double num8 = num2 * num2 * num2 / 6.0;
			Point(seed, index, num3 - 1, out var x2, out var z2);
			x = x2 * num5;
			z = z2 * num5;
			Point(seed, index, num3, out x2, out z2);
			x += x2 * num6;
			z += z2 * num6;
			Point(seed, index, num3 + 1, out x2, out z2);
			x += x2 * num7;
			z += z2 * num7;
			Point(seed, index, num3 + 2, out x2, out z2);
			x += x2 * num8;
			z += z2 * num8;
			double num9 = KoiMath.Radius(shape, Math.Atan2(z, x)) * width * 0.5;
			x *= num9;
			z *= num9 * KoiMath.Aspect(shape);
		}

		internal static double SurfaceBlend(double time, int index, double seed)
		{
			double num = 36.0 + Random(seed, 0, 0L, 5) * 12.0;
			double num2 = time / num + Random(seed, 0, 0L, 6) + (double)index * 0.6180339887498949;
			num2 -= Math.Floor(num2);
			double num3 = 1.0 / 3.0;
			double num4 = 2.0 / num;
			if (num2 < num3)
			{
				return 1.0;
			}
			if (num2 < num3 + num4)
			{
				return 1.0 - Smooth((num2 - num3) / num4);
			}
			if (num2 > 1.0 - num4)
			{
				return Smooth((num2 - 1.0 + num4) / num4);
			}
			return 0.0;
		}

		private static double Smooth(double t)
		{
			return t * t * (3.0 - 2.0 * t);
		}
	}
}