Decompiled source of ChillHook v1.0.3

ChillHook.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("Andejx")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Licensed under CC BY 4.0 (creativecommons.org/licenses/by/4.0). Based on work by Azumatt (Hooked) and Lenson (ChillFishing).")]
[assembly: AssemblyDescription("Chill fishing mod with a Stardew-style circle minigame. More fish spawns, all baits work, biome-based rewards, skill-scaling difficulty.")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3")]
[assembly: AssemblyProduct("ChillHook")]
[assembly: AssemblyTitle("ChillHook")]
[assembly: AssemblyVersion("1.0.3.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[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 ChillHook
{
	internal static class V
	{
		internal static readonly FieldInfo FF_m_nview = AccessTools.Field(typeof(FishingFloat), "m_nview");

		internal static readonly MethodInfo FF_GetOwner = AccessTools.Method(typeof(FishingFloat), "GetOwner", (Type[])null, (Type[])null);

		internal static readonly MethodInfo FF_TryToHook = AccessTools.Method(typeof(FishingFloat), "TryToHook", (Type[])null, (Type[])null);

		internal static readonly MethodInfo FF_SetCatch = AccessTools.Method(typeof(FishingFloat), "SetCatch", (Type[])null, (Type[])null);

		internal static readonly MethodInfo FF_Message = AccessTools.Method(typeof(FishingFloat), "Message", (Type[])null, (Type[])null);

		internal static readonly FieldInfo GC_m_mouseCapture = AccessTools.Field(typeof(GameCamera), "m_mouseCapture");

		internal static ZNetView FF_NView(FishingFloat ff)
		{
			object? value = FF_m_nview.GetValue(ff);
			return (ZNetView)((value is ZNetView) ? value : null);
		}

		internal static Character FF_Owner(FishingFloat ff)
		{
			object? obj = FF_GetOwner.Invoke(ff, null);
			return (Character)((obj is Character) ? obj : null);
		}

		internal static void FF_Hook(FishingFloat ff)
		{
			FF_TryToHook.Invoke(ff, null);
		}

		internal static void FF_Catch(FishingFloat ff, Fish fish)
		{
			FF_SetCatch.Invoke(ff, new object[1] { fish });
		}

		internal static void FF_Msg(FishingFloat ff, string msg, bool top)
		{
			FF_Message.Invoke(ff, new object[2] { msg, top });
		}

		internal static void GC_Mouse(GameCamera cam, bool value)
		{
			GC_m_mouseCapture.SetValue(cam, value);
		}
	}
	public static class BiomeUnlock
	{
		private static readonly Dictionary<Biome, string> BossKey = new Dictionary<Biome, string>
		{
			{
				(Biome)8,
				"defeated_gdking"
			},
			{
				(Biome)2,
				"defeated_bonemass"
			},
			{
				(Biome)4,
				"defeated_dragon"
			},
			{
				(Biome)16,
				"defeated_goblinking"
			},
			{
				(Biome)512,
				"defeated_queen"
			},
			{
				(Biome)32,
				"defeated_fader"
			},
			{
				(Biome)64,
				"defeated_fader"
			}
		};

		private static readonly Dictionary<string, Biome> BaitBiome = new Dictionary<string, Biome>
		{
			{
				"FishingBaitForest",
				(Biome)8
			},
			{
				"FishingBaitSwamp",
				(Biome)2
			},
			{
				"FishingBaitCave",
				(Biome)4
			},
			{
				"FishingBaitPlains",
				(Biome)16
			},
			{
				"FishingBaitMistlands",
				(Biome)512
			},
			{
				"FishingBaitAshlands",
				(Biome)32
			},
			{
				"FishingBaitDeepNorth",
				(Biome)64
			},
			{
				"FishingBaitOcean",
				(Biome)256
			}
		};

		private static readonly Biome[] TierOrder;

		private static bool IsAlwaysOn(Biome b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if ((int)b != 1)
			{
				return (int)b == 256;
			}
			return true;
		}

		public static bool IsBiomeUnlocked(Biome biome)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (!ModConfig.RequireBossForOthers.Value)
			{
				return true;
			}
			if (IsAlwaysOn(biome))
			{
				return true;
			}
			if (!BossKey.TryGetValue(biome, out var value))
			{
				return true;
			}
			return BossDefeated(value);
		}

		public static bool IsAvailable(Biome native, Biome local)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.LocalBiomeAlwaysShows.Value && native == local)
			{
				return true;
			}
			return IsBiomeUnlocked(native);
		}

		public static bool BaitFiltersTo(string bait, Biome local)
		{
			//IL_001e: 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)
			if (ModConfig.BiomeBaitFilter.Value && bait != null && BaitBiome.TryGetValue(bait, out var value))
			{
				return value == local;
			}
			return false;
		}

		private static bool BossDefeated(string key)
		{
			if ((Object)(object)ZoneSystem.instance == (Object)null)
			{
				return false;
			}
			return ZoneSystem.instance.GetGlobalKey(key);
		}

		public static int BiomeTier(Biome biome)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between I4 and Unknown
			for (int i = 0; i < TierOrder.Length; i++)
			{
				if ((int)TierOrder[i] == (int)biome)
				{
					return i;
				}
			}
			return 4;
		}

		public static float DifficultyFor(Biome biome, int quality)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)BiomeTier(biome) / (float)(TierOrder.Length - 1);
			float num2 = Mathf.Clamp01((float)(quality - 1) / 4f);
			return Mathf.Clamp01(num * 0.75f + num * num2 * 0.25f);
		}

		static BiomeUnlock()
		{
			Biome[] array = new Biome[9];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			TierOrder = (Biome[])(object)array;
		}
	}
	public sealed class CatchSession
	{
		private const float PreFightDelay = 1f;

		private readonly FishingFloat _float;

		private readonly Fish _fish;

		private readonly Player _player;

		private readonly ItemDrop _drop;

		private readonly float _skill;

		private readonly int _startQuality;

		private readonly MinigameCore _core;

		private readonly float _distanceFactor;

		private readonly bool _lunker;

		private readonly float _staminaPerSecond;

		private bool _finished;

		private float _delayTimer;

		private float _targetX;

		private float _targetY;

		private Vector3 _lastMouse;

		public static CatchSession Active { get; private set; }

		public static bool IsFighting
		{
			get
			{
				if (Active != null && !Active._finished)
				{
					return Active._core != null;
				}
				return false;
			}
		}

		private CatchSession(FishingFloat ff, Fish fish, Player player)
		{
			//IL_0068: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			_float = ff;
			_fish = fish;
			_player = player;
			_drop = ((Component)fish).GetComponent<ItemDrop>();
			_skill = ((Character)player).GetSkillFactor((SkillType)104);
			_startQuality = (((Object)(object)_drop == (Object)null) ? 1 : Mathf.Max(1, _drop.m_itemData.m_quality));
			float num = Vector3.Distance(((Component)player).transform.position, ((Component)ff).transform.position);
			float maxDistance = ff.m_maxDistance;
			_distanceFactor = ((maxDistance > 0f) ? Mathf.Clamp01(num / maxDistance) : 0f);
			float num2 = Mathf.Clamp01(BiomeUnlock.DifficultyFor(FishCatalog.BiomeOf(fish), _startQuality) + _distanceFactor * ModConfig.DistanceBonus.Value);
			_lunker = Rewards.RollLunker(_skill, _distanceFactor);
			_staminaPerSecond = ModConfig.BaseStaminaRate.Value * (1f + num2 * 4.2f) * (1f - _skill * 0.5f);
			_core = (ModConfig.MinigameEnabled.Value ? new MinigameCore(_skill, new SystemRng(), num2) : null);
			Sprite icon = (((Object)(object)_drop != (Object)null) ? _drop.m_itemData.GetIcon() : null);
			if (_core != null)
			{
				_delayTimer = 1f;
				_lastMouse = Input.mousePosition;
				MouseTarget(out _targetX, out _targetY);
				InputCapture.Acquire();
				MinigameHud.Show(_core, icon);
				V.FF_Msg(ff, "Get ready!", top: true);
			}
		}

		public static void Start(FishingFloat ff, Fish fish)
		{
			if (!((Object)(object)fish == (Object)null) && !((Object)(object)ff == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)V.FF_Owner(ff) != (Object)(object)Player.m_localPlayer))
			{
				End();
				Active = new CatchSession(ff, fish, Player.m_localPlayer);
				if (Active._core == null)
				{
					Active.Land(perfect: false, Active._lunker);
				}
			}
		}

		public static void Step(float dt)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_0098: 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_00b7: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			CatchSession active = Active;
			if (active == null || active._finished)
			{
				return;
			}
			if ((Object)(object)active._player == (Object)null || ((Character)active._player).IsDead() || (Object)(object)active._float == (Object)null || (Object)(object)active._fish == (Object)null)
			{
				active.Abandon();
			}
			else
			{
				if (active._core == null)
				{
					return;
				}
				if (active._delayTimer > 0f)
				{
					active._delayTimer -= dt;
					return;
				}
				Vector3 mousePosition = Input.mousePosition;
				Vector3 val = mousePosition - active._lastMouse;
				bool num = ((Vector3)(ref val)).sqrMagnitude > 0.25f;
				active._lastMouse = mousePosition;
				if (num)
				{
					MouseTarget(out active._targetX, out active._targetY);
				}
				else
				{
					Vector2 joyLeftStick = ZInput.GetJoyLeftStick();
					float num2 = ModConfig.GamepadSensitivity.Value * 140f * dt;
					active._targetX = Mathf.Clamp(active._targetX + joyLeftStick.x * num2, -140f, 140f);
					active._targetY = Mathf.Clamp(active._targetY + joyLeftStick.y * num2, -140f, 140f);
				}
				active._core.Step(active._targetX, active._targetY, dt);
				((Character)active._player).UseStamina(active._staminaPerSecond * dt);
				if (!((Character)active._player).HaveStamina(0f))
				{
					active.Escape();
				}
				else if (active._core.Caught)
				{
					active.Land(active._core.PeakProgress >= 1f, active._lunker);
				}
				else if (active._core.Lost)
				{
					active.Escape();
				}
			}
		}

		private static void MouseTarget(out float x, out float y)
		{
			//IL_001f: 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 = ModConfig.MouseSensitivity.Value * 140f / ((float)Screen.width * 0.5f);
			x = Mathf.Clamp((Input.mousePosition.x - (float)Screen.width * 0.5f) * num, -140f, 140f);
			y = Mathf.Clamp((Input.mousePosition.y - (float)Screen.height * 0.5f) * num, -140f, 140f);
		}

		private void Land(bool perfect, bool lunker)
		{
			//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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (!_finished)
			{
				_finished = true;
				int num = _startQuality;
				if (perfect)
				{
					num++;
				}
				if ((Object)(object)_drop != (Object)null)
				{
					int num2 = Mathf.Max(1, _drop.m_itemData.m_shared.m_maxQuality);
					num = Mathf.Clamp(num, 1, num2);
				}
				DropFish(num, lunker);
				Biome biome = Waters.Biome(((Component)_float).transform.position);
				string suffix = Rewards.GiveCatch(_player, biome, _skill, perfect, lunker, num, _distanceFactor);
				Message("Catch!", suffix);
				Cleanup();
			}
		}

		private void Escape()
		{
			if (!_finished)
			{
				_finished = true;
				Rewards.GiveLoss(_player, _skill, (_core != null) ? _core.PeakProgress : 0f, _distanceFactor);
				Message("The fish got away.", "");
				Cleanup();
			}
		}

		private void Abandon()
		{
			if (!_finished)
			{
				_finished = true;
				Cleanup();
			}
		}

		private void DropFish(int quality, bool lunker)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_0085: 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_008c: 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)
			if ((Object)(object)_fish == (Object)null)
			{
				return;
			}
			string prefabName = Utils.GetPrefabName(((Component)_fish).gameObject);
			GameObject val = null;
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				val = ObjectDB.instance.GetItemPrefab(prefabName);
			}
			if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				val = ZNetScene.instance.GetPrefab(prefabName);
			}
			if ((Object)(object)val != (Object)null)
			{
				Vector3 val2 = ((Component)_player).transform.position + Vector3.up * 0.5f;
				ItemDrop component = Object.Instantiate<GameObject>(val, val2, Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f)).GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null)
				{
					component.SetQuality(quality);
					component.SetStack(1);
				}
			}
		}

		private void Message(string text, string suffix)
		{
			if (!((Object)(object)_float == (Object)null))
			{
				V.FF_Msg(_float, text + suffix, top: true);
			}
		}

		private void Cleanup()
		{
			InputCapture.Release();
			MinigameHud.Hide();
			if ((Object)(object)_float != (Object)null)
			{
				V.FF_Catch(_float, null);
				ZNetView val = V.FF_NView(_float);
				if ((Object)(object)val != (Object)null && val.IsValid())
				{
					val.Destroy();
				}
			}
			if ((Object)(object)_fish != (Object)null)
			{
				_fish.OnHooked((FishingFloat)null);
			}
			if (Active == this)
			{
				Active = null;
			}
		}

		public static void End()
		{
			CatchSession active = Active;
			if (active == null)
			{
				return;
			}
			active._finished = true;
			InputCapture.Release();
			MinigameHud.Hide();
			if ((Object)(object)active._float != (Object)null)
			{
				ZNetView val = V.FF_NView(active._float);
				if ((Object)(object)val != (Object)null && val.IsValid())
				{
					val.Destroy();
				}
			}
			Active = null;
		}
	}
	public sealed class FishEntry
	{
		public GameObject Prefab;

		public Biome NativeBiome;

		public float Weight;
	}
	public static class FishCatalog
	{
		private static readonly Dictionary<GameObject, Biome> Native = new Dictionary<GameObject, Biome>();

		private static readonly HashSet<GameObject> Seen = new HashSet<GameObject>();

		private static readonly Dictionary<Biome, float> BiomeWeight = new Dictionary<Biome, float>
		{
			{
				(Biome)1,
				10f
			},
			{
				(Biome)256,
				9f
			},
			{
				(Biome)8,
				6.5f
			},
			{
				(Biome)2,
				5f
			},
			{
				(Biome)4,
				7.6f
			},
			{
				(Biome)16,
				5.6f
			},
			{
				(Biome)512,
				3.2f
			},
			{
				(Biome)32,
				1.8f
			},
			{
				(Biome)64,
				1f
			}
		};

		private const float UnclassifiedWeight = 2.4f;

		public static void Register(SpawnSystem spawnSystem)
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)spawnSystem == (Object)null || spawnSystem.m_spawnLists == null)
			{
				return;
			}
			foreach (SpawnSystemList spawnList in spawnSystem.m_spawnLists)
			{
				if ((Object)(object)spawnList == (Object)null || spawnList.m_spawners == null)
				{
					continue;
				}
				foreach (SpawnData spawner in spawnList.m_spawners)
				{
					if (spawner != null && !((Object)(object)spawner.m_prefab == (Object)null) && !((Object)(object)spawner.m_prefab.GetComponent<Fish>() == (Object)null) && !Seen.Contains(spawner.m_prefab))
					{
						Seen.Add(spawner.m_prefab);
						Native[spawner.m_prefab] = FirstBiome(spawner.m_biome);
					}
				}
			}
		}

		public static void RegisterExtra(ZNetScene scene)
		{
			if ((Object)(object)scene == (Object)null)
			{
				return;
			}
			foreach (string prefabName in scene.GetPrefabNames())
			{
				GameObject prefab = scene.GetPrefab(prefabName);
				if (!((Object)(object)prefab == (Object)null) && !((Object)(object)prefab.GetComponent<Fish>() == (Object)null) && !Native.ContainsKey(prefab))
				{
					Native[prefab] = (Biome)0;
				}
			}
		}

		public static List<FishEntry> Candidates(Biome local, string bait)
		{
			//IL_0001: 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_0044: 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_0056: 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_006a: 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)
			bool flag = BiomeUnlock.BaitFiltersTo(bait, local);
			List<FishEntry> list = new List<FishEntry>();
			foreach (KeyValuePair<GameObject, Biome> item in Native)
			{
				if (!((Object)(object)item.Key == (Object)null) && (!flag || item.Value == local))
				{
					float value;
					if ((int)item.Value == 0)
					{
						value = 2.4f;
					}
					else if (!BiomeUnlock.IsAvailable(item.Value, local) || !BiomeWeight.TryGetValue(item.Value, out value))
					{
						continue;
					}
					if (value > 0f)
					{
						list.Add(new FishEntry
						{
							Prefab = item.Key,
							NativeBiome = item.Value,
							Weight = value
						});
					}
				}
			}
			ApplyLocalShare(list, local);
			return list;
		}

		private static void ApplyLocalShare(List<FishEntry> pool, Biome local)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!ModConfig.BiomeWeights.Value)
			{
				return;
			}
			float num = 0f;
			float num2 = 0f;
			foreach (FishEntry item in pool)
			{
				if (item.NativeBiome == local)
				{
					num += item.Weight;
				}
				else
				{
					num2 += item.Weight;
				}
			}
			if (num <= 0f || num2 <= 0f)
			{
				return;
			}
			float num3 = Mathf.Clamp01(ModConfig.LocalBiomeShare.Value);
			float num4 = num + num2;
			float num5 = num3 * num4 / num;
			float num6 = (1f - num3) * num4 / num2;
			foreach (FishEntry item2 in pool)
			{
				item2.Weight *= ((item2.NativeBiome == local) ? num5 : num6);
			}
			pool.RemoveAll((FishEntry e) => e.Weight <= 0f);
		}

		public static FishEntry Pick(List<FishEntry> pool)
		{
			if (pool == null || pool.Count == 0)
			{
				return null;
			}
			float num = 0f;
			foreach (FishEntry item in pool)
			{
				num += item.Weight;
			}
			if (num <= 0f)
			{
				return null;
			}
			float num2 = Random.Range(0f, num);
			float num3 = 0f;
			foreach (FishEntry item2 in pool)
			{
				num3 += item2.Weight;
				if (num2 <= num3)
				{
					return item2;
				}
			}
			return pool[pool.Count - 1];
		}

		public static Biome BiomeOf(Fish fish)
		{
			//IL_0051: 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)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)fish == (Object)null))
			{
				string prefabName = Utils.GetPrefabName(((Component)fish).gameObject);
				foreach (KeyValuePair<GameObject, Biome> item in Native)
				{
					if ((Object)(object)item.Key != (Object)null && ((Object)item.Key).name == prefabName)
					{
						return item.Value;
					}
				}
				return (Biome)1;
			}
			return (Biome)1;
		}

		private static Biome FirstBiome(Biome mask)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Biome[] array = new Biome[9];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			Biome[] array2 = (Biome[])(object)array;
			foreach (Biome val in array2)
			{
				if ((mask & val) != 0)
				{
					return val;
				}
			}
			return (Biome)1;
		}
	}
	public static class FishSpawner
	{
		private static readonly Dictionary<Fish, float> Spawned = new Dictionary<Fish, float>();

		private static float _timer;

		public static void Tick(float dt)
		{
			if (!ModConfig.FishComeToYou.Value)
			{
				return;
			}
			_timer += dt;
			float value = ModConfig.SpawnTickSeconds.Value;
			if (_timer < value)
			{
				return;
			}
			_timer = 0f;
			Prune();
			List<FishingFloat> list = ActiveFloats();
			if (list.Count == 0)
			{
				return;
			}
			RefreshIdle(list, ModConfig.SpawnRadius.Value);
			foreach (FishingFloat item in list)
			{
				TopUp(item);
			}
		}

		public static void Clear()
		{
			Spawned.Clear();
		}

		private static List<FishingFloat> ActiveFloats()
		{
			List<FishingFloat> list = new List<FishingFloat>();
			foreach (FishingFloat allInstance in FishingFloat.GetAllInstances())
			{
				if (!((Object)(object)allInstance == (Object)null))
				{
					ZNetView component = ((Component)allInstance).GetComponent<ZNetView>();
					if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner() && allInstance.IsInWater() && !((Object)(object)allInstance.GetCatch() != (Object)null))
					{
						list.Add(allInstance);
					}
				}
			}
			return list;
		}

		private static void Prune()
		{
			List<Fish> list = null;
			foreach (Fish key in Spawned.Keys)
			{
				if ((Object)(object)key == (Object)null)
				{
					(list ?? (list = new List<Fish>())).Add(key);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (Fish item in list)
			{
				Spawned.Remove(item);
			}
		}

		private static void RefreshIdle(List<FishingFloat> floats, float radius)
		{
			//IL_004d: 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)
			Fish[] array = (Fish[])(object)new Fish[Spawned.Count];
			Spawned.Keys.CopyTo(array, 0);
			Fish[] array2 = array;
			foreach (Fish val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				foreach (FishingFloat @float in floats)
				{
					if (Vector3.Distance(((Component)val).transform.position, ((Component)@float).transform.position) <= radius)
					{
						Spawned[val] = Time.time;
						break;
					}
				}
			}
		}

		private static void TopUp(FishingFloat ff)
		{
			//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_0017: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0052: 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_005e: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)ff).transform.position;
			float value = ModConfig.SpawnRadius.Value;
			if (CountNear(position, value) >= ModConfig.TargetFishNearby.Value)
			{
				return;
			}
			FishEntry fishEntry = FishCatalog.Pick(FishCatalog.Candidates(Waters.Biome(position), ff.GetBait()));
			if (fishEntry != null)
			{
				Vector2 val = Random.insideUnitCircle * value;
				Vector3 val2 = position + new Vector3(val.x, 0f, val.y);
				Fish component = Object.Instantiate<GameObject>(fishEntry.Prefab, val2, Quaternion.identity).GetComponent<Fish>();
				if ((Object)(object)component != (Object)null)
				{
					Spawned[component] = Time.time;
				}
			}
		}

		private static int CountNear(Vector3 center, float radius)
		{
			//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)
			int num = 0;
			foreach (Fish key in Spawned.Keys)
			{
				if ((Object)(object)key != (Object)null && Vector3.Distance(((Component)key).transform.position, center) <= radius)
				{
					num++;
				}
			}
			return num;
		}
	}
	internal static class InputCapture
	{
		private static int _blocks;

		private static bool _restorePending;

		public static bool IsBlocked => _blocks > 0;

		public static void Acquire()
		{
			_blocks++;
			if (_blocks == 1)
			{
				Cursor.lockState = (CursorLockMode)2;
				Cursor.visible = false;
				if ((Object)(object)GameCamera.instance != (Object)null)
				{
					V.GC_Mouse(GameCamera.instance, value: false);
				}
			}
		}

		public static void Release()
		{
			_blocks = Mathf.Max(0, _blocks - 1);
			if (_blocks == 0)
			{
				_restorePending = true;
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
				if ((Object)(object)GameCamera.instance != (Object)null)
				{
					V.GC_Mouse(GameCamera.instance, value: true);
				}
			}
		}

		public static void Reset()
		{
			_blocks = 0;
			_restorePending = true;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}

		public static void Tick()
		{
			if (IsBlocked)
			{
				if ((Object)(object)GameCamera.instance != (Object)null)
				{
					V.GC_Mouse(GameCamera.instance, value: false);
				}
			}
			else if (_restorePending)
			{
				_restorePending = false;
				if ((Object)(object)GameCamera.instance != (Object)null)
				{
					V.GC_Mouse(GameCamera.instance, value: true);
				}
			}
		}

		public static void BlockPlayerInput(ref bool result)
		{
			if (IsBlocked)
			{
				result = false;
			}
		}
	}
	public interface IRng
	{
		float Value();

		float Range(float lo, float hi);
	}
	public sealed class SystemRng : IRng
	{
		private readonly Random _r;

		public SystemRng()
			: this(Environment.TickCount)
		{
		}

		public SystemRng(int seed)
		{
			_r = new Random(seed);
		}

		public float Value()
		{
			return (float)_r.NextDouble();
		}

		public float Range(float lo, float hi)
		{
			return lo + (float)_r.NextDouble() * (hi - lo);
		}
	}
	public static class SkillCurve
	{
		public const float OuterRadius = 140f;

		public const float MouseFollow = 3f;

		public const float CentreBase = 50f;

		public const float CentreSkillBonus = 66f;

		public const float DriftBase = 100f;

		public const float DriftSkillReduction = 1f;

		public const float FillBase = 0.13f;

		public const float FillSkillBonus = 2f;

		public const float DrainBase = 0.1f;

		public const float DrainSkillReduction = 0.9f;

		public static float CentreRadius(float skill)
		{
			return 50f + 66f * Clamp01(skill);
		}

		public static float DriftSpeed(float skill)
		{
			return 100f * (1f - 1f * Clamp01(skill));
		}

		public static float FillRate(float skill)
		{
			return 0.13f * (1f + 2f * Clamp01(skill));
		}

		public static float DrainRate(float skill)
		{
			return 0.1f * (1f - 0.9f * Clamp01(skill));
		}

		private static float Clamp01(float v)
		{
			if (!(v < 0f))
			{
				if (!(v > 1f))
				{
					return v;
				}
				return 1f;
			}
			return 0f;
		}
	}
	public sealed class MinigameCore
	{
		public const float DriftTurnSeconds = 1.1f;

		public float CentreRadius;

		public float DriftSpeed;

		public float FillRate;

		public float DrainRate;

		public const float StartProgress = 0.2f;

		public float DotX;

		public float DotY;

		public float Progress;

		public float PeakProgress;

		private readonly IRng _rng;

		private float _driftAngle;

		private float _driftTargetAngle;

		private float _driftTimer;

		private bool _lost;

		public bool InCentre => DistToCentre <= CentreRadius;

		public float DistToCentre => (float)Math.Sqrt(DotX * DotX + DotY * DotY);

		public bool Caught => Progress >= 1f;

		public bool Lost => _lost;

		public MinigameCore(float skill, IRng rng = null, float fishDifficulty = 0f)
		{
			_rng = rng ?? new SystemRng();
			Progress = 0.2f;
			CentreRadius = SkillCurve.CentreRadius(skill);
			DriftSpeed = SkillCurve.DriftSpeed(skill);
			FillRate = SkillCurve.FillRate(skill);
			DrainRate = SkillCurve.DrainRate(skill);
			float num = ((fishDifficulty < 0f) ? 0f : ((fishDifficulty > 1f) ? 1f : fishDifficulty));
			CentreRadius *= 1f - num * 0.4f;
			DriftSpeed *= 1f + num * 2f;
			FillRate /= 1f + num * 1.5f;
			DrainRate *= 1f + num * 2f;
			_driftAngle = _rng.Range(0f, (float)Math.PI * 2f);
			_driftTargetAngle = _driftAngle;
			_driftTimer = 1.1f;
		}

		public void Step(float targetX, float targetY, float dt)
		{
			if (!(dt <= 0f) && !Caught && !_lost)
			{
				_driftTimer -= dt;
				if (_driftTimer <= 0f)
				{
					_driftTimer = 1.1f;
					_driftTargetAngle = _rng.Range(0f, (float)Math.PI * 2f);
				}
				_driftAngle = ApproachAngle(_driftAngle, _driftTargetAngle, dt * 2.2f);
				DotX += (targetX - DotX) * 3f * dt;
				DotY += (targetY - DotY) * 3f * dt;
				DotX += (float)Math.Cos(_driftAngle) * DriftSpeed * dt;
				DotY += (float)Math.Sin(_driftAngle) * DriftSpeed * dt;
				float distToCentre = DistToCentre;
				if (distToCentre > 140f && distToCentre > 0f)
				{
					float num = 140f / distToCentre;
					DotX *= num;
					DotY *= num;
				}
				Progress += (InCentre ? FillRate : (0f - DrainRate)) * dt;
				if (Progress < 0f)
				{
					Progress = 0f;
				}
				if (Progress > 1f)
				{
					Progress = 1f;
				}
				if (Progress > PeakProgress)
				{
					PeakProgress = Progress;
				}
				if (Progress <= 0f)
				{
					_lost = true;
				}
			}
		}

		private static float ApproachAngle(float from, float to, float t)
		{
			float num = (float)Math.PI * 2f;
			float num2 = to - from;
			while ((double)num2 > Math.PI)
			{
				num2 -= num;
			}
			for (; (double)num2 < -Math.PI; num2 += num)
			{
			}
			float num3 = num2 * ((t > 1f) ? 1f : t);
			return from + num3;
		}
	}
	public sealed class MinigameHud : MonoBehaviour
	{
		private static MinigameHud _instance;

		private static MinigameCore _core;

		private static Sprite _fishIcon;

		private const float OuterRadiusPx = 100f;

		private const int DiscTexSize = 128;

		private const float DiscSoftEdge = 3f;

		private const float Margin = 32f;

		private const float Pad = 14f;

		private const float BorderW = 3f;

		private const float BarGap = 12f;

		private const float BarHeight = 20f;

		private const float TextGap = 8f;

		private const float HintHeight = 24f;

		private const float FishIconSize = 36f;

		private const float FishShadowOffset = 2f;

		private static readonly Color PanelFill = new Color(0.1f, 0.07f, 0.04f, 0.85f);

		private static readonly Color PanelBorder = new Color(0.38f, 0.28f, 0.18f, 0.95f);

		private static readonly Color PanelHighlight = new Color(0.22f, 0.16f, 0.1f, 0.6f);

		private static readonly Color PondFill = new Color(0.05f, 0.09f, 0.12f, 0.9f);

		private static readonly Color PondRim = new Color(0.42f, 0.33f, 0.22f, 0.95f);

		private static readonly Color RippleColor = new Color(0.15f, 0.25f, 0.3f, 0.3f);

		private static readonly Color NetSafe = new Color(0.25f, 0.55f, 0.22f, 0.4f);

		private static readonly Color NetDanger = new Color(0.6f, 0.38f, 0.12f, 0.4f);

		private static readonly Color NetRope = new Color(0.5f, 0.38f, 0.22f, 0.65f);

		private static readonly Color NetGrid = new Color(0.4f, 0.3f, 0.18f, 0.3f);

		private static readonly Color FishShadow = new Color(0f, 0f, 0f, 0.4f);

		private static readonly Color BarBack = new Color(0.06f, 0.05f, 0.03f, 0.92f);

		private static readonly Color BarFill = new Color(0.4f, 0.58f, 0.25f, 1f);

		private static readonly Color BarFillFull = new Color(0.55f, 0.78f, 0.32f, 1f);

		private static readonly Color BarBorder = new Color(0.3f, 0.22f, 0.14f, 0.8f);

		private static readonly Color TextNormal = new Color(0.88f, 0.82f, 0.7f, 1f);

		private static readonly Color TextCaught = new Color(0.5f, 0.88f, 0.4f, 1f);

		private static Texture2D _solid;

		private static Texture2D _disc;

		private static float _discBakedDiameter = -1f;

		private GUIStyle _barStyle;

		private GUIStyle _hintStyle;

		private static string[] _catchLabels;

		public static void Show(MinigameCore core, Sprite icon = null)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if ((Object)(object)_instance == (Object)null)
			{
				GameObject val = new GameObject("ChillHook_MinigameHud");
				Object.DontDestroyOnLoad((Object)val);
				_instance = val.AddComponent<MinigameHud>();
			}
			_core = core;
			_fishIcon = icon;
			if (!((Component)_instance).gameObject.activeSelf)
			{
				((Component)_instance).gameObject.SetActive(true);
			}
		}

		public static void Hide()
		{
			_core = null;
			_fishIcon = null;
			if ((Object)(object)_instance != (Object)null && ((Component)_instance).gameObject.activeSelf)
			{
				((Component)_instance).gameObject.SetActive(false);
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_instance == (Object)(object)this)
			{
				_instance = null;
			}
			_core = null;
			_fishIcon = null;
			ReleaseTextures();
		}

		private void OnGUI()
		{
			//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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: 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_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: 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_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: 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_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0348: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			MinigameCore core = _core;
			if (core != null)
			{
				if (_barStyle == null)
				{
					BuildStyles();
				}
				EnsureTextures(200f);
				float num = 0.71428573f;
				float num2 = 200f;
				float num3 = num2 + 34f;
				float num4 = 298f;
				float num5 = (float)Screen.width - 32f - num3;
				float num6 = ((float)Screen.height - num4) / 2f;
				num5 = Mathf.Clamp(num5, 32f, Mathf.Max(32f, (float)Screen.width - 32f - num3));
				num6 = Mathf.Clamp(num6, 32f, Mathf.Max(32f, (float)Screen.height - 32f - num4));
				float num7 = num5 + num3 * 0.5f;
				float num8 = num6 + 14f + 3f + 100f;
				FillRect(new Rect(num5, num6, num3, num4), PanelBorder);
				FillRect(new Rect(num5 + 3f, num6 + 3f, num3 - 6f, num4 - 6f), PanelFill);
				FillRect(new Rect(num5 + 3f, num6 + 3f, num3 - 6f, 2f), PanelHighlight);
				DrawDisc(num7, num8, 100f, PondRim);
				DrawDisc(num7, num8, 97f, PondFill);
				float[] array = new float[3] { 0.25f, 0.5f, 0.75f };
				foreach (float num9 in array)
				{
					float radius = 100f * num9;
					DrawRing(num7, num8, radius, RippleColor, 1.5f);
				}
				float radius2 = Mathf.Clamp(core.CentreRadius * num, 0f, 97f);
				DrawDisc(num7, num8, radius2, core.InCentre ? NetSafe : NetDanger);
				DrawNetGrid(num7, num8, radius2, NetGrid);
				DrawRing(num7, num8, radius2, NetRope, 2.5f);
				float cx = num7 + core.DotX * num;
				float cy = num8 - core.DotY * num;
				DrawFish(cx, cy, core);
				float num10 = num5 + 14f + 3f;
				float num11 = num8 + 100f + 3f + 12f;
				Rect val = new Rect(num10, num11, num2, 20f);
				FillRect(new Rect(num10 - 1f, num11 - 1f, num2 + 2f, 22f), BarBorder);
				FillRect(val, BarBack);
				float num12 = Mathf.Clamp01(core.Progress);
				if (num12 > 0f)
				{
					FillRect(new Rect(num10, num11, num2 * num12, 20f), core.Caught ? BarFillFull : BarFill);
				}
				GUI.color = TextNormal;
				GUI.Label(val, CatchLabel(num12), _barStyle);
				GUI.color = Color.white;
				bool caught = core.Caught;
				Rect val2 = new Rect(num5 + 14f, num11 + 20f + 8f, num2 + 6f, 24f);
				_hintStyle.fontStyle = (FontStyle)(caught ? 1 : 0);
				GUI.color = (caught ? TextCaught : TextNormal);
				GUI.Label(val2, caught ? "Caught!" : "Keep the fish in the net", _hintStyle);
				GUI.color = Color.white;
			}
		}

		private void DrawFish(float cx, float cy, MinigameCore core)
		{
			//IL_0027: 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_00ad: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(core.DotX, core.DotY);
			float angle = 0f;
			if (((Vector2)(ref val)).sqrMagnitude > 0.01f)
			{
				angle = Mathf.Atan2(0f - val.y, val.x) * 57.29578f;
			}
			if ((Object)(object)_fishIcon != (Object)null && (Object)(object)_fishIcon.texture != (Object)null)
			{
				DrawSprite(cx + 2f, cy + 2f, _fishIcon, 36f, angle, FishShadow);
				DrawSprite(cx, cy, _fishIcon, 36f, angle, Color.white);
			}
			else
			{
				DrawDisc(cx + 2f, cy + 2f, 14.400001f, FishShadow);
				DrawDisc(cx, cy, 16.199999f, new Color(0.15f, 0.12f, 0.08f, 0.95f));
				DrawDisc(cx, cy, 12.599999f, new Color(0.85f, 0.72f, 0.35f, 1f));
			}
		}

		private static void DrawSprite(float cx, float cy, Sprite sprite, float size, float angle, Color tint)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_00c5: 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)
			if (!((Object)(object)sprite == (Object)null) && !((Object)(object)sprite.texture == (Object)null))
			{
				Rect textureRect = sprite.textureRect;
				float num = ((Rect)(ref textureRect)).width / ((Rect)(ref textureRect)).height;
				float num2 = size / num;
				Color color = GUI.color;
				GUI.color = tint;
				GUIUtility.RotateAroundPivot(angle, new Vector2(cx, cy));
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((Rect)(ref textureRect)).x / (float)((Texture)sprite.texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)sprite.texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)sprite.texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)sprite.texture).height);
				GUI.DrawTextureWithTexCoords(new Rect(cx - size * 0.5f, cy - num2 * 0.5f, size, num2), (Texture)(object)sprite.texture, val, true);
				GUIUtility.RotateAroundPivot(0f - angle, new Vector2(cx, cy));
				GUI.color = color;
			}
		}

		private static void DrawNetGrid(float cx, float cy, float radius, Color color)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			if (!(radius < 8f))
			{
				float num = 1.5f;
				float num2 = 14f;
				for (float num3 = 0f - radius; num3 <= radius; num3 += num2)
				{
					float num4 = Mathf.Sqrt(Mathf.Max(0f, radius * radius - num3 * num3));
					FillRect(new Rect(cx - num4, cy + num3 - num * 0.5f, num4 * 2f, num), color);
				}
				for (float num5 = 0f - radius; num5 <= radius; num5 += num2)
				{
					float num6 = Mathf.Sqrt(Mathf.Max(0f, radius * radius - num5 * num5));
					FillRect(new Rect(cx + num5 - num * 0.5f, cy - num6, num, num6 * 2f), color);
				}
			}
		}

		private static void DrawRing(float cx, float cy, float radius, Color color, float thickness)
		{
			//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_0028: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			if (!(radius < 2f))
			{
				Color color2 = GUI.color;
				GUI.color = color;
				GUI.DrawTexture(new Rect(cx - radius, cy - radius, radius * 2f, radius * 2f), (Texture)(object)_disc);
				GUI.color = PondFill;
				float num = Mathf.Max(0f, radius - thickness);
				GUI.DrawTexture(new Rect(cx - num, cy - num, num * 2f, num * 2f), (Texture)(object)_disc);
				GUI.color = color2;
			}
		}

		private void BuildStyles()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			_barStyle = new GUIStyle(GUI.skin.label);
			_barStyle.alignment = (TextAnchor)4;
			_barStyle.fontSize = 13;
			_barStyle.fontStyle = (FontStyle)1;
			_barStyle.normal.textColor = Color.white;
			_hintStyle = new GUIStyle(GUI.skin.label);
			_hintStyle.alignment = (TextAnchor)4;
			_hintStyle.fontSize = 14;
			_hintStyle.normal.textColor = Color.white;
		}

		private static string CatchLabel(float progress01)
		{
			if (_catchLabels == null)
			{
				_catchLabels = new string[101];
				for (int i = 0; i <= 100; i++)
				{
					_catchLabels[i] = "Catch " + i + "%";
				}
			}
			int num = Mathf.Clamp(Mathf.RoundToInt(progress01 * 100f), 0, 100);
			return _catchLabels[num];
		}

		private static void FillRect(Rect rect, Color color)
		{
			//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_000b: Unknown result type (might be due to invalid IL or missing references)
			Color color2 = GUI.color;
			GUI.color = color;
			GUI.DrawTexture(rect, (Texture)(object)_solid);
			GUI.color = color2;
		}

		private static void DrawDisc(float cx, float cy, float radius, Color color)
		{
			//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_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!(radius <= 0.5f))
			{
				Color color2 = GUI.color;
				GUI.color = color;
				GUI.DrawTexture(new Rect(cx - radius, cy - radius, radius * 2f, radius * 2f), (Texture)(object)_disc);
				GUI.color = color2;
			}
		}

		private static void EnsureTextures(float onScreenDiameter)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_solid == (Object)null)
			{
				_solid = new Texture2D(1, 1, (TextureFormat)4, false);
				_solid.SetPixel(0, 0, Color.white);
				_solid.Apply(false, true);
				((Object)_solid).hideFlags = (HideFlags)61;
			}
			if ((Object)(object)_disc != (Object)null && Mathf.Abs(_discBakedDiameter - onScreenDiameter) <= 8f)
			{
				return;
			}
			if ((Object)(object)_disc != (Object)null)
			{
				Object.Destroy((Object)(object)_disc);
			}
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false);
			float num = 64f;
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num2 = (float)j + 0.5f - num;
					float num3 = (float)i + 0.5f - num;
					float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
					float num5 = Mathf.Clamp01((num - num4) / 3f);
					val.SetPixel(j, i, new Color(1f, 1f, 1f, num5));
				}
			}
			val.Apply(false, true);
			((Object)val).hideFlags = (HideFlags)61;
			_disc = val;
			_discBakedDiameter = onScreenDiameter;
		}

		private static void ReleaseTextures()
		{
			if ((Object)(object)_disc != (Object)null)
			{
				Object.Destroy((Object)(object)_disc);
				_disc = null;
			}
			if ((Object)(object)_solid != (Object)null)
			{
				Object.Destroy((Object)(object)_solid);
				_solid = null;
			}
			_discBakedDiameter = -1f;
		}
	}
	public struct MinigameTuning
	{
		public float CentreRadius;

		public float DriftSpeed;

		public float FillRate;

		public float DrainRate;

		public static MinigameTuning ForSkill(float skill)
		{
			return new MinigameTuning
			{
				CentreRadius = SkillCurve.CentreRadius(skill),
				DriftSpeed = SkillCurve.DriftSpeed(skill),
				FillRate = SkillCurve.FillRate(skill),
				DrainRate = SkillCurve.DrainRate(skill)
			};
		}
	}
	public static class ModConfig
	{
		public static ConfigEntry<bool> MinigameEnabled;

		public static ConfigEntry<float> SkillEase;

		public static ConfigEntry<float> MouseSensitivity;

		public static ConfigEntry<float> GamepadSensitivity;

		public static ConfigEntry<bool> AutoHook;

		public static ConfigEntry<bool> AllBaitsWork;

		public static ConfigEntry<bool> BiomeBaitFilter;

		public static ConfigEntry<bool> BaitConsumedOnHook;

		public static ConfigEntry<bool> FishComeToYou;

		public static ConfigEntry<int> TargetFishNearby;

		public static ConfigEntry<float> SpawnTickSeconds;

		public static ConfigEntry<float> SpawnRadius;

		public static ConfigEntry<bool> LocalBiomeAlwaysShows;

		public static ConfigEntry<bool> RequireBossForOthers;

		public static ConfigEntry<bool> BiomeWeights;

		public static ConfigEntry<float> LocalBiomeShare;

		public static ConfigEntry<float> BaseTreasureChance;

		public static ConfigEntry<float> BaseLunkerChance;

		public static ConfigEntry<float> SkillRewardBonus;

		public static ConfigEntry<float> SkillXpMultiplier;

		public static ConfigEntry<float> DistanceBonus;

		public static ConfigEntry<float> BaseStaminaRate;

		public static ConfigEntry<string> TreasureLoot;

		public static void Bind(ConfigFile cfg)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Expected O, but got Unknown
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Expected O, but got Unknown
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected O, but got Unknown
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Expected O, but got Unknown
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Expected O, but got Unknown
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Expected O, but got Unknown
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Expected O, but got Unknown
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Expected O, but got Unknown
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Expected O, but got Unknown
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Expected O, but got Unknown
			MinigameEnabled = cfg.Bind<bool>("1 - Fight", "Minigame Enabled", true, "Use the circle-and-dot catch minigame. Off falls back to instantly landing the fish.");
			SkillEase = cfg.Bind<float>("1 - Fight", "Skill Eases Fight", 0.85f, new ConfigDescription("How much Fishing skill relaxes the fight (0 = none, 1 = fully automatic at level 100).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			MouseSensitivity = cfg.Bind<float>("1 - Fight", "Mouse Sensitivity", 1f, new ConfigDescription("How far the dot moves per pixel of mouse movement.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
			GamepadSensitivity = cfg.Bind<float>("1 - Fight", "Gamepad Sensitivity", 2f, new ConfigDescription("How fast the left stick steers the dot (outer-circle radii per second at full tilt).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 5f), Array.Empty<object>()));
			AutoHook = cfg.Bind<bool>("2 - Hooking", "Auto Hook", true, "Hook the fish the instant it bites (no need to click at the right moment).");
			AllBaitsWork = cfg.Bind<bool>("2 - Hooking", "All Baits Work", true, "Every bait catches every fish.");
			BiomeBaitFilter = cfg.Bind<bool>("2 - Hooking", "Biome Bait Filter", false, "A biome's own bait (e.g. Ashlands bait while fishing in Ashlands) limits bites to that biome's fish. Regular bait never limits, and bait for some other biome behaves as usual.");
			BaitConsumedOnHook = cfg.Bind<bool>("2 - Hooking", "Bait Used On Hook", true, "Consume one bait whenever a fish is hooked, whether or not you land it.");
			FishComeToYou = cfg.Bind<bool>("3 - Fish Nearby", "Fish Come To You", true, "Keep fish swimming near your float so there is always something to catch.");
			TargetFishNearby = cfg.Bind<int>("3 - Fish Nearby", "Target Fish Nearby", 4, new ConfigDescription("How many fish to keep around one float.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), Array.Empty<object>()));
			SpawnTickSeconds = cfg.Bind<float>("3 - Fish Nearby", "Spawn Check Seconds", 2f, new ConfigDescription("How often to check and top up nearby fish.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 30f), Array.Empty<object>()));
			SpawnRadius = cfg.Bind<float>("3 - Fish Nearby", "Spawn Radius", 10f, new ConfigDescription("Radius (metres) around the float where fish gather.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 40f), Array.Empty<object>()));
			LocalBiomeAlwaysShows = cfg.Bind<bool>("4 - Species", "Local Biome Always Shows", true, "The biome you are standing in always shows its own fish, even before its boss is beaten.");
			RequireBossForOthers = cfg.Bind<bool>("4 - Species", "Boss Unlocks Other Biomes", true, "Fish from a different biome appear anywhere once that biome's boss is defeated. Off = every biome's fish are always available.");
			BiomeWeights = cfg.Bind<bool>("4 - Species", "Biome Weights", false, "Fish from the biome you are fishing in appear more often than fish from other biomes (e.g. Ashlands water yields mostly Ashlands fish).");
			LocalBiomeShare = cfg.Bind<float>("4 - Species", "Local Biome Share", 0.7f, new ConfigDescription("With Biome Weights on: share of fish that come from the local biome (0-1). The rest are other unlocked biomes, by rarity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			BaseTreasureChance = cfg.Bind<float>("5 - Rewards", "Treasure Chance", 0.15f, new ConfigDescription("Base chance a caught fish also yields biome treasure.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			BaseLunkerChance = cfg.Bind<float>("5 - Rewards", "Lunker Chance", 0.03f, new ConfigDescription("Base chance a hooked fish is a rare, tougher lunker with better rewards.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			SkillRewardBonus = cfg.Bind<float>("5 - Rewards", "Skill Reward Bonus", 0.25f, new ConfigDescription("Most extra treasure/lunker chance that Fishing skill can add (added at level 100).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			SkillXpMultiplier = cfg.Bind<float>("5 - Rewards", "Skill XP Multiplier", 1f, new ConfigDescription("Multiplier on all Fishing XP gained.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			DistanceBonus = cfg.Bind<float>("5 - Rewards", "Distance Bonus", 0.5f, new ConfigDescription("How much cast distance affects difficulty and rewards. 0 = no effect, 1 = full. Further casts are harder but give more XP, better quality, and higher lunker/treasure chance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			BaseStaminaRate = cfg.Bind<float>("1 - Fight", "Base Stamina Drain", 1f, new ConfigDescription("Base stamina drained per second during a fight, scaled up by fish difficulty and distance and down by skill. At 1.0, the hardest possible fish costs ~80 stamina for a perfect catch.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			TreasureLoot = cfg.Bind<string>("5 - Rewards", "Treasure Loot", "Coins:20:60:30, Amber:1:3:20, AmberPearl:1:2:8, Ruby:1:1:4, FishingBait:5:15:25", "Treasure entries as Prefab:min:max:weight, comma separated. This table is used for every biome.");
		}

		public static MinigameTuning TuningFor(float skill)
		{
			float value = SkillEase.Value;
			return new MinigameTuning
			{
				CentreRadius = 50f + 66f * skill * value,
				DriftSpeed = 100f * (1f - skill * value),
				FillRate = 0.13f * (1f + 2f * skill * value),
				DrainRate = 0.1f * (1f - 0.9f * skill * value)
			};
		}

		public static float RewardBonusAt(float skill)
		{
			return skill * SkillRewardBonus.Value;
		}
	}
	[HarmonyPatch(typeof(Fish), "TestBate")]
	internal static class Patch_TestBate
	{
		[HarmonyPrefix]
		private static bool Prefix(Fish __instance, FishingFloat ff, ref bool __result)
		{
			//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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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)
			Biome val = Waters.Biome(((Component)ff).transform.position);
			if (BiomeUnlock.BaitFiltersTo(ff.GetBait(), val) && FishCatalog.BiomeOf(__instance) != val)
			{
				__result = false;
				return false;
			}
			if (!ModConfig.AllBaitsWork.Value)
			{
				return true;
			}
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(FishingFloat), "RPC_Nibble")]
	internal static class Patch_AutoHook
	{
		[HarmonyPostfix]
		private static void Postfix(FishingFloat __instance, bool correctBait)
		{
			if (ModConfig.AutoHook.Value && correctBait)
			{
				ZNetView val = V.FF_NView(__instance);
				if (!((Object)(object)val == (Object)null) && val.IsValid() && val.IsOwner())
				{
					V.FF_Hook(__instance);
				}
			}
		}
	}
	[HarmonyPatch(typeof(SpawnSystem), "Awake")]
	internal static class Patch_CatalogFromSpawns
	{
		[HarmonyPostfix]
		private static void Postfix(SpawnSystem __instance)
		{
			FishCatalog.Register(__instance);
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class Patch_CatalogFromNetScene
	{
		[HarmonyPostfix]
		private static void Postfix(ZNetScene __instance)
		{
			FishCatalog.RegisterExtra(__instance);
		}
	}
	[HarmonyPatch(typeof(FishingFloat), "SetCatch")]
	internal static class Patch_SetCatch
	{
		[HarmonyPostfix]
		private static void Postfix(FishingFloat __instance, Fish fish)
		{
			if (!((Object)(object)fish == (Object)null))
			{
				if (ModConfig.BaitConsumedOnHook.Value)
				{
					ConsumeBait(__instance);
				}
				CatchSession.Start(__instance, fish);
			}
		}

		private static void ConsumeBait(FishingFloat ff)
		{
			string bait = ff.GetBait();
			Character obj = V.FF_Owner(ff);
			Player val = (Player)(object)((obj is Player) ? obj : null);
			if (!string.IsNullOrEmpty(bait) && !((Object)(object)val == (Object)null))
			{
				((Humanoid)val).GetInventory().RemoveItem(bait, 1, -1, true);
			}
		}
	}
	[HarmonyPatch(typeof(FishingFloat), "FixedUpdate")]
	internal static class Patch_DriveFight
	{
		[HarmonyPrefix]
		private static bool Prefix(FishingFloat __instance)
		{
			if (!CatchSession.IsFighting)
			{
				return true;
			}
			ZNetView val = V.FF_NView(__instance);
			if ((Object)(object)val == (Object)null || !val.IsOwner())
			{
				return true;
			}
			CatchSession.Step(Time.fixedDeltaTime);
			return false;
		}
	}
	[HarmonyPatch(typeof(FishingFloat), "OnDestroy")]
	internal static class Patch_FloatDestroyed
	{
		[HarmonyPostfix]
		private static void Postfix(FishingFloat __instance)
		{
			CatchSession.End();
		}
	}
	[HarmonyPatch(typeof(Player), "TakeInput")]
	internal static class Patch_PlayerTakeInput
	{
		[HarmonyPostfix]
		private static void Postfix(ref bool __result)
		{
			InputCapture.BlockPlayerInput(ref __result);
		}
	}
	[HarmonyPatch(typeof(PlayerController), "TakeInput", new Type[] { typeof(bool) })]
	internal static class Patch_ControllerTakeInput
	{
		[HarmonyPostfix]
		private static void Postfix(ref bool __result)
		{
			InputCapture.BlockPlayerInput(ref __result);
		}
	}
	[BepInPlugin("Andejx.ChillHook", "ChillHook", "1.0.3")]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModGUID = "Andejx.ChillHook";

		public const string ModName = "ChillHook";

		public const string ModVersion = "1.0.3";

		private readonly Harmony _harmony = new Harmony("Andejx.ChillHook");

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony.PatchAll();
			Log.LogInfo((object)"ChillHook v1.0.3 loaded.");
		}

		private void Update()
		{
			InputCapture.Tick();
			FishSpawner.Tick(Time.deltaTime);
		}

		private void OnDestroy()
		{
			CatchSession.End();
			FishSpawner.Clear();
			InputCapture.Reset();
			_harmony.UnpatchSelf();
		}
	}
	public static class Rewards
	{
		private readonly struct Entry
		{
			public readonly GameObject Prefab;

			public readonly string Name;

			public readonly int Min;

			public readonly int Max;

			public readonly float Weight;

			public Entry(GameObject prefab, string name, int min, int max, float weight)
			{
				Prefab = prefab;
				Name = name;
				Min = min;
				Max = max;
				Weight = weight;
			}
		}

		private const float CatchXpPerQuality = 4f;

		private const float LunkerXpMultiplier = 2f;

		private const float PerfectXpMultiplier = 1.3f;

		private const float LossXpBase = 5f;

		private static readonly Dictionary<Biome, string> DefaultBiomeLoot = new Dictionary<Biome, string>
		{
			[(Biome)1] = "Feathers:2:8:20, Resin:5:15:20, Mushroom:1:3:15, Raspberry:5:10:15, Dandelion:1:3:10, Coins:10:30:10",
			[(Biome)8] = "GreydwarfEye:3:8:25, Resin:8:20:20, Thistle:2:5:20, BoneFragments:3:8:15, Ruby:1:1:5, Coins:15:40:10",
			[(Biome)2] = "Guck:2:6:20, Ooze:2:5:20, Bloodbag:2:6:20, WitheredBone:1:2:10, Root:1:3:10, Chain:1:1:5, Coins:15:40:10",
			[(Biome)4] = "Obsidian:3:8:20, FreezeGland:2:5:20, WolfFang:1:4:15, Crystal:1:3:15, SilverNecklace:1:1:4, Coins:15:40:10",
			[(Biome)16] = "Needle:3:8:20, Barley:2:6:20, Flax:2:6:20, Cloudberry:3:8:15, LinenThread:1:3:10, Coins:20:50:15",
			[(Biome)512] = "Sap:1:3:20, YggdrasilWood:2:6:20, RoyalJelly:1:3:15, Softtissue:2:5:15, Carapace:1:3:10, Eitr:1:2:5, Coins:20:50:15",
			[(Biome)32] = "CharredBone:2:6:20, Blackwood:3:8:20, MorgenHeart:1:1:4, Coins:25:60:20",
			[(Biome)64] = "FreezeGland:2:5:20, Crystal:1:3:15, Obsidian:3:8:15, Coins:25:60:20",
			[(Biome)256] = "Chitin:2:6:20, SerpentScale:1:3:15, SerpentMeat:1:2:10, Coins:30:80:25"
		};

		private const string FallbackLoot = "Coins:10:40:30, Amber:1:3:20, AmberPearl:1:2:10, Ruby:1:1:5";

		private static readonly Dictionary<Biome, List<Entry>> BiomeTables = new Dictionary<Biome, List<Entry>>();

		private static List<Entry> _fallbackTable = new List<Entry>();

		private static bool _biomeTablesReady;

		private static List<Entry> _globalTable = new List<Entry>();

		private static string _globalTableRaw;

		public static bool RollLunker(float skill, float distanceFactor)
		{
			float num = Mathf.Clamp01(ModConfig.BaseLunkerChance.Value + ModConfig.RewardBonusAt(skill) + distanceFactor * 0.15f * ModConfig.DistanceBonus.Value);
			return Random.value < num;
		}

		public static string GiveCatch(Player player, Biome biome, float skill, bool perfect, bool lunker, int quality, float distanceFactor)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				return "";
			}
			float value = ModConfig.DistanceBonus.Value;
			float num = 4f * (float)Mathf.Max(1, quality);
			if (lunker)
			{
				num *= 2f;
			}
			if (perfect)
			{
				num *= 1.3f;
			}
			num *= 1f + distanceFactor * 0.5f * value;
			((Character)player).RaiseSkill((SkillType)104, num * ModConfig.SkillXpMultiplier.Value);
			if (Random.value < distanceFactor * 0.3f * value)
			{
				quality++;
			}
			float num2 = Mathf.Clamp01(ModConfig.BaseTreasureChance.Value + ModConfig.RewardBonusAt(skill) + distanceFactor * 0.15f * value);
			if (Random.value >= num2)
			{
				return "";
			}
			EnsureBiomeTables();
			List<Entry> list = BiomeTable(biome);
			List<Entry> list2 = GlobalTable();
			StringBuilder stringBuilder = new StringBuilder();
			DropOne(player, list, stringBuilder);
			if (list2.Count > 0)
			{
				DropOne(player, list2, stringBuilder);
			}
			if (lunker && perfect)
			{
				DropOne(player, (list.Count > 0) ? list : list2, stringBuilder);
			}
			return stringBuilder.ToString();
		}

		public static void GiveLoss(Player player, float skill, float peakProgress, float distanceFactor)
		{
			if (!((Object)(object)player == (Object)null))
			{
				float num = 5f * Mathf.Clamp01(peakProgress) * ModConfig.SkillXpMultiplier.Value;
				num *= 1f + distanceFactor * 0.5f * ModConfig.DistanceBonus.Value;
				if (num > 0f)
				{
					((Character)player).RaiseSkill((SkillType)104, num);
				}
			}
		}

		private static void DropOne(Player player, List<Entry> table, StringBuilder summary)
		{
			//IL_0039: 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)
			Entry? entry = Pick(table);
			if (!entry.HasValue)
			{
				return;
			}
			Entry value = entry.Value;
			int num = Random.Range(value.Min, value.Max + 1);
			if (num > 0)
			{
				ItemDrop component = Object.Instantiate<GameObject>(value.Prefab, DropSpot(player), Quaternion.Euler(0f, (float)Random.Range(0, 360), 0f)).GetComponent<ItemDrop>();
				if (component != null)
				{
					component.SetStack(num);
				}
				summary.Append(" & ").Append(Localize(value.Name)).Append(" x")
					.Append(num);
			}
		}

		private static Vector3 DropSpot(Player player)
		{
			//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_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)
			return ((Component)player).transform.position + Vector3.up * 0.5f;
		}

		private static Entry? Pick(List<Entry> table)
		{
			if (table == null || table.Count == 0)
			{
				return null;
			}
			float num = 0f;
			foreach (Entry item in table)
			{
				num += item.Weight;
			}
			if (num <= 0f)
			{
				return null;
			}
			float num2 = Random.Range(0f, num);
			foreach (Entry item2 in table)
			{
				num2 -= item2.Weight;
				if (num2 <= 0f)
				{
					return item2;
				}
			}
			return null;
		}

		private static void EnsureBiomeTables()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (_biomeTablesReady || (Object)(object)ObjectDB.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			BiomeTables.Clear();
			foreach (KeyValuePair<Biome, string> item in DefaultBiomeLoot)
			{
				List<Entry> list = Parse(item.Value);
				if (list.Count > 0)
				{
					BiomeTables[item.Key] = list;
				}
			}
			_fallbackTable = Parse("Coins:10:40:30, Amber:1:3:20, AmberPearl:1:2:10, Ruby:1:1:5");
			_biomeTablesReady = true;
		}

		private static List<Entry> BiomeTable(Biome biome)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (!BiomeTables.TryGetValue(biome, out var value))
			{
				return _fallbackTable;
			}
			return value;
		}

		private static List<Entry> GlobalTable()
		{
			string text = ModConfig.TreasureLoot.Value ?? "";
			if (text != _globalTableRaw)
			{
				_globalTableRaw = text;
				_globalTable = ((text.Trim().Length > 0) ? Parse(text) : new List<Entry>());
			}
			return _globalTable;
		}

		private static List<Entry> Parse(string config)
		{
			List<Entry> list = new List<Entry>();
			if (string.IsNullOrEmpty(config))
			{
				return list;
			}
			string[] array = config.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length == 0)
				{
					continue;
				}
				string[] array2 = text.Split(new char[1] { ':' });
				if (array2.Length != 4)
				{
					Warn("Ignoring treasure entry '" + text + "': expected 'Prefab:min:max:weight'.");
					continue;
				}
				string text2 = array2[0].Trim();
				GameObject val = FindPrefab(text2);
				ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
				int result;
				int result2;
				float result3;
				if ((Object)(object)val2 == (Object)null)
				{
					Warn("Ignoring treasure entry '" + text + "': no item prefab named '" + text2 + "'.");
				}
				else if (!int.TryParse(array2[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out result) || !int.TryParse(array2[2].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out result2) || !float.TryParse(array2[3].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out result3))
				{
					Warn("Ignoring treasure entry '" + text + "': min, max and weight all have to be numbers.");
				}
				else if (!(result3 <= 0f))
				{
					list.Add(new Entry(val, val2.m_itemData.m_shared.m_name, result, Mathf.Max(result, result2), result3));
				}
			}
			return list;
		}

		private static GameObject FindPrefab(string prefabName)
		{
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
				if ((Object)(object)itemPrefab != (Object)null)
				{
					return itemPrefab;
				}
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
				if ((Object)(object)prefab != (Object)null)
				{
					return prefab;
				}
			}
			return null;
		}

		private static string Localize(string key)
		{
			if (Localization.instance == null)
			{
				return key;
			}
			return Localization.instance.Localize(key);
		}

		private static void Warn(string message)
		{
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogWarning((object)message);
			}
		}
	}
	public static class Waters
	{
		public static Biome Biome(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Biome val = Heightmap.FindBiome(point);
			if ((int)val == 0)
			{
				return (Biome)256;
			}
			return val;
		}

		public static float Depth(Vector3 point)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: 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_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_002d: 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)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(point + Vector3.up * 0.5f, Vector3.down, ref val, 200f))
			{
				return Mathf.Max(0f, point.y - ((RaycastHit)(ref val)).point.y);
			}
			return 0f;
		}
	}
}