Decompiled source of Hooked v1.1.0

Hooked.dll

Decompiled 18 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Hooked.Fishing;
using Hooked.UI;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UIManager;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.U2D;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Hooked")]
[assembly: AssemblyDescription("A Stardew Valley style fishing minigame for Valheim.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Azumatt")]
[assembly: AssemblyProduct("Hooked")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("E0E2F92E-557C-4A05-9D89-AA92A0BD75C4")]
[assembly: AssemblyFileVersion("1.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 LocalizationManager
{
	[PublicAPI]
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

		private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts;

		private static readonly ConditionalWeakTable<Localization, string> localizationLanguage;

		private static readonly List<WeakReference<Localization>> localizationObjects;

		private static BaseUnityPlugin? _plugin;

		private static readonly List<string> fileExtensions;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Expected O, but got Unknown
				if (_plugin == null)
				{
					IEnumerable<TypeInfo> source;
					try
					{
						source = Assembly.GetExecutingAssembly().DefinedTypes.ToList();
					}
					catch (ReflectionTypeLoadException ex)
					{
						source = from t in ex.Types
							where t != null
							select t.GetTypeInfo();
					}
					_plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		public static event Action? OnLocalizationComplete;

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out string value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2))
			{
				text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull
		{
			if (convertConfigValue == null)
			{
				convertConfigValue = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key))
			{
				PlaceholderProcessors[key] = new Dictionary<string, Func<string>>();
			}
			config.SettingChanged += delegate
			{
				UpdatePlaceholder();
			};
			if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage()))
			{
				UpdatePlaceholder();
			}
			void UpdatePlaceholder()
			{
				PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value);
				UpdatePlaceholderText(Localization.instance, key);
			}
		}

		public static void AddText(string key, string text)
		{
			List<WeakReference<Localization>> list = new List<WeakReference<Localization>>();
			foreach (WeakReference<Localization> localizationObject in localizationObjects)
			{
				if (localizationObject.TryGetTarget(out var target))
				{
					Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)];
					if (!target.m_translations.ContainsKey(key))
					{
						dictionary[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

		public static void Load()
		{
			_ = plugin;
		}

		public static void LoadLocalizationLater(Localization __instance)
		{
			LoadLocalization(Localization.instance, __instance.GetSelectedLanguage());
		}

		public static void SafeCallLocalizeComplete()
		{
			Localizer.OnLocalizationComplete?.Invoke();
		}

		private static void LoadLocalization(Localization __instance, string language)
		{
			if (!localizationLanguage.Remove(__instance))
			{
				localizationObjects.Add(new WeakReference<Localization>(__instance));
			}
			localizationLanguage.Add(__instance, language);
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories)
				where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0
				select f)
			{
				string[] array = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' });
				if (array.Length >= 2)
				{
					string text = array[1];
					if (dictionary.ContainsKey(text))
					{
						Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped."));
					}
					else
					{
						dictionary[text] = item;
					}
				}
			}
			byte[] array2 = LoadTranslationFromAssembly("English");
			if (array2 == null)
			{
				throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml.");
			}
			Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array2));
			if (dictionary2 == null)
			{
				throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty.");
			}
			string text2 = null;
			if (language != "English")
			{
				if (dictionary.TryGetValue(language, out var value))
				{
					text2 = File.ReadAllText(value);
				}
				else
				{
					byte[] array3 = LoadTranslationFromAssembly(language);
					if (array3 != null)
					{
						text2 = Encoding.UTF8.GetString(array3);
					}
				}
			}
			if (text2 == null && dictionary.TryGetValue("English", out var value2))
			{
				text2 = File.ReadAllText(value2);
			}
			if (text2 != null)
			{
				foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>())
				{
					dictionary2[item2.Key] = item2.Value;
				}
			}
			loadedTexts[language] = dictionary2;
			foreach (KeyValuePair<string, string> item3 in dictionary2)
			{
				UpdatePlaceholderText(__instance, item3.Key);
			}
		}

		static Localizer()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string>(2) { ".json", ".yml" };
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static byte[]? LoadTranslationFromAssembly(string language)
		{
			foreach (string fileExtension in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal));
			if (text != null)
			{
				containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream);
			}
			return (memoryStream.Length == 0L) ? null : memoryStream.ToArray();
		}
	}
	public static class LocalizationManagerVersion
	{
		public const string Version = "1.4.1";
	}
}
namespace Hooked
{
	[BepInPlugin("Azumatt.Hooked", "Hooked", "1.1.0")]
	public class HookedPlugin : BaseUnityPlugin
	{
		public enum Toggle
		{
			On = 1,
			Off = 0
		}

		public enum BarAnchor
		{
			Left,
			Right
		}

		public enum TutorialMode
		{
			Always,
			Beginner,
			Never
		}

		public enum DifficultyPreset
		{
			Relaxed,
			Casual,
			Normal,
			Challenging,
			Brutal
		}

		internal const string ModName = "Hooked";

		internal const string ModVersion = "1.1.0";

		internal const string Author = "Azumatt";

		private const string ModGUID = "Azumatt.Hooked";

		private static readonly string ConfigFileName = "Azumatt.Hooked.cfg";

		private static readonly string ConfigFileFullPath;

		internal static string ConnectionError;

		public static readonly ManualLogSource HookedLogger;

		private static readonly ConfigSync ConfigSync;

		private static HookedPlugin self;

		private readonly Harmony harmony = new Harmony("Azumatt.Hooked");

		private static readonly Dictionary<Biome, string> DefaultBiomeLoot;

		private static ConfigEntry<Toggle> serverConfigLocked;

		public static ConfigEntry<Toggle> minigameEnabled;

		public static ConfigEntry<DifficultyPreset> difficulty;

		public static ConfigEntry<float> biteProximityBonus;

		public static ConfigEntry<Toggle> autoHook;

		public static ConfigEntry<int> barHeightBase;

		public static ConfigEntry<int> barHeightPerLevel;

		public static ConfigEntry<float> startingProgress;

		public static ConfigEntry<float> firstCatchProgress;

		public static ConfigEntry<float> fillRate;

		public static ConfigEntry<float> drainRate;

		public static ConfigEntry<float> barGravity;

		public static ConfigEntry<float> inBarGravityScale;

		public static ConfigEntry<float> difficultyScale;

		public static ConfigEntry<float> escapeDifficultyBonus;

		public static ConfigEntry<float> reelInFrom;

		public static ConfigEntry<float> minLineLength;

		public static ConfigEntry<Toggle> lineBreaks;

		public static ConfigEntry<float> biteRangeBonus;

		public static ConfigEntry<Toggle> beginnerAssist;

		public static ConfigEntry<float> beginnerSkillLevel;

		public static ConfigEntry<float> beginnerDifficultyScale;

		public static ConfigEntry<float> beginnerDrainScale;

		public static ConfigEntry<float> beginnerBarBonus;

		public static ConfigEntry<string> fishOverrides;

		public static ConfigEntry<Toggle> flexibleBait;

		public static ConfigEntry<Toggle> baitTackle;

		public static ConfigEntry<Toggle> lunkers;

		public static ConfigEntry<float> lunkerChance;

		public static ConfigEntry<float> lunkerSkillBonus;

		public static ConfigEntry<float> lunkerTierBonus;

		public static ConfigEntry<float> lunkerDifficultyBonus;

		public static ConfigEntry<float> lunkerWanderScale;

		public static ConfigEntry<float> lunkerSkillScale;

		public static ConfigEntry<int> lunkerQualityBonus;

		public static ConfigEntry<Toggle> lunkerTreasure;

		public static ConfigEntry<int> lunkerTreasureRolls;

		public static ConfigEntry<Toggle> depthRewards;

		public static ConfigEntry<float> shallowDepth;

		public static ConfigEntry<float> fullDepth;

		public static ConfigEntry<float> depthTreasureBonus;

		public static ConfigEntry<float> depthSizeBonus;

		public static ConfigEntry<float> depthSkillBonus;

		public static ConfigEntry<float> depthLunkerBonus;

		public static ConfigEntry<Toggle> freshCatch;

		public static ConfigEntry<Toggle> freshCatchNeedsPerfect;

		public static ConfigEntry<float> freshCatchDuration;

		public static ConfigEntry<float> freshCatchCarryWeight;

		public static ConfigEntry<float> freshCatchStaminaRegen;

		public static ConfigEntry<float> freshCatchEitrRegen;

		public static ConfigEntry<Toggle> sizeFromSkill;

		public static ConfigEntry<Toggle> qualityFromSize;

		public static ConfigEntry<int> qualityLossSteps;

		public static ConfigEntry<Toggle> perfectUpgradesQuality;

		public static ConfigEntry<float> skillGainScale;

		public static ConfigEntry<float> skillGainOnLoss;

		public static ConfigEntry<float> skillFillBonus;

		public static ConfigEntry<Toggle> treasureEnabled;

		public static ConfigEntry<float> treasureChance;

		public static ConfigEntry<float> treasureSkillBonus;

		public static ConfigEntry<float> treasureTierBonus;

		public static ConfigEntry<float> treasureFillRate;

		public static ConfigEntry<float> treasureDrainRate;

		public static ConfigEntry<int> treasureRollsMin;

		public static ConfigEntry<int> treasureRollsMax;

		public static ConfigEntry<string> treasureLoot;

		public static ConfigEntry<Toggle> treasureGuard;

		public static ConfigEntry<string> treasureBlocklist;

		public static ConfigEntry<Toggle> treasureKnownOnly;

		public static ConfigEntry<Toggle> treasureBiomeLoot;

		public static ConfigEntry<Toggle> treasureBiomeAddsToBase;

		public static readonly Dictionary<Biome, ConfigEntry<string>> treasureBiomeTables;

		public static ConfigEntry<float> staminaScale;

		public static ConfigEntry<float> reelStaminaScale;

		public static ConfigEntry<Toggle> fishFinder;

		public static ConfigEntry<Toggle> soundEnabled;

		public static ConfigEntry<float> soundVolume;

		public static ConfigEntry<string> reelClipNames;

		public static ConfigEntry<float> shakeStrength;

		public static ConfigEntry<float> uiScale;

		public static ConfigEntry<float> fishIconScale;

		public static ConfigEntry<TutorialMode> tutorial;

		public static ConfigEntry<BarAnchor> uiAnchor;

		public static ConfigEntry<float> uiOffsetX;

		public static ConfigEntry<float> uiOffsetY;

		public void Awake()
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Expected O, but got Unknown
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Expected O, but got Unknown
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Expected O, but got Unknown
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Expected O, but got Unknown
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Expected O, but got Unknown
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Expected O, but got Unknown
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Expected O, but got Unknown
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Expected O, but got Unknown
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Expected O, but got Unknown
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Expected O, but got Unknown
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Expected O, but got Unknown
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Expected O, but got Unknown
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d1: Expected O, but got Unknown
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_043f: Expected O, but got Unknown
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0477: Expected O, but got Unknown
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04af: Expected O, but got Unknown
			//IL_04dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e7: Expected O, but got Unknown
			//IL_05cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d7: Expected O, but got Unknown
			//IL_061f: Unknown result type (might be due to invalid IL or missing references)
			//IL_062a: Expected O, but got Unknown
			//IL_0657: Unknown result type (might be due to invalid IL or missing references)
			//IL_0662: Expected O, but got Unknown
			//IL_06aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b5: Expected O, but got Unknown
			//IL_06e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ed: Expected O, but got Unknown
			//IL_071a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0725: Expected O, but got Unknown
			//IL_0752: Unknown result type (might be due to invalid IL or missing references)
			//IL_075d: Expected O, but got Unknown
			//IL_078a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0795: Expected O, but got Unknown
			//IL_07c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_07cd: Expected O, but got Unknown
			//IL_07ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f9: Expected O, but got Unknown
			//IL_0836: Unknown result type (might be due to invalid IL or missing references)
			//IL_0841: Expected O, but got Unknown
			//IL_0889: Unknown result type (might be due to invalid IL or missing references)
			//IL_0894: Expected O, but got Unknown
			//IL_08c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_08cc: Expected O, but got Unknown
			//IL_08f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0904: Expected O, but got Unknown
			//IL_0931: Unknown result type (might be due to invalid IL or missing references)
			//IL_093c: Expected O, but got Unknown
			//IL_0969: Unknown result type (might be due to invalid IL or missing references)
			//IL_0974: Expected O, but got Unknown
			//IL_09a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ac: Expected O, but got Unknown
			//IL_0a0f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a1a: Expected O, but got Unknown
			//IL_0a47: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a52: Expected O, but got Unknown
			//IL_0a7f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a8a: Expected O, but got Unknown
			//IL_0ab7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ac2: Expected O, but got Unknown
			//IL_0b0a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b15: Expected O, but got Unknown
			//IL_0b42: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b4d: Expected O, but got Unknown
			//IL_0b7a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b85: Expected O, but got Unknown
			//IL_0bb2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bbd: Expected O, but got Unknown
			//IL_0bea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bf5: Expected O, but got Unknown
			//IL_0c17: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c22: Expected O, but got Unknown
			//IL_0c44: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c4f: Expected O, but got Unknown
			//IL_0d95: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d9a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0db7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0df9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e48: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e53: Expected O, but got Unknown
			//IL_0e80: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e8b: Expected O, but got Unknown
			//IL_0f28: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f33: Expected O, but got Unknown
			//IL_0f60: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f6b: Expected O, but got Unknown
			//IL_0f98: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fa3: Expected O, but got Unknown
			//IL_0fd0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fdb: Expected O, but got Unknown
			//IL_1023: Unknown result type (might be due to invalid IL or missing references)
			//IL_102e: Expected O, but got Unknown
			//IL_105b: Unknown result type (might be due to invalid IL or missing references)
			//IL_1066: Expected O, but got Unknown
			self = this;
			Localizer.Load();
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			serverConfigLocked = config("1 - General", "Lock Configuration", Toggle.On, "Only server admins can change synced settings.");
			ConfigSync.AddLockingConfigEntry<Toggle>(serverConfigLocked);
			minigameEnabled = config("2 - Minigame", "Enabled", Toggle.On, "Runs the bobber-bar fight. Off uses vanilla line pulling.");
			difficulty = config("2 - Minigame", "Difficulty", DifficultyPreset.Normal, "Fight preset. Normal leaves the settings below alone.");
			biteProximityBonus = config("2 - Minigame", "Bite Proximity Bonus", 0.2f, new ConfigDescription("Extra bite chance at point-blank range. 0 keeps vanilla odds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			autoHook = config("2 - Minigame", "Auto Hook", Toggle.On, "Hooks fish as soon as they bite.");
			barHeightBase = config("2 - Minigame", "Bar Height", 96, new ConfigDescription("Green bar height at Fishing 0.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(32, 400), Array.Empty<object>()));
			barHeightPerLevel = config("2 - Minigame", "Bar Height Per Level", 8, new ConfigDescription("Bar height gained per 10 Fishing.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 40), Array.Empty<object>()));
			startingProgress = config("2 - Minigame", "Starting Progress", 0.3f, new ConfigDescription("Catch meter at the start of each fight.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.9f), Array.Empty<object>()));
			firstCatchProgress = config("2 - Minigame", "First Catch Progress", 0.1f, new ConfigDescription("Catch meter for this character's first fish. Match Starting Progress to disable.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.9f), Array.Empty<object>()));
			fillRate = config("2 - Minigame", "Fill Rate", 0.002f, new ConfigDescription("Catch meter gained per 1/60s inside the bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.0002f, 0.02f), Array.Empty<object>()));
			drainRate = config("2 - Minigame", "Drain Rate", 0.003f, new ConfigDescription("Catch meter lost per 1/60s outside the bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.0002f, 0.02f), Array.Empty<object>()));
			barGravity = config("2 - Minigame", "Bar Gravity", 0.25f, new ConfigDescription("Strength of the bar's rise and fall.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			skillFillBonus = config("2 - Minigame", "Skill Fill Bonus", 2f, new ConfigDescription("Fill rate multiplier at Fishing 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
			inBarGravityScale = config("2 - Minigame", "In Bar Gravity Scale", 0.6f, new ConfigDescription("Bar gravity while the fish is inside. Lower is steadier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			difficultyScale = config("2 - Minigame", "Difficulty Scale", 1f, new ConfigDescription("Scales derived fish difficulty. Overrides ignore it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
			escapeDifficultyBonus = config("2 - Minigame", "Escape Difficulty Bonus", 15f, new ConfigDescription("Difficulty added while the fish thrashes.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>()));
			reelInFrom = config("2 - Minigame", "Reel In From", 0.75f, new ConfigDescription("Catch meter where the float starts coming in.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			minLineLength = config("2 - Minigame", "Minimum Line Length", 4f, new ConfigDescription("Closest the float comes before the catch, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 25f), Array.Empty<object>()));
			biteRangeBonus = config("2 - Minigame", "Bite Range Bonus", 4f, new ConfigDescription("Hook range added at Fishing 100, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			lineBreaks = config("2 - Minigame", "Line Breaks", Toggle.On, "Breaks the line past the rod's maximum range.");
			beginnerAssist = config("2 - Minigame", "Beginner Assist", Toggle.On, "Enables the early bar and drain help.");
			beginnerSkillLevel = config("2 - Minigame", "Beginner Skill Level", 10f, new ConfigDescription("Fishing level where beginner help and tutorial stop.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			beginnerDifficultyScale = config("2 - Minigame", "Beginner Difficulty Scale", 1f, new ConfigDescription("Difficulty multiplier at Fishing 0. 1 disables it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			beginnerDrainScale = config("2 - Minigame", "Beginner Drain Scale", 0.67f, new ConfigDescription("Drain multiplier at Fishing 0.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			beginnerBarBonus = config("2 - Minigame", "Beginner Bar Bonus", 40f, new ConfigDescription("Bar height added at Fishing 0.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), Array.Empty<object>()));
			fishOverrides = config("3 - Fish", "Overrides", "", "Fish1=60:Dart, Fish3=85. Patterns: Mixed, Dart, Smooth, Sinker, Floater.");
			fishOverrides.SettingChanged += delegate
			{
				FishTuning.ParseOverrides(fishOverrides.Value);
			};
			FishTuning.ParseOverrides(fishOverrides.Value);
			flexibleBait = config("3 - Fish / Bait", "Flexible Bait", Toggle.On, "After you discover the required bait, any fishing bait can hook that fish. The equipped bait is still spent.");
			baitTackle = config("3 - Fish / Bait", "Bait Benefits", Toggle.On, "Trophy-crafted bait gives its fixed fishing benefit.");
			sizeFromSkill = config("4 - Rewards", "Size From Skill", Toggle.On, "Fishing skill and deep water can add one or two quality levels.");
			qualityFromSize = config("4 - Rewards", "Misses Lower Quality", Toggle.On, "Time outside the bar can lower fish quality.");
			qualityLossSteps = config("4 - Rewards", "Quality Loss Steps", 4, new ConfigDescription("Number of 0.8s misses that remove one quality level.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 40), Array.Empty<object>()));
			perfectUpgradesQuality = config("4 - Rewards", "Perfect Upgrades Quality", Toggle.On, "Perfect catches gain one quality level.");
			skillGainScale = config("4 - Rewards", "Skill Gain Scale", 1f, new ConfigDescription("Fishing XP multiplier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 4f), Array.Empty<object>()));
			skillGainOnLoss = config("4 - Rewards", "Skill Gain On Loss", 0.5f, new ConfigDescription("XP share paid on escape, scaled by peak meter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			lunkers = config("4 - Rewards / Lunkers", "Enabled", Toggle.On, "Enables rare, harder fish with better rewards.");
			lunkerChance = config("4 - Rewards / Lunkers", "Chance", 0.03f, new ConfigDescription("Base chance per hooked fish.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			lunkerSkillBonus = config("4 - Rewards / Lunkers", "Skill Bonus", 0.05f, new ConfigDescription("Chance added at Fishing 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			lunkerTierBonus = config("4 - Rewards / Lunkers", "Tier Bonus", 0.04f, new ConfigDescription("Chance added for the hardest fish.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			lunkerDifficultyBonus = config("4 - Rewards / Lunkers", "Difficulty Bonus", 15f, new ConfigDescription("Difficulty added to lunkers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>()));
			lunkerWanderScale = config("4 - Rewards / Lunkers", "Wander Scale", 1f, new ConfigDescription("Lunker target-change rate. 1 leaves it alone.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
			lunkerSkillScale = config("4 - Rewards / Lunkers", "Skill Scale", 5f, new ConfigDescription("Lunker XP multiplier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>()));
			lunkerQualityBonus = config("4 - Rewards / Lunkers", "Quality Bonus", 1, new ConfigDescription("Quality levels added to lunkers.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4), Array.Empty<object>()));
			lunkerTreasure = config("4 - Rewards / Lunkers", "Guaranteed Treasure", Toggle.On, "Lunkers always carry treasure.");
			lunkerTreasureRolls = config("4 - Rewards / Lunkers", "Treasure Rolls", 1, new ConfigDescription("Extra loot rolls in a lunker chest.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 10), Array.Empty<object>()));
			depthRewards = config("4 - Rewards / Depth", "Enabled", Toggle.On, "Enables rewards for deeper water.");
			shallowDepth = config("4 - Rewards / Depth", "Shallow Depth", 5f, new ConfigDescription("Water depth where bonuses start, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			fullDepth = config("4 - Rewards / Depth", "Full Depth", 15f, new ConfigDescription("Water depth where bonuses max out, in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 100f), Array.Empty<object>()));
			depthTreasureBonus = config("4 - Rewards / Depth", "Treasure Bonus", 0.08f, new ConfigDescription("Treasure chance added at full depth.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			depthSizeBonus = config("4 - Rewards / Depth", "Size Bonus", 0.25f, new ConfigDescription("Quality-roll chance added at full depth.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			depthSkillBonus = config("4 - Rewards / Depth", "Skill Bonus", 0.25f, new ConfigDescription("XP bonus at full depth. 0.25 means 25%.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
			depthLunkerBonus = config("4 - Rewards / Depth", "Lunker Bonus", 0.02f, new ConfigDescription("Lunker chance added at full depth.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			freshCatch = config("4 - Rewards / Fresh Catch", "Enabled", Toggle.On, "Enables the Fresh Catch buff.");
			freshCatchNeedsPerfect = config("4 - Rewards / Fresh Catch", "Requires Perfect", Toggle.On, "Requires a Perfect catch or lunker.");
			freshCatchDuration = config("4 - Rewards / Fresh Catch", "Duration", 300f, new ConfigDescription("Buff duration in seconds. Lunkers double it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 3600f), Array.Empty<object>()));
			freshCatchCarryWeight = config("4 - Rewards / Fresh Catch", "Carry Weight", 50f, new ConfigDescription("Carry weight added by the buff.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>()));
			freshCatchStaminaRegen = config("4 - Rewards / Fresh Catch", "Stamina Regen", 1.1f, new ConfigDescription("Stamina regeneration multiplier. 1.1 means 10% faster.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2f), Array.Empty<object>()));
			freshCatchEitrRegen = config("4 - Rewards / Fresh Catch", "Eitr Regen", 1f, new ConfigDescription("Eitr regeneration multiplier. 1 leaves it alone.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2f), Array.Empty<object>()));
			treasureEnabled = config("5 - Treasure", "Enabled", Toggle.On, "Enables treasure in the bobber bar.");
			treasureChance = config("5 - Treasure", "Chance", 0.15f, new ConfigDescription("Base chance per hooked fish.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			treasureSkillBonus = config("5 - Treasure", "Skill Bonus", 0.15f, new ConfigDescription("Chance added at Fishing 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			treasureTierBonus = config("5 - Treasure", "Tier Bonus", 0.1f, new ConfigDescription("Chance added for the hardest fish.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			treasureFillRate = config("5 - Treasure", "Fill Rate", 0.0135f, new ConfigDescription("Treasure meter gained per 1/60s inside the bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.001f, 0.1f), Array.Empty<object>()));
			treasureDrainRate = config("5 - Treasure", "Drain Rate", 0.01f, new ConfigDescription("Treasure meter lost per 1/60s outside the bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.1f), Array.Empty<object>()));
			treasureRollsMin = config("5 - Treasure", "Rolls Min", 1, new ConfigDescription("Minimum loot rolls per chest.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>()));
			treasureRollsMax = config("5 - Treasure", "Rolls Max", 2, new ConfigDescription("Maximum loot rolls per chest.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>()));
			treasureLoot = config("5 - Treasure", "Loot", "Coins:20:60:30, FishingBait:5:15:25, Amber:1:3:20, AmberPearl:1:2:8, Ruby:1:1:4", "Prefab:min:max:weight, comma separated.");
			treasureGuard = config("5 - Treasure", "Block Progression Items", Toggle.On, "Blocks non-teleportable items and trophies.");
			treasureBlocklist = config("5 - Treasure", "Blocklist", "", "Extra blocked prefab names, comma separated.");
			treasureKnownOnly = config("5 - Treasure", "Known Items Only", Toggle.On, "Limits loot to items this character knows. Falls back to base loot if none qualify.");
			treasureLoot.SettingChanged += delegate
			{
				Treasure.Invalidate();
			};
			treasureGuard.SettingChanged += delegate
			{
				Treasure.Invalidate();
			};
			treasureBlocklist.SettingChanged += delegate
			{
				Treasure.Invalidate();
			};
			treasureBiomeLoot = config("5 - Treasure / Biome", "Biome Tables", Toggle.On, "Uses a loot table for the float's biome.");
			treasureBiomeAddsToBase = config("5 - Treasure / Biome", "Adds To Base", Toggle.On, "Adds biome loot to base loot. Off replaces it.");
			foreach (KeyValuePair<Biome, string> item in DefaultBiomeLoot)
			{
				ConfigEntry<string> val = config("5 - Treasure / Biome", ((object)item.Key/*cast due to .constrained prefix*/).ToString(), item.Value, $"Prefab:min:max:weight for {item.Key}. Blank uses base loot.");
				val.SettingChanged += delegate
				{
					Treasure.Invalidate();
				};
				treasureBiomeTables[item.Key] = val;
			}
			staminaScale = config("6 - Stamina", "Hooked Drain Scale", 1f, new ConfigDescription("Rod stamina drain while a fish is hooked.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			reelStaminaScale = config("6 - Stamina", "Reel Drain Scale", 1f, new ConfigDescription("Rod pull cost while reeling.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
			fishFinder = config("7 - Interface", "Fish Finder", Toggle.On, "Shows nearby fish that can take the equipped bait.", synchronizedSetting: false);
			reelClipNames = config("7 - Interface", "Reel Clip", "", "Reel audio clip names, comma separated. Blank uses defaults.", synchronizedSetting: false);
			tutorial = config("7 - Interface", "Tutorial", TutorialMode.Beginner, "Control hint beside the bar. Beginner stops at Beginner Skill Level.", synchronizedSetting: false);
			soundEnabled = config("7 - Interface", "Sound", Toggle.On, "Enables Hooked's reel, bounce and result sounds.", synchronizedSetting: false);
			soundVolume = config("7 - Interface", "Sound Volume", 0.7f, new ConfigDescription("Hooked sound volume.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()), synchronizedSetting: false);
			shakeStrength = config("7 - Interface", "Shake Strength", 3f, new ConfigDescription("Screen shake in pixels. 0 disables it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 12f), Array.Empty<object>()), synchronizedSetting: false);
			uiScale = config("7 - Interface", "Scale", 0.85f, new ConfigDescription("Bobber-bar UI scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.4f, 2f), Array.Empty<object>()), synchronizedSetting: false);
			fishIconScale = config("7 - Interface", "Fish Icon Scale", 1.25f, new ConfigDescription("Fish icon scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()), synchronizedSetting: false);
			uiAnchor = config("7 - Interface", "Anchor", BarAnchor.Right, "Side of the player used by the bar.", synchronizedSetting: false);
			uiOffsetX = config("7 - Interface", "Offset X", 0f, new ConfigDescription("Horizontal offset in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-800f, 800f), Array.Empty<object>()), synchronizedSetting: false);
			uiOffsetY = config("7 - Interface", "Offset Y", 0f, new ConfigDescription("Vertical offset in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-500f, 500f), Array.Empty<object>()), synchronizedSetting: false);
			UIRoot.Init(HookedLogger, harmony);
			harmony.PatchAll(Assembly.GetExecutingAssembly());
			SetupWatcher();
			if (saveOnConfigSet)
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}

		private void SetupWatcher()
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName);
			fileSystemWatcher.Changed += ReadConfigValues;
			fileSystemWatcher.Created += ReadConfigValues;
			fileSystemWatcher.Renamed += ReadConfigValues;
			fileSystemWatcher.IncludeSubdirectories = true;
			fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject;
			fileSystemWatcher.EnableRaisingEvents = true;
		}

		private void ReadConfigValues(object sender, FileSystemEventArgs e)
		{
			if (!File.Exists(ConfigFileFullPath))
			{
				return;
			}
			try
			{
				HookedLogger.LogDebug((object)"ReadConfigValues called");
				((BaseUnityPlugin)this).Config.Reload();
			}
			catch
			{
				HookedLogger.LogError((object)("There was an issue loading your " + ConfigFileName));
				HookedLogger.LogError((object)"Please check your config entries for spelling and format!");
			}
		}

		internal static ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags);
			ConfigEntry<T> val2 = ((BaseUnityPlugin)self).Config.Bind<T>(group, name, value, val);
			ConfigSync.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedSetting;
			return val2;
		}

		internal static ConfigEntry<T> config<T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		static HookedPlugin()
		{
			string configPath = Paths.ConfigPath;
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName;
			ConnectionError = "";
			HookedLogger = Logger.CreateLogSource("Hooked");
			ConfigSync = new ConfigSync("Azumatt.Hooked")
			{
				DisplayName = "Hooked",
				CurrentVersion = "1.1.0",
				MinimumRequiredVersion = "1.1.0",
				ModRequired = false
			};
			self = null;
			DefaultBiomeLoot = new Dictionary<Biome, string>
			{
				[(Biome)1] = "Feathers:2:8:20, Dandelion:1:3:15, Resin:5:15:20, Mushroom:1:3:15, Raspberry:5:10:10",
				[(Biome)8] = "GreydwarfEye:3:8:25, Resin:8:20:20, Thistle:2:5:20, BoneFragments:3:8:15, Ruby:1:1:5, FishingBaitForest:5:15:15",
				[(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, FishingBaitSwamp:5:15:15",
				[(Biome)4] = "Obsidian:3:8:20, FreezeGland:2:5:20, WolfFang:1:4:15, Crystal:1:3:15, SilverNecklace:1:1:4, OnionSeeds:1:3:10, FishingBaitCave:5:15:15",
				[(Biome)16] = "Needle:3:8:20, Barley:2:6:20, Flax:2:6:20, Cloudberry:3:8:15, LinenThread:1:3:10, FishingBaitPlains:5:15: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, FishingBaitMistlands:5:15:15",
				[(Biome)32] = "CharredBone:2:6:20, Blackwood:3:8:20, MorgenHeart:1:1:4, FishingBaitAshlands:5:15:15",
				[(Biome)64] = "FreezeGland:2:5:20, Crystal:1:3:15, FishingBaitDeepNorth:5:15:15",
				[(Biome)256] = "Chitin:2:6:20, SerpentScale:1:3:15, SerpentMeat:1:2:10, Coins:30:80:20, FishingBaitOcean:5:15:15"
			};
			serverConfigLocked = null;
			minigameEnabled = null;
			difficulty = null;
			biteProximityBonus = null;
			autoHook = null;
			barHeightBase = null;
			barHeightPerLevel = null;
			startingProgress = null;
			firstCatchProgress = null;
			fillRate = null;
			drainRate = null;
			barGravity = null;
			inBarGravityScale = null;
			difficultyScale = null;
			escapeDifficultyBonus = null;
			reelInFrom = null;
			minLineLength = null;
			lineBreaks = null;
			biteRangeBonus = null;
			beginnerAssist = null;
			beginnerSkillLevel = null;
			beginnerDifficultyScale = null;
			beginnerDrainScale = null;
			beginnerBarBonus = null;
			fishOverrides = null;
			flexibleBait = null;
			baitTackle = null;
			lunkers = null;
			lunkerChance = null;
			lunkerSkillBonus = null;
			lunkerTierBonus = null;
			lunkerDifficultyBonus = null;
			lunkerWanderScale = null;
			lunkerSkillScale = null;
			lunkerQualityBonus = null;
			lunkerTreasure = null;
			lunkerTreasureRolls = null;
			depthRewards = null;
			shallowDepth = null;
			fullDepth = null;
			depthTreasureBonus = null;
			depthSizeBonus = null;
			depthSkillBonus = null;
			depthLunkerBonus = null;
			freshCatch = null;
			freshCatchNeedsPerfect = null;
			freshCatchDuration = null;
			freshCatchCarryWeight = null;
			freshCatchStaminaRegen = null;
			freshCatchEitrRegen = null;
			sizeFromSkill = null;
			qualityFromSize = null;
			qualityLossSteps = null;
			perfectUpgradesQuality = null;
			skillGainScale = null;
			skillGainOnLoss = null;
			skillFillBonus = null;
			treasureEnabled = null;
			treasureChance = null;
			treasureSkillBonus = null;
			treasureTierBonus = null;
			treasureFillRate = null;
			treasureDrainRate = null;
			treasureRollsMin = null;
			treasureRollsMax = null;
			treasureLoot = null;
			treasureGuard = null;
			treasureBlocklist = null;
			treasureKnownOnly = null;
			treasureBiomeLoot = null;
			treasureBiomeAddsToBase = null;
			treasureBiomeTables = new Dictionary<Biome, ConfigEntry<string>>();
			staminaScale = null;
			reelStaminaScale = null;
			fishFinder = null;
			soundEnabled = null;
			soundVolume = null;
			reelClipNames = null;
			shakeStrength = null;
			uiScale = null;
			fishIconScale = null;
			tutorial = null;
			uiAnchor = null;
			uiOffsetX = null;
			uiOffsetY = null;
		}
	}
}
namespace Hooked.UI
{
	public class BobberBarAudio
	{
		public static string[] ReelClips = new string[2] { "Ui_Click_01", "UI_Build_Default_01" };

		public static string[] GrabClips = new string[3] { "Fishing_PoleCastLine1", "UI_Equip_Start_M_01", "Ui_Click_01" };

		public static string[] BounceClips = new string[1] { "Ui_Click_01" };

		public static string[] TreasureUpClips = new string[3] { "Fishing_BaitSplash1", "UI_TreasurePile_Place_01", "Ui_Click_01" };

		public static string[] TreasureWonClips = new string[3] { "UI_TreasurePile_Place_01", "UI_Craft_Finish_01", "UI_LevelUp_S_01" };

		public static string[] CaughtClips = new string[2] { "UI_Craft_Finish_01", "UI_Pickup_M_01" };

		public static string[] PerfectClips = new string[2] { "UI_LevelUp_S_01", "UI_Craft_Finish_01" };

		public static string[] LostClips = new string[2] { "Fishing_LineSnap3", "UI_Drop_M_01" };

		private const float FastClickInterval = 0.07f;

		private const float SlowClickInterval = 0.3f;

		private const float WinningPitch = 1.25f;

		private const float LosingPitch = 0.8f;

		private const float ClickVolumeScale = 0.3f;

		private readonly AudioSource ratchet = Source(host);

		private readonly AudioSource oneShot = Source(host);

		private AudioClip? reelClip;

		private float clickTimer;

		private bool wasReeling;

		private bool wasAtEdge;

		private bool wasTreasureVisible;

		private bool wasTreasureCaught;

		private static bool Enabled
		{
			get
			{
				if (HookedPlugin.soundEnabled.Value == HookedPlugin.Toggle.On)
				{
					return HookedPlugin.soundVolume.Value > 0f;
				}
				return false;
			}
		}

		public BobberBarAudio(GameObject host)
		{
		}

		public void Begin()
		{
			wasReeling = false;
			wasTreasureVisible = false;
			wasTreasureCaught = false;
			wasAtEdge = true;
			clickTimer = 0f;
			if (reelClip == null)
			{
				reelClip = ResolveReel();
			}
		}

		public void Track(BobberBar model)
		{
			if (Enabled)
			{
				Ratchet(model.FishInBar);
				if (model.Reeling && !wasReeling)
				{
					Play(GrabClips);
				}
				bool flag = model.BarPosition <= 0.01f || model.BarPosition >= 568f - model.BarHeight - 0.01f;
				if (flag && !wasAtEdge)
				{
					Play(BounceClips, 0.5f);
				}
				if (model.TreasureVisible && !wasTreasureVisible)
				{
					Play(TreasureUpClips);
				}
				if (model.TreasureCaught && !wasTreasureCaught)
				{
					Play(TreasureWonClips);
				}
				wasReeling = model.Reeling;
				wasAtEdge = flag;
				wasTreasureVisible = model.TreasureVisible;
				wasTreasureCaught = model.TreasureCaught;
			}
		}

		public void Finish(BarResult result, bool perfect)
		{
			Stop();
			switch (result)
			{
			case BarResult.Caught:
				Play(perfect ? PerfectClips : CaughtClips);
				break;
			case BarResult.Lost:
				Play(LostClips);
				break;
			default:
				throw new ArgumentOutOfRangeException("result", result, null);
			case BarResult.Running:
				break;
			}
		}

		public void Stop()
		{
			ratchet.Stop();
		}

		private void Ratchet(bool winning)
		{
			if (!((Object)(object)reelClip == (Object)null))
			{
				clickTimer -= Time.deltaTime;
				if (!(clickTimer > 0f))
				{
					clickTimer = (winning ? 0.07f : 0.3f);
					ratchet.pitch = (winning ? 1.25f : 0.8f) + Random.Range(-0.05f, 0.05f);
					ratchet.PlayOneShot(reelClip, HookedPlugin.soundVolume.Value * 0.3f);
				}
			}
		}

		private static AudioClip? ResolveReel()
		{
			string value = HookedPlugin.reelClipNames.Value;
			string[] array = ((value.Trim().Length > 0) ? value.Split(new char[1] { ',' }) : ReelClips);
			string[] array2 = array;
			for (int i = 0; i < array2.Length; i++)
			{
				AudioClip val = GameAssets.Clip(array2[i].Trim());
				if (val != null)
				{
					HookedPlugin.HookedLogger.LogDebug((object)("Reel click using clip '" + ((Object)val).name + "'"));
					return val;
				}
			}
			HookedPlugin.HookedLogger.LogWarning((object)("No reel clip resolved, the reel will be silent. Tried: " + string.Join(", ", array)));
			return null;
		}

		private void Play(string[] candidates, float volumeScale = 1f)
		{
			AudioClip val = GameAssets.FirstClip(candidates);
			if (val != null)
			{
				oneShot.PlayOneShot(val, HookedPlugin.soundVolume.Value * volumeScale);
			}
		}

		private static AudioSource Source(GameObject host)
		{
			AudioSource val = host.AddComponent<AudioSource>();
			val.playOnAwake = false;
			val.loop = false;
			val.spatialBlend = 0f;
			val.volume = 1f;
			if ((Object)(object)AudioMan.instance != (Object)null)
			{
				val.outputAudioMixerGroup = AudioMan.instance.m_guiMixer;
			}
			return val;
		}
	}
	public class BobberBarView : MonoBehaviour
	{
		public static string[] TreasureIconItems = new string[4] { "Coins", "Amber", "Ruby", "AmberPearl" };

		public static string[] PanelSprites = new string[4] { "woodpanel_512x512", "panel_bkg_128_transparent", "panel_bkg_128", "panel_bkg" };

		public static string[] BorderSprites = new string[2] { "panel_border_128", "panel_border_bw_128" };

		public static string[] SunkenSprites = new string[3] { "InputFieldBackground", "item_background_sunken", "item_background" };

		private const float FrameWidth = 108f;

		private const float FramePadding = 12f;

		private const float TrackX = 14f;

		private const float TrackWidth = 48f;

		private const float BarWidth = 36f;

		private const float MeterX = 74f;

		private const float MeterWidth = 20f;

		private const float MarkerSize = 40f;

		private const float MarkerCenterOffset = 24f;

		private const float ChestMeterWidth = 40f;

		private const float ChestMeterHeight = 8f;

		private const float ScreenOffsetX = 0.104f;

		private const float ScreenOffsetY = -0.139f;

		private const float ResultShakeSeconds = 0.5f;

		private const float FadeSeconds = 0.25f;

		private const float PerfectFadeSeconds = 0.7f;

		private const float BorderThickness = 2f;

		private const float SliceShrink = 2f;

		private static readonly Color BorderColor = new Color(0.55f, 0.45f, 0.3f, 0.55f);

		private static readonly Color FrameBackColor = new Color(0f, 0f, 0f, 0.85f);

		private static readonly Color ChannelColor = new Color(0.04f, 0.05f, 0.07f, 0.85f);

		private static readonly Color BarColor = new Color(0.33f, 0.85f, 0.36f, 0.85f);

		private static readonly Color MeterBackColor = new Color(0.03f, 0.04f, 0.05f, 0.9f);

		private static readonly Color ChestMeterBackColor = new Color(0.41f, 0.41f, 0.41f, 0.5f);

		private static readonly Color ChestMeterColor = new Color(1f, 0.65f, 0f, 1f);

		private static readonly Color TreasureColor = new Color(0.93f, 0.78f, 0.31f, 1f);

		private static readonly Color LunkerColor = new Color(1f, 0.85f, 0.45f, 1f);

		private static readonly Color EmptyColor = new Color(0.92f, 0.24f, 0.2f, 1f);

		private static readonly Color FullColor = new Color(0.34f, 0.92f, 0.36f, 1f);

		private static BobberBarView? instance;

		private static Sprite? treasureIcon;

		private RectTransform frame;

		private RectTransform track;

		private RectTransform bar;

		private RectTransform fish;

		private RectTransform treasure;

		private RectTransform chestMeter;

		private RectTransform chestFill;

		private RectTransform catchMeter;

		private RectTransform catchFill;

		private Image catchFillImage;

		private Image fishImage;

		private Image treasureImage;

		private CanvasGroup perfectBadge;

		private GameObject lunkerBadge;

		private GameObject tutorial;

		private Text tutorialText;

		private CanvasGroup group;

		private BobberBarAudio audio;

		private float scale;

		private float trackPixels;

		private Vector2 anchor;

		private float outroTimer;

		private float perfectAlpha;

		private bool chestShown;

		private bool chestMeterShown;

		public static void Show(FishingSession session)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if (!UIRoot.IsReady)
			{
				HookedPlugin.HookedLogger.LogWarning((object)"GUI root isn't up yet, running this catch without a bar.");
				return;
			}
			if (instance == null)
			{
				instance = Build();
			}
			((Component)instance).gameObject.SetActive(true);
			instance.fishImage.sprite = session.Icon;
			((Graphic)instance.fishImage).color = (((Object)(object)session.Icon == (Object)null) ? TreasureColor : (session.Lunker ? LunkerColor : Color.white));
			instance.lunkerBadge.SetActive(session.Lunker);
			instance.DressTreasure();
			instance.chestShown = false;
			instance.chestMeterShown = false;
			((Component)instance.treasure).gameObject.SetActive(false);
			((Component)instance.chestMeter).gameObject.SetActive(false);
			((Component)instance.perfectBadge).gameObject.SetActive(true);
			instance.perfectAlpha = 1f;
			instance.perfectBadge.alpha = 1f;
			instance.outroTimer = 0f;
			instance.group.alpha = 1f;
			instance.DressTutorial(session);
			instance.Layout(session.Bar);
			instance.audio.Begin();
		}

		public static void Finish(BarResult result, bool perfect)
		{
			if (!((Object)(object)instance == (Object)null))
			{
				if (result == BarResult.Running)
				{
					Hide();
					return;
				}
				instance.outroTimer = 0.75f;
				instance.perfectBadge.alpha = ((result == BarResult.Caught && perfect) ? 1f : 0f);
				instance.tutorial.SetActive(false);
				instance.audio.Finish(result, perfect);
			}
		}

		public static void Hide()
		{
			if ((Object)(object)instance != (Object)null)
			{
				instance.audio.Stop();
				instance.outroTimer = 0f;
				((Component)instance).gameObject.SetActive(false);
			}
		}

		private void Update()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: 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_01c3: 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_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			if (outroTimer > 0f)
			{
				Outro();
				return;
			}
			FishingSession active = FishingSession.Active;
			if (active == null)
			{
				Hide();
				return;
			}
			BobberBar bobberBar = active.Bar;
			float value = HookedPlugin.shakeStrength.Value;
			bar.anchoredPosition = new Vector2(0f, (0f - bobberBar.BarPosition) * scale) + (bobberBar.FishInBar ? Vector2.zero : Jitter(value));
			fish.anchoredPosition = new Vector2(0f, (0f - (bobberBar.FishPosition + 24f)) * scale) + (bobberBar.FishInBar ? Jitter(value) : Vector2.zero);
			catchFill.sizeDelta = new Vector2(0f, trackPixels * bobberBar.Progress);
			((Graphic)catchFillImage).color = Color.Lerp(EmptyColor, FullColor, bobberBar.Progress);
			float num = (bobberBar.Perfect ? 1f : Mathf.Max(0f, perfectAlpha - Time.deltaTime / 0.7f));
			if (!Mathf.Approximately(num, perfectAlpha))
			{
				perfectAlpha = num;
				perfectBadge.alpha = num;
			}
			audio.Track(bobberBar);
			if (bobberBar.HasTreasure)
			{
				bool treasureVisible = bobberBar.TreasureVisible;
				bool flag = bobberBar.TreasureInBar && !bobberBar.TreasureCaught;
				if (treasureVisible != chestShown)
				{
					chestShown = treasureVisible;
					((Component)treasure).gameObject.SetActive(treasureVisible);
				}
				treasure.anchoredPosition = new Vector2(0f, (0f - (bobberBar.TreasurePosition + 24f)) * scale) + (flag ? Jitter(value * 2f) : Vector2.zero);
				((Transform)treasure).localScale = Vector3.one * Mathf.Max(0.01f, bobberBar.TreasureScale);
				bool flag2 = treasureVisible && bobberBar.TreasureProgress > 0f && !bobberBar.TreasureCaught;
				if (flag2 != chestMeterShown)
				{
					chestMeterShown = flag2;
					((Component)chestMeter).gameObject.SetActive(flag2);
				}
				chestMeter.anchoredPosition = new Vector2(0f, (0f - bobberBar.TreasurePosition) * scale);
				chestFill.offsetMax = new Vector2(-40f * scale * (1f - bobberBar.TreasureProgress), 0f);
			}
		}

		private void Outro()
		{
			//IL_002b: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			outroTimer -= Time.deltaTime;
			if (outroTimer <= 0f)
			{
				Hide();
				return;
			}
			RectTransform val = (RectTransform)((Component)this).transform;
			bool flag = outroTimer > 0.25f;
			val.anchoredPosition = anchor + (flag ? Jitter(HookedPlugin.shakeStrength.Value) : Vector2.zero);
			group.alpha = (flag ? 1f : (outroTimer / 0.25f));
		}

		private void DressTreasure()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (treasureIcon == null)
			{
				treasureIcon = FindTreasureIcon();
			}
			treasureImage.sprite = treasureIcon;
			((Graphic)treasureImage).color = (((Object)(object)treasureIcon == (Object)null) ? TreasureColor : Color.white);
		}

		private void DressTutorial(FishingSession session)
		{
			bool flag = HookedPlugin.tutorial.Value switch
			{
				HookedPlugin.TutorialMode.Always => true, 
				HookedPlugin.TutorialMode.Beginner => session.SkillLevel < HookedPlugin.beginnerSkillLevel.Value, 
				_ => false, 
			};
			tutorial.SetActive(flag);
			if (flag)
			{
				tutorialText.text = Localization.instance.Localize("[<color=yellow><b>$KEY_Block</b></color>] $hooked_tut_raise\n$hooked_tut_lower\n\n<color=#7ACC5E>$hooked_tut_keep</color>\n<color=#FFA13C>$hooked_tut_perfect</color>");
			}
		}

		private static Sprite? FindTreasureIcon()
		{
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return null;
			}
			string[] treasureIconItems = TreasureIconItems;
			foreach (string text in treasureIconItems)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(text);
				if (itemPrefab != null)
				{
					ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
					if (component != null)
					{
						return component.m_itemData.GetIcon();
					}
				}
			}
			return null;
		}

		private static Vector2 Jitter(float strength)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (!(strength <= 0f))
			{
				return new Vector2(Random.Range(0f - strength, strength), Random.Range(0f - strength, strength));
			}
			return Vector2.zero;
		}

		private void Layout(BobberBar model)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: 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_006d: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: 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_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: 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_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Expected O, but got Unknown
			float num = (float)Screen.height / 616f;
			scale = Mathf.Min(HookedPlugin.uiScale.Value, num);
			trackPixels = 568f * scale;
			RectTransform val = (RectTransform)((Component)this).transform;
			bool flag = HookedPlugin.uiAnchor.Value == HookedPlugin.BarAnchor.Left;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			val.anchorMax = val2;
			val.anchorMin = val2;
			val.pivot = new Vector2(0.5f, 0.5f);
			val.sizeDelta = new Vector2(108f * scale, trackPixels + 24f * scale);
			anchor = new Vector2((flag ? (-1f) : 1f) * 0.104f * (float)Screen.width + HookedPlugin.uiOffsetX.Value, -0.139f * (float)Screen.height + HookedPlugin.uiOffsetY.Value);
			val.anchoredPosition = anchor;
			Column(frame, 0f, 108f * scale, 0f);
			Column(track, 14f * scale, 48f * scale, 12f * scale);
			Column(catchMeter, 74f * scale, 20f * scale, 12f * scale);
			bar.sizeDelta = new Vector2(36f * scale, model.BarHeight * scale);
			treasure.sizeDelta = new Vector2(40f * scale, 40f * scale);
			chestMeter.sizeDelta = new Vector2(40f * scale, 8f * scale);
			float num2 = 40f * HookedPlugin.fishIconScale.Value * scale;
			fish.sizeDelta = new Vector2(num2, num2);
			RectTransform val3 = (RectTransform)((Component)perfectBadge).transform;
			val3.anchoredPosition = new Vector2(54f * scale, 0.6f);
			val3.sizeDelta = new Vector2(108f * scale, 28f);
			RectTransform val4 = (RectTransform)lunkerBadge.transform;
			val4.anchoredPosition = new Vector2(54f * scale, -0.6f);
			val4.sizeDelta = new Vector2(108f * scale, 28f);
			RectTransform val5 = (RectTransform)tutorial.transform;
			((Vector2)(ref val2))..ctor(flag ? 1f : 0f, 0.5f);
			val5.anchorMax = val2;
			val5.anchorMin = val2;
			val5.pivot = new Vector2(flag ? 0f : 1f, 0.5f);
			val5.anchoredPosition = new Vector2(flag ? 16f : (-16f), 0f);
			UILayout.ClampToCanvas(val5);
		}

		private static BobberBarView Build()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_00b9: 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_00f1: 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_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: 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_0206: 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_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: 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)
			GameObject val = new GameObject("Hooked_BobberBar", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(UIRoot.Front, false);
			BobberBarView bobberBarView = val.AddComponent<BobberBarView>();
			bobberBarView.group = val.AddComponent<CanvasGroup>();
			bobberBarView.group.interactable = false;
			bobberBarView.group.blocksRaycasts = false;
			bobberBarView.audio = new BobberBarAudio(val);
			bobberBarView.frame = Plate("Frame", val.transform);
			Styler.Lit(((Component)bobberBarView.frame).gameObject);
			bobberBarView.track = ((Graphic)Sunken("Track", (Transform)(object)bobberBarView.frame)).rectTransform;
			bobberBarView.bar = Marker("Bar", (Transform)(object)bobberBarView.track, BarColor, centered: false);
			bobberBarView.chestMeter = Marker("ChestMeter", (Transform)(object)bobberBarView.track, ChestMeterBackColor, centered: false);
			bobberBarView.chestFill = ((Graphic)Rect("Fill", (Transform)(object)bobberBarView.chestMeter, ChestMeterColor)).rectTransform;
			Stretch(bobberBarView.chestFill);
			bobberBarView.treasure = Marker("Treasure", (Transform)(object)bobberBarView.track, TreasureColor, centered: true);
			bobberBarView.treasureImage = ((Component)bobberBarView.treasure).GetComponent<Image>();
			bobberBarView.treasureImage.preserveAspect = true;
			bobberBarView.fish = Marker("Fish", (Transform)(object)bobberBarView.track, Color.white, centered: true);
			bobberBarView.fishImage = ((Component)bobberBarView.fish).GetComponent<Image>();
			bobberBarView.fishImage.preserveAspect = true;
			bobberBarView.catchMeter = ((Graphic)Sunken("CatchMeter", (Transform)(object)bobberBarView.frame)).rectTransform;
			bobberBarView.catchFill = ((Graphic)Rect("Fill", (Transform)(object)bobberBarView.catchMeter, Color.white)).rectTransform;
			bobberBarView.catchFill.anchorMin = new Vector2(0f, 0f);
			bobberBarView.catchFill.anchorMax = new Vector2(1f, 0f);
			bobberBarView.catchFill.pivot = new Vector2(0.5f, 0f);
			bobberBarView.catchFill.anchoredPosition = Vector2.zero;
			bobberBarView.catchFill.sizeDelta = Vector2.zero;
			bobberBarView.catchFillImage = ((Component)bobberBarView.catchFill).GetComponent<Image>();
			RectTransform val2 = Badge("PerfectBadge", val.transform, "$hooked_perfect", GameColors.Orange, new Vector2(0f, 1f), new Vector2(0.5f, 0f));
			bobberBarView.perfectBadge = ((Component)val2).gameObject.AddComponent<CanvasGroup>();
			bobberBarView.lunkerBadge = ((Component)Badge("LunkerBadge", val.transform, "$hooked_lunker", LunkerColor, new Vector2(0f, 0f), new Vector2(0.5f, 1f))).gameObject;
			RectTransform val3 = Plate("Tutorial", val.transform);
			Styler.Lit(((Component)val3).gameObject);
			val3.sizeDelta = new Vector2(270f, 170f);
			bobberBarView.tutorial = ((Component)val3).gameObject;
			bobberBarView.tutorialText = UIFactory.Text("Text", (Transform)(object)val3, "", TextRole.Label, 16, (TextAnchor)3);
			((Graphic)bobberBarView.tutorialText).raycastTarget = false;
			Skin.Outline(((Component)bobberBarView.tutorialText).gameObject);
			Stretch(((Graphic)bobberBarView.tutorialText).rectTransform, 18f);
			return bobberBarView;
		}

		private static RectTransform Badge(string name, Transform parent, string key, Color color, Vector2 anchor, Vector2 pivot)
		{
			//IL_000a: 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)
			//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_003c: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Plate(name, parent);
			Vector2 anchorMin = (val.anchorMax = anchor);
			val.anchorMin = anchorMin;
			val.pivot = pivot;
			Text obj = UIFactory.Text("Text", (Transform)(object)val, Localization.instance.Localize(key), TextRole.Title, 20, (TextAnchor)4);
			((Graphic)obj).color = color;
			((Graphic)obj).raycastTarget = false;
			obj.horizontalOverflow = (HorizontalWrapMode)1;
			Skin.Outline(((Component)obj).gameObject);
			Stretch(((Graphic)obj).rectTransform);
			return val;
		}

		internal static RectTransform Plate(string name, Transform parent)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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)
			Image val = Rect(name, parent, FrameBackColor);
			if (name == "Frame")
			{
				Skinned(val, PanelSprites, Color.white);
				return ((Graphic)val).rectTransform;
			}
			Image obj = Rect("Border", ((Component)val).transform, BorderColor);
			Skinned(obj, BorderSprites, Color.white);
			Stretch(((Graphic)obj).rectTransform);
			return ((Graphic)val).rectTransform;
		}

		private static Image Sunken(string name, Transform parent)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			Image obj = Rect(name, parent, ChannelColor);
			Skinned(obj, SunkenSprites);
			return obj;
		}

		private static void Skinned(Image image, string[] candidates, Color? tint = null)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Sprite val = GameAssets.FirstSprite(candidates);
			if (val != null)
			{
				image.sprite = val;
				image.type = (Type)1;
				image.pixelsPerUnitMultiplier = 2f;
				if (tint.HasValue)
				{
					Color valueOrDefault = tint.GetValueOrDefault();
					((Graphic)image).color = valueOrDefault;
				}
			}
		}

		private static Image Rect(string name, Transform parent, Color color)
		{
			//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_0046: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = color;
			((Graphic)component).material = null;
			((Graphic)component).raycastTarget = false;
			return component;
		}

		private static RectTransform Marker(string name, Transform parent, Color color, bool centered)
		{
			//IL_0002: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			RectTransform rectTransform = ((Graphic)Rect(name, parent, color)).rectTransform;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 1f);
			rectTransform.anchorMax = val;
			rectTransform.anchorMin = val;
			rectTransform.pivot = new Vector2(0.5f, centered ? 0.5f : 1f);
			return rectTransform;
		}

		internal static void Stretch(RectTransform rect, float inset = 0f)
		{
			//IL_0001: 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_0019: 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)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.one;
			rect.offsetMin = new Vector2(inset, inset);
			rect.offsetMax = new Vector2(0f - inset, 0f - inset);
		}

		private static void Column(RectTransform rect, float offsetX, float width, float inset)
		{
			//IL_000b: 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_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)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = new Vector2(0f, 0f);
			rect.anchorMax = new Vector2(0f, 1f);
			rect.pivot = new Vector2(0f, 0.5f);
			rect.sizeDelta = new Vector2(width, (0f - inset) * 2f);
			rect.anchoredPosition = new Vector2(offsetX, 0f);
		}
	}
	public class CastStatusView : MonoBehaviour
	{
		private struct Reading
		{
			public bool Incoming;

			public int Interested;

			public int InRange;

			public int TooShallow;

			public float Nearest;
		}

		private const float PollSeconds = 0.4f;

		private const float ScreenOffsetX = 0.104f;

		private const float ScreenOffsetY = -0.139f;

		private static readonly Color Incoming = new Color(0.45f, 0.95f, 0.45f, 1f);

		private static readonly Color Nearby = new Color(0.78f, 0.86f, 0.72f, 1f);

		private static readonly Color WrongBait = new Color(1f, 0.75f, 0.35f, 1f);

		private static readonly Color Empty = new Color(0.78f, 0.78f, 0.78f, 1f);

		private static CastStatusView? instance;

		private Text label;

		private CanvasGroup group;

		private float timer;

		private bool shown;

		public static void Ensure()
		{
			if ((Object)(object)instance == (Object)null && UIRoot.IsReady)
			{
				instance = Build();
			}
		}

		private void Update()
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: 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)
			timer -= Time.deltaTime;
			if (timer > 0f)
			{
				return;
			}
			timer = 0.4f;
			if (HookedPlugin.fishFinder.Value != HookedPlugin.Toggle.Off && !((Object)(object)Player.m_localPlayer == (Object)null) && FishingSession.Active == null)
			{
				FishingFloat val = LocalFloat();
				if (val != null)
				{
					if (!val.IsInWater() || (Object)(object)val.GetCatch() != (Object)null)
					{
						Show(visible: false);
						return;
					}
					Reading reading = Count(val);
					Show(visible: true);
					Layout();
					if (reading.Incoming)
					{
						((Graphic)label).color = Incoming;
						label.text = Localization.instance.Localize("$hooked_finder_incoming");
					}
					else if (reading.TooShallow > 0 && reading.Interested == 0)
					{
						((Graphic)label).color = WrongBait;
						label.text = Localization.instance.Localize("$hooked_finder_shallow");
					}
					else if (reading.Interested > 0)
					{
						((Graphic)label).color = Nearby;
						label.text = Localization.instance.Localize("$hooked_finder_nearby", new string[2]
						{
							reading.Interested.ToString(),
							Mathf.RoundToInt(reading.Nearest).ToString()
						});
					}
					else if (reading.InRange > 0)
					{
						((Graphic)label).color = WrongBait;
						label.text = Localization.instance.Localize("$hooked_finder_wrongbait", new string[1] { reading.InRange.ToString() });
					}
					else
					{
						((Graphic)label).color = Empty;
						label.text = Localization.instance.Localize("$hooked_finder_empty");
					}
					return;
				}
			}
			Show(visible: false);
		}

		private static Reading Count(FishingFloat bobber)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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)
			Reading result = default(Reading);
			string bait = bobber.GetBait();
			Character owner = bobber.GetOwner();
			Player player = (Player)(object)((owner is Player) ? owner : null);
			Vector3 position = ((Component)bobber).transform.position;
			float range = bobber.m_range;
			float num = Waters.Depth(position);
			foreach (IMonoUpdater instance in Fish.Instances)
			{
				Fish val = (Fish)(object)((instance is Fish) ? instance : null);
				if (val == null || (Object)(object)((Component)val).transform == (Object)null)
				{
					continue;
				}
				if ((Object)(object)val.m_waypointFF == (Object)(object)bobber)
				{
					result.Incoming = true;
				}
				float num2 = Vector3.Distance(((Component)val).transform.position, position);
				if (num2 > range)
				{
					continue;
				}
				result.InRange++;
				if (!BaitTackle.Accepts(val, bait, player))
				{
					continue;
				}
				if (num < val.m_minDepth)
				{
					result.TooShallow++;
					continue;
				}
				if (result.Interested == 0 || num2 < result.Nearest)
				{
					result.Nearest = num2;
				}
				result.Interested++;
			}
			return result;
		}

		private static FishingFloat? LocalFloat()
		{
			foreach (FishingFloat allInstance in FishingFloat.GetAllInstances())
			{
				if ((Object)(object)allInstance != (Object)null && (Object)(object)allInstance.GetOwner() == (Object)(object)Player.m_localPlayer)
				{
					return allInstance;
				}
			}
			return null;
		}

		private void Show(bool visible)
		{
			if (visible != shown)
			{
				shown = visible;
				group.alpha = (visible ? 1f : 0f);
			}
		}

		private void Layout()
		{
			//IL_0006: 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)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			RectTransform val = (RectTransform)((Component)this).transform;
			bool flag = HookedPlugin.uiAnchor.Value == HookedPlugin.BarAnchor.Left;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			val.anchorMax = val2;
			val.anchorMin = val2;
			val.pivot = new Vector2(0.5f, 0.5f);
			val.sizeDelta = new Vector2(230f, 34f);
			val.anchoredPosition = new Vector2((flag ? (-1f) : 1f) * 0.104f * (float)Screen.width + HookedPlugin.uiOffsetX.Value, -0.139f * (float)Screen.height + HookedPlugin.uiOffsetY.Value);
			UILayout.ClampToCanvas(val);
		}

		private static CastStatusView Build()
		{
			RectTransform val = BobberBarView.Plate("Hooked_CastStatus", UIRoot.Front);
			Styler.Lit(((Component)val).gameObject);
			CastStatusView castStatusView = ((Component)val).gameObject.AddComponent<CastStatusView>();
			castStatusView.group = ((Component)val).gameObject.AddComponent<CanvasGroup>();
			castStatusView.group.interactable = false;
			castStatusView.group.blocksRaycasts = false;
			castStatusView.group.alpha = 0f;
			castStatusView.label = UIFactory.Text("Text", (Transform)(object)val, "", TextRole.Label, 16, (TextAnchor)4);
			((Graphic)castStatusView.label).raycastTarget = false;
			castStatusView.label.horizontalOverflow = (HorizontalWrapMode)1;
			Skin.Outline(((Component)castStatusView.label).gameObject);
			BobberBarView.Stretch(((Graphic)castStatusView.label).rectTransform, 6f);
			return castStatusView;
		}
	}
}
namespace Hooked.Fishing
{
	public readonly struct Tackle
	{
		public readonly float BarBonus;

		public readonly float DrainScale;

		public readonly float ClingStrength;

		public readonly float BounceScale;

		public readonly float DoubleChance;

		public readonly int QualityBonus;

		public readonly bool TreasureHunter;

		public Tackle(float barBonus = 0f, float drainScale = 1f, float clingStrength = 0f, float bounceScale = 1f, float doubleChance = 0f, int qualityBonus = 0, bool treasureHunter = false)
		{
			BarBonus = barBonus;
			DrainScale = drainScale;
			ClingStrength = clingStrength;
			BounceScale = bounceScale;
			DoubleChance = doubleChance;
			QualityBonus = qualityBonus;
			TreasureHunter = treasureHunter;
		}
	}
	public static class BaitTackle
	{
		public static readonly Tackle Plain = default(Tackle);

		private static readonly Dictionary<string, Tackle> Baits = new Dictionary<string, Tackle>(StringComparer.Ordinal)
		{
			["FishingBaitForest"] = new Tackle(24f),
			["FishingBaitSwamp"] = new Tackle(0f, 2f / 3f),
			["FishingBaitCave"] = new Tackle(0f, 1f, 0f, 1f, 0f, 1),
			["FishingBaitOcean"] = new Tackle(0f, 1f, 0f, 0.1f),
			["FishingBaitPlains"] = new Tackle(0f, 1f, 0.2f),
			["FishingBaitMistlands"] = new Tackle(0f, 1f, 0f, 1f, 0f, 0, treasureHunter: true),
			["FishingBaitAshlands"] = new Tackle(0f, 1f, 0f, 1f, 0.25f),
			["FishingBaitDeepNorth"] = new Tackle(24f, 2f / 3f)
		};

		public static Tackle For(string? bait)
		{
			if (HookedPlugin.baitTackle.Value == HookedPlugin.Toggle.Off || bait == null)
			{
				return Plain;
			}
			if (!Baits.TryGetValue(bait, out var value))
			{
				return Plain;
			}
			return value;
		}

		public static bool Accepts(Fish fish, string? bait, Player? player)
		{
			if (bait == null)
			{
				return false;
			}
			if (IsNative(fish, bait))
			{
				return true;
			}
			if (HookedPlugin.flexibleBait.Value == HookedPlugin.Toggle.On && (Object)(object)player != (Object)null)
			{
				return UnlockedChance(fish, player) > 0f;
			}
			return false;
		}

		public static bool IsNative(Fish fish, string? bait)
		{
			if (bait == null)
			{
				return false;
			}
			foreach (BaitSetting bait2 in fish.m_baits)
			{
				if ((Object)(object)bait2.m_bait != (Object)null && ((Object)bait2.m_bait).name == bait)
				{
					return true;
				}
			}
			return false;
		}

		public static float UnlockedChance(Fish fish, Player player)
		{
			float num = 0f;
			foreach (BaitSetting bait in fish.m_baits)
			{
				if ((Object)(object)bait.m_bait != (Object)null && player.IsKnownMaterial(bait.m_bait.m_itemData.m_shared.m_name))
				{
					num = Mathf.Max(num, bait.m_chance);
				}
			}
			return num;
		}
	}
	public enum FishMotion
	{
		Mixed,
		Dart,
		Smooth,
		Sinker,
		Floater
	}
	public enum BarResult
	{
		Running,
		Caught,
		Lost
	}
	public class BobberBar
	{
		public const float TrackHeight = 568f;

		public const float FishTrackHeight = 548f;

		public const float MinDifficulty = 15f;

		public const float MaxDifficulty = 100f;

		private const float StepSeconds = 1f / 60f;

		private const float SizeReductionSeconds = 0.8f;

		public float Difficulty;

		public float Gravity = 0.25f;

		public float InBarGravityScale = 0.6f;

		public float FillRate = 0.002f;

		public float DrainRate = 0.003f;

		public float TreasureFillRate = 0.0135f;

		public float TreasureDrainRate = 0.01f;

		public bool TreasureProtectsFish;

		public float WanderScale = 1f;

		public float Cling;

		public float Bounce = 1f;

		public readonly FishMotion Motion;

		public readonly float BarHeight;

		public readonly bool HasTreasure;

		private float fishSpeed;

		private float fishTarget;

		private float floaterSinker;

		private float barSpeed;

		private float treasureTimer;

		private float sizeTimer = 0.8f;

		private float accumulator;

		private bool fishHasBeenInBar;

		public float FishPosition { get; private set; } = 508f;

		public float BarPosition { get; private set; }

		public float Progress { get; private set; }

		public float PeakProgress { get; private set; }

		public float TreasurePosition { get; private set; }

		public float TreasureProgress { get; private set; }

		public float TreasureScale { get; private set; }

		public bool TreasureCaught { get; private set; }

		public bool TreasureVisible => TreasureScale > 0f;

		public bool TreasureInBar { get; private set; }

		public bool FishInBar { get; private set; }

		public bool Reeling { get; private set; }

		public bool Perfect { get; private set; } = true;

		public BarResult Result { get; private set; }

		public int SizeLossSteps { get; private set; }

		public BobberBar(float difficulty, FishMotion motion, float barHeight, bool treasure, float startProgress)
		{
			Difficulty = Mathf.Clamp(difficulty, 15f, 100f);
			Motion = motion;
			BarHeight = Mathf.Clamp(barHeight, 16f, 568f);
			HasTreasure = treasure;
			BarPosition = 568f - BarHeight;
			Progress = Mathf.Clamp01(startProgress);
			fishTarget = (100f - Difficulty) / 100f * 548f;
			treasureTimer = Random.Range(1f, 3f);
		}

		public void Update(bool reeling, float deltaTime)
		{
			if (Result != BarResult.Running)
			{
				return;
			}
			accumulator += Mathf.Min(deltaTime, 0.25f);
			while (accumulator >= 1f / 60f)
			{
				accumulator -= 1f / 60f;
				MoveFish();
				MoveBar(reeling);
				MoveTreasure();
				Score();
				if (Result != BarResult.Running)
				{
					break;
				}
			}
		}

		private void MoveFish()
		{
			if (Chance(Difficulty * ((Motion == FishMotion.Smooth) ? 20f : 1f) / 4000f * WanderScale) && (Motion != FishMotion.Smooth || fishTarget < 0f))
			{
				float num = 548f - FishPosition;
				float num2 = Mathf.Min(99f, Difficulty + (float)Random.Range(10, 45)) / 100f;
				fishTarget = FishPosition + (float)Random.Range(-(int)FishPosition, (int)num) * num2;
			}
			floaterSinker = Motion switch
			{
				FishMotion.Floater => Mathf.Max(floaterSinker - 0.01f, -1.5f), 
				FishMotion.Sinker => Mathf.Min(floaterSinker + 0.01f, 1.5f), 
				_ => floaterSinker, 
			};
			if (Mathf.Abs(FishPosition - fishTarget) > 3f && fishTarget >= 0f)
			{
				float num3 = (fishTarget - FishPosition) / ((float)Random.Range(10, 30) + (100f - Mathf.Min(100f, Difficulty)));
				fishSpeed += (num3 - fishSpeed) / 5f;
			}
			else if (Motion != FishMotion.Smooth && Chance(Difficulty / 2000f * WanderScale))
			{
				fishTarget = FishPosition + (float)(Chance(0.5f) ? Random.Range(-100, -51) : Random.Range(50, 101));
			}
			else
			{
				fishTarget = -1f;
			}
			if (Motion == FishMotion.Dart && Chance(Difficulty / 1000f * WanderScale))
			{
				int num4 = (int)Difficulty * 2;
				fishTarget = FishPosition + (float)(Chance(0.5f) ? Random.Range(-100 - num4, -51) : Random.Range(50, 101 + num4));
			}
			fishTarget = Mathf.Clamp(fishTarget, -1f, 548f);
			FishPosition = Mathf.Clamp(FishPosition + fishSpeed + floaterSinker, 0f, 532f);
		}

		private void MoveBar(bool reeling)
		{
			Reeling = reeling;
			FishInBar = FishPosition + 12f <= BarPosition - 32f + BarHeight && FishPosition - 16f >= BarPosition - 32f;
			if (FishPosition >= 548f - BarHeight && BarPosition >= 568f - BarHeight - 4f)
			{
				FishInBar = true;
			}
			float num = (reeling ? (0f - Gravity) : Gravity);
			if (reeling && (BarPosition <= 0f || BarPosition >= 568f - BarHeight))
			{
				barSpeed = 0f;
			}
			if (FishInBar)
			{
				num *= InBarGravityScale;
				if (Cling > 0f)
				{
					barSpeed += ((FishPosition + 16f < BarPosition + BarHeight / 2f) ? (0f - Cling) : Cling);
				}
			}
			barSpeed += num;
			BarPosition += barSpeed;
			if (BarPosition + BarHeight > 568f)
			{
				BarPosition = 568f - BarHeight;
				barSpeed = (0f - barSpeed) * 2f / 3f * Bounce;
			}
			else if (BarPosition < 0f)
			{
				BarPosition = 0f;
				barSpeed = (0f - barSpeed) * 2f / 3f;
			}
		}

		private void MoveTreasure()
		{
			if (!HasTreasure)
			{
				return;
			}
			float num = treasureTimer;
			treasureTimer -= 1f / 60f;
			if (treasureTimer > 0f)
			{
				return;
			}
			if (TreasureScale < 1f && !TreasureCaught)
			{
				if (num > 0f)
				{
					bool num2 = BarPosition > 284f;
					float num3 = (num2 ? 8f : Mathf.Min(528f, BarPosition + BarHeight));
					float num4 = (num2 ? (BarPosition - 20f) : 500f);
					TreasurePosition = Random.Range(Mathf.Min(num3, num4), Mathf.Max(num3, num4));
				}
				TreasureScale = Mathf.Min(1f, TreasureScale + 0.1f);
			}
			TreasureInBar = TreasurePosition + 12f <= BarPosition - 32f + BarHeight && TreasurePosition - 16f >= BarPosition - 32f;
			if (TreasureInBar && !TreasureCaught)
			{
				TreasureProgress += TreasureFillRate;
				if (TreasureProgress >= 1f)
				{
					TreasureProgress = 1f;
					TreasureCaught = true;
				}
			}
			else if (TreasureCaught)
			{
				TreasureScale = Mathf.Max(0f, TreasureScale - 0.1f);
			}
			else
			{
				TreasureProgress = Mathf.Max(0f, TreasureProgress - TreasureDrainRate);
			}
		}

		private void Score()
		{
			if (FishInBar)
			{
				Progress += FillRate;
				fishHasBeenInBar = true;
			}
			else if (!TreasureProtectsFish || !TreasureInBar || TreasureCaught)
			{
				if (fishHasBeenInBar)
				{
					Perfect = false;
				}
				sizeTimer -= 1f / 60f;
				if (sizeTimer <= 0f)
				{
					sizeTimer = 0.8f;
					int sizeLossSteps = SizeLossSteps + 1;
					SizeLossSteps = sizeLossSteps;
				}
				Progress -= DrainRate;
			}
			Progress = Mathf.Clamp01(Progress);
			PeakProgress = Mathf.Max(PeakProgress, Progress);
			float progress = Progress;
			BarResult result = ((progress <= 0f) ? BarResult.Lost : ((progress >= 1f) ? BarResult.Caught : Result));
			Result = result;
		}

		private static bool Chance(float probability)
		{
			return Random.value < probability;
		}
	}
	public readonly struct FishProfile
	{
		public readonly float Difficulty;

		public readonly FishMotion Motion;

		public FishProfile(float difficulty, FishMotion motion)
		{
			Difficulty = difficulty;
			Motion = motion;
		}
	}
	public static class FishTuning
	{
		private readonly struct Override
		{
			public readonly float Difficulty;

			public readonly FishMotion? Motion;

			public Override(float difficulty, FishMotion? motion)
			{
				Difficulty = difficulty;
				Motion = motion;
			}
		}

		private const float EasiestEscapeStamina = 10f;

		private const float HardestEscapeStamina = 50f;

		private const float EasiestDifficulty = 32f;

		private const float DifficultyCurve = 1.35f;

		private static readonly Dictionary<string, Override> Overrides = new Dictionary<string, Override>(StringComparer.OrdinalIgnoreCase);

		public static FishProfile For(Fish fish)
		{
			string prefabName = Utils.GetPrefabName(((Component)fish).gameObject);
			if (!Overrides.TryGetValue(prefabName, out var value))
			{
				return new FishProfile(Difficulty(fish), Motion(fish));
			}
			return new FishProfile(value.Difficulty, value.Motion ?? Motion(fish));
		}

		private static float Difficulty(Fish fish)
		{
			ItemDrop component = ((Component)fish).GetComponent<ItemDrop>();
			int num = ((component == null) ? 1 : Mathf.Max(1, component.m_itemData.m_quality));
			float num2 = ((fish.m_escapeStaminaUse > 0f) ? fish.m_escapeStaminaUse : (fish.m_staminaUse * 2.5f));
			float num3 = Mathf.InverseLerp(10f, 50f, num2);
			return Mathf.Clamp((Mathf.Lerp(32f, 100f, Mathf.Pow(num3, 1.35f)) + (float)(num - 1) * 5f) * HookedPlugin.difficultyScale.Value, 15f, 100f);
		}

		private static FishMotion Motion(Fish fish)
		{
			if (fish.m_minDepth >= 4f)
			{
				return FishMotion.Sinker;
			}
			if (fish.m_maxDepth <= 2f)
			{
				return FishMotion.Floater;
			}
			if (fish.m_speed >= 8f)
			{
				return FishMotion.Dart;
			}
			if (!(fish.m_speed <= 2.5f))
			{
				return FishMotion.Mixed;
			}
			return FishMotion.Smooth;
		}

		public static void ParseOverrides(string config)
		{
			Overrides.Clear();
			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 != 2 || array2[0].Trim().Length == 0)
				{
					HookedPlugin.HookedLogger.LogWarning((object)("Ignoring fish override '" + text + "': expected 'PrefabName=difficulty' or 'PrefabName=difficulty:pattern'."));
					continue;
				}
				string[] array3 = array2[1].Split(new char[1] { ':' });
				if (!float.TryParse(array3[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					HookedPlugin.HookedLogger.LogWarning((object)("Ignoring fish override '" + text + "': '" + array3[0].Trim() + "' is not a number."));
					continue;
				}
				FishMotion? motion = null;
				if (array3.Length > 1)
				{
					if (!Enum.TryParse<FishMotion>(array3[1].Trim(), ignoreCase: true, out var result2))
					{
						HookedPlugin.HookedLogger.LogWarning((object)("Ignoring fish override '" + text + "': '" + array3[1].Trim() + "' is not a swim pattern."));
						continue;
					}
					motion = result2;
				}
				Overrides[array2[0].Trim()] =