Decompiled source of Hunters Instinct v1.0.0

plugins/HuntersInstinct.dll

Decompiled 4 days 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.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;
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: AssemblyFileVersion("1.0.0")]
[assembly: Guid("87F8C644-7EBA-4E13-8582-41061532ED7B")]
[assembly: ComVisible(false)]
[assembly: AssemblyCopyright("Copyright © 2026 Radamanto")]
[assembly: AssemblyProduct("Hunter's Instinct")]
[assembly: AssemblyCompany("Radamanto")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDescription("Animal footprints and skill-based hunting instinct for Valheim.")]
[assembly: AssemblyTitle("Hunter's Instinct")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: <35c36a8e-2072-4cbd-b3ac-b2dac557cc6a>RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<37491297-bece-4aaf-8d9a-3a68c4b98492>Embedded]
	internal sealed class <37491297-bece-4aaf-8d9a-3a68c4b98492>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	[<37491297-bece-4aaf-8d9a-3a68c4b98492>Embedded]
	internal sealed class <520c740c-0a0b-4506-a2a4-96b0bb152a58>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <520c740c-0a0b-4506-a2a4-96b0bb152a58>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <520c740c-0a0b-4506-a2a4-96b0bb152a58>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[<37491297-bece-4aaf-8d9a-3a68c4b98492>Embedded]
	internal sealed class <10b1878f-e44c-4d09-839e-a1dff4722204>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <10b1878f-e44c-4d09-839e-a1dff4722204>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[<37491297-bece-4aaf-8d9a-3a68c4b98492>Embedded]
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class <35c36a8e-2072-4cbd-b3ac-b2dac557cc6a>RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public <35c36a8e-2072-4cbd-b3ac-b2dac557cc6a>RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HuntersInstinct
{
	[BepInPlugin("radamanto.HuntersInstinct", "Hunter's Instinct", "1.0.0")]
	public sealed class HuntersInstinctPlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(Skills), "CheatRaiseSkill")]
		private static class RaiseHuntingCommand
		{
			private static bool Prefix(Skills __instance, string name, float value, bool showMessage)
			{
				if (!IsHuntingName(name))
				{
					return true;
				}
				RegisterSkill(__instance);
				Skill val = SkillByType(__instance, (SkillType)1978436211);
				val.m_level = Mathf.Clamp(val.m_level + value, 0f, 100f);
				if (__instance.m_useSkillCap)
				{
					Rebalance(__instance, (SkillType)1978436211);
				}
				if (showMessage && Object.op_Implicit((Object)(object)Console.instance))
				{
					Console.instance.Print("Hunting = " + val.m_level);
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Skills), "CheatResetSkill")]
		private static class ResetHuntingCommand
		{
			private static bool Prefix(Skills __instance, string name)
			{
				if (!IsHuntingName(name))
				{
					return true;
				}
				__instance.ResetSkill((SkillType)1978436211);
				if (Object.op_Implicit((Object)(object)Console.instance))
				{
					Console.instance.Print("Hunting = 0");
				}
				return false;
			}
		}

		private sealed class Trail
		{
			public readonly HuntersInstinctTracking Tracking = new HuntersInstinctTracking();

			public Vector3 Previous;

			public float Seen;

			public float Distance;

			public bool Active;

			public bool Left;

			public HuntersInstinctRules.FootprintStyle Style;
		}

		private sealed class Mark
		{
			public GameObject Object;

			public MeshRenderer Renderer;

			public MeshFilter Filter;

			public float Born;

			public float Lifetime;

			public bool WasTamed;

			public bool Studied;

			public Character Source;

			public string Prefab;
		}

		private class ConfigurationManagerAttributes
		{
			public bool? Browsable = false;
		}

		[HarmonyPatch(typeof(Skills), "Awake")]
		private static class RegisterHuntingSkill
		{
			private static void Postfix(Skills __instance)
			{
				RegisterSkill(__instance);
			}
		}

		[HarmonyPatch(typeof(Skills), "Load")]
		private static class BeforeLoadHuntingSkill
		{
			private static void Prefix(Skills __instance)
			{
				RegisterSkill(__instance);
			}
		}

		[HarmonyPatch(typeof(Skills), "IsSkillValid")]
		private static class ValidateHuntingSkill
		{
			private static void Postfix(SkillType type, ref bool __result)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Invalid comparison between Unknown and I4
				if ((int)type == 1978436211)
				{
					__result = true;
				}
			}
		}

		internal const string ModName = "Hunter's Instinct";

		internal const string ModId = "HuntersInstinct";

		internal const string ModVersion = "1.0.0";

		internal const string Author = "radamanto";

		internal const string ModGUID = "radamanto.HuntersInstinct";

		private Harmony harmony;

		private Player activePlayer;

		private float nextSample;

		private float trackReach;

		private float instinctReach;

		private float trailLifetime;

		private float trackingDuration;

		private float staminaPerSecond;

		private int groundMask;

		private bool huntingActive;

		private bool visualFailure;

		private float focusDuration;

		private float auraLifetime;

		private float focusBarAlpha;

		private float focusBarProgress;

		private readonly HuntersInstinctFocus focus = new HuntersInstinctFocus();

		private readonly HuntersInstinctActivation activation = new HuntersInstinctActivation();

		private static readonly Func<Player, bool> CanTakeInput = AccessTools.MethodDelegate<Func<Player, bool>>(AccessTools.Method(typeof(Player), "TakeInput", (Type[])null, (Type[])null), (object)null, true);

		private readonly HuntersInstinctExclusions exclusions = new HuntersInstinctExclusions();

		private static readonly Func<Skills, SkillType, Skill> SkillByType = AccessTools.MethodDelegate<Func<Skills, SkillType, Skill>>(AccessTools.Method(typeof(Skills), "GetSkill", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<Skills, SkillType> Rebalance = AccessTools.MethodDelegate<Action<Skills, SkillType>>(AccessTools.Method(typeof(Skills), "RebalanceSkills", (Type[])null, (Type[])null), (object)null, true);

		private TMP_FontAsset titleFont;

		private Material titleMaterial;

		private TextMeshProUGUI focusLabel;

		private float nextFontSearch;

		private bool verifiedTitleFont;

		private GameObject focusCanvas;

		private ConfigEntry<bool> modEnabled;

		private ConfigEntry<bool> trackTamed;

		private ConfigEntry<bool> tamedExperience;

		private ConfigEntry<bool> trailsEnabled;

		private ConfigEntry<bool> instinctEnabled;

		private const float TargetScanInterval = 0.2f;

		private const int MaximumGroundMarks = 1200;

		private const float FootprintOpacity = 0.7f;

		private const float FootprintScale = 1f;

		private const float FootprintSpacing = 0.75f;

		private const float AuraOpacity = 0.85f;

		private const float AuraScale = 1.8f;

		private const float FadeInSeconds = 0.25f;

		private const float FadeOutSeconds = 0.35f;

		private ConfigEntry<KeyCode> activationKey;

		private ConfigEntry<string> excludedPrefabs;

		private ConfigEntry<float> crouchingMultiplier;

		private ConfigEntry<float> walkingMultiplier;

		private ConfigEntry<float> runningMultiplier;

		private ConfigEntry<float> featherFallMultiplier;

		private ConfigEntry<float> focusStart;

		private ConfigEntry<float> focusEnd;

		private ConfigEntry<float> auraLifeStart;

		private ConfigEntry<float> auraLifeEnd;

		private ConfigEntry<float> trailLifeStart;

		private ConfigEntry<float> trailLifeEnd;

		private ConfigEntry<float> trackingStart;

		private ConfigEntry<float> trackingEnd;

		private ConfigEntry<float> trackRangeStart;

		private ConfigEntry<float> trackRangeEnd;

		private ConfigEntry<float> instinctRangeStart;

		private ConfigEntry<float> instinctRangeEnd;

		private ConfigEntry<float> experience;

		private ConfigEntry<float> staminaStart;

		private ConfigEntry<float> staminaEnd;

		private ConfigEntry<int> maxGlows;

		private ConfigEntry<string> markColor;

		private ConfigEntry<string> instinctColor;

		private readonly Dictionary<Character, Trail> trails = new Dictionary<Character, Trail>();

		private readonly List<Character> staleTrails = new List<Character>();

		private readonly List<Mark> marks = new List<Mark>();

		private readonly Stack<Mark> markPool = new Stack<Mark>();

		private readonly Mesh[] footprintMeshes = (Mesh[])(object)new Mesh[4];

		private Material trailMaterial;

		private MaterialPropertyBlock trailProperties;

		private static readonly int ColorId = Shader.PropertyToID("_Color");

		[<520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(2)]
		internal static ConfigSync ConfigSync;

		[<520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(2)]
		private static ConfigEntry<bool> _serverConfigLocked;

		[<520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(2)]
		private FileSystemWatcher _configWatcher;

		private long _lastCfgWrite;

		private bool _reloadScheduled;

		private bool _watcherReady;

		private readonly List<Character> instinctTargets = new List<Character>();

		private readonly Dictionary<Character, float> lastDetection = new Dictionary<Character, float>();

		private readonly List<Character> oldDetections = new List<Character>();

		private readonly Dictionary<Character, HuntersInstinctMark> instinctMarks = new Dictionary<Character, HuntersInstinctMark>();

		private Texture2D auraTexture;

		private Texture2D pulseTexture;

		private float nextExperience;

		private Vector3 trainingOrigin;

		internal const int HuntingSkillId = 1978436211;

		internal const SkillType HuntingSkill = (SkillType)1978436211;

		private bool InstinctActive => huntingActive && instinctEnabled.Value && Object.op_Implicit((Object)(object)activePlayer) && !((Character)activePlayer).IsDead();

		private void Awake()
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			Localizer.Load();
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			try
			{
				SetupServerSyncAndWatcher();
				Configure();
			}
			finally
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
			}
			((BaseUnityPlugin)this).Config.Save();
			SetupConfigWatcher();
			groundMask = LayerMask.GetMask(new string[4] { "terrain", "Default", "static_solid", "piece" });
			harmony = new Harmony("radamanto.HuntersInstinct");
			harmony.CreateClassProcessor(typeof(RegisterHuntingSkill)).Patch();
			harmony.CreateClassProcessor(typeof(BeforeLoadHuntingSkill)).Patch();
			harmony.CreateClassProcessor(typeof(ValidateHuntingSkill)).Patch();
			harmony.CreateClassProcessor(typeof(RaiseHuntingCommand)).Patch();
			harmony.CreateClassProcessor(typeof(ResetHuntingCommand)).Patch();
		}

		private void Update()
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Character)localPlayer).IsDead() || !modEnabled.Value)
			{
				ClearSession();
			}
			else
			{
				if (visualFailure)
				{
					return;
				}
				if (!Object.op_Implicit((Object)(object)trailMaterial) && !CreateTrailResources())
				{
					visualFailure = true;
					return;
				}
				if ((Object)(object)activePlayer != (Object)(object)localPlayer)
				{
					ClearSession();
					activePlayer = localPlayer;
					trainingOrigin = ((Component)localPlayer).transform.position;
					nextExperience = Time.time + 5f;
					nextSample = 0f;
				}
				float time = Time.time;
				bool flag = time >= nextSample;
				if (flag)
				{
					nextSample = time + 0.2f;
					Skills skills = ((Character)localPlayer).GetSkills();
					if (!Object.op_Implicit((Object)(object)skills))
					{
						return;
					}
					RegisterSkill(skills);
					float skillLevel = skills.GetSkillLevel((SkillType)1978436211);
					trackReach = HuntersInstinctRules.Reach(skillLevel, trackRangeStart.Value, trackRangeEnd.Value);
					instinctReach = HuntersInstinctRules.Reach(skillLevel, instinctRangeStart.Value, instinctRangeEnd.Value);
					focusDuration = HuntersInstinctRules.StaminaRate(skillLevel, focusStart.Value, focusEnd.Value);
					auraLifetime = HuntersInstinctRules.Reach(skillLevel, auraLifeStart.Value, auraLifeEnd.Value);
					trackingDuration = HuntersInstinctRules.Reach(skillLevel, trackingStart.Value, trackingEnd.Value);
					trailLifetime = HuntersInstinctRules.Reach(skillLevel, trailLifeStart.Value, trailLifeEnd.Value);
					staminaPerSecond = HuntersInstinctRules.StaminaRate(skillLevel, staminaStart.Value, staminaEnd.Value);
				}
				bool held = (int)activationKey.Value != 0 && Input.GetKey(activationKey.Value);
				bool allowed = Application.isFocused && Time.timeScale > 0f && Object.op_Implicit((Object)(object)Hud.instance) && CanTakeInput(localPlayer);
				HuntersInstinctActivation.Result result = activation.Tick(held, allowed, localPlayer.GetStamina(), staminaPerSecond, Time.deltaTime, Game.m_staminaRate);
				bool flag2 = huntingActive;
				float num = HuntersInstinctRules.PostureMultiplier(((Character)localPlayer).IsCrouching(), ((Character)localPlayer).IsRunning(), crouchingMultiplier.Value, walkingMultiplier.Value, runningMultiplier.Value, IsFeatherFalling(localPlayer), featherFallMultiplier.Value);
				huntingActive = focus.Advance(result.Active, Time.deltaTime, focusDuration * num);
				bool flag3 = huntingActive && !flag2;
				if (result.Active)
				{
					focusBarProgress = focus.Progress;
				}
				focusBarAlpha = HuntersInstinctRules.StepFade(focusBarAlpha, result.Active && !huntingActive, Time.unscaledDeltaTime, 0.25f, 0.35f);
				UpdateFocusLabel();
				if (result.StaminaCost > 0f)
				{
					((Character)localPlayer).UseStamina(result.StaminaCost);
				}
				UpdateInstinctMarks(time);
				if (flag || flag3)
				{
					SampleTrails(time);
					if (huntingActive)
					{
						SampleInstinctTargets();
						TrainHunting(time);
					}
				}
				FadeTrails(time);
			}
		}

		private static bool IsFeatherFalling(Player player)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (((Character)player).IsOnGround() || ((Character)player).IsSwimming() || ((Character)player).IsAttached() || ((Character)player).GetVelocity().y >= 0f)
			{
				return false;
			}
			foreach (StatusEffect statusEffect in ((Character)player).GetSEMan().GetStatusEffects())
			{
				SE_Stats val = (SE_Stats)(object)((statusEffect is SE_Stats) ? statusEffect : null);
				if (val != null && val.m_maxMaxFallSpeed > 0f)
				{
					return true;
				}
			}
			return false;
		}

		private HuntersInstinctRules.Kind Classify(Character c)
		{
			if (!Object.op_Implicit((Object)(object)c) || c.IsDead() || c.IsPlayer() || !Object.op_Implicit((Object)(object)activePlayer) || !HuntersInstinctRules.CanTrackCreature(IsExcluded(((Object)((Component)c).gameObject).name), c.IsTamed(), trackTamed.Value))
			{
				return HuntersInstinctRules.Kind.Ignore;
			}
			BaseAI baseAI = c.GetBaseAI();
			return HuntersInstinctRules.Classify(Object.op_Implicit((Object)(object)baseAI), baseAI is AnimalAI, BaseAI.IsEnemy(c, (Character)(object)activePlayer));
		}

		private void ClearSession()
		{
			ClearTrails();
			huntingActive = false;
			focus.Reset();
			focusBarAlpha = (focusBarProgress = 0f);
			if (Object.op_Implicit((Object)(object)focusCanvas))
			{
				focusCanvas.SetActive(false);
			}
			instinctMarks.Clear();
			activation.Reset();
			instinctTargets.Clear();
			lastDetection.Clear();
			oldDetections.Clear();
			activePlayer = null;
		}

		private void OnDestroy()
		{
			_watcherReady = false;
			_configWatcher?.Dispose();
			_configWatcher = null;
			((MonoBehaviour)this).StopAllCoroutines();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			ClearSession();
			DisposeTrailResources();
			if (Object.op_Implicit((Object)(object)auraTexture))
			{
				Object.Destroy((Object)(object)auraTexture);
			}
			if (Object.op_Implicit((Object)(object)pulseTexture))
			{
				Object.Destroy((Object)(object)pulseTexture);
			}
			if (Object.op_Implicit((Object)(object)focusCanvas))
			{
				Object.Destroy((Object)(object)focusCanvas);
			}
		}

		private bool IsExcluded(string prefab)
		{
			return exclusions.Contains(excludedPrefabs.Value, prefab);
		}

		private bool CanTrackMark(Mark mark)
		{
			bool tamed = (Object.op_Implicit((Object)(object)mark.Source) ? mark.Source.IsTamed() : mark.WasTamed);
			return HuntersInstinctRules.CanTrackCreature(IsExcluded(mark.Prefab), tamed, trackTamed.Value);
		}

		private bool CanRewardMark(Mark mark)
		{
			bool tamed = (Object.op_Implicit((Object)(object)mark.Source) ? mark.Source.IsTamed() : mark.WasTamed);
			return HuntersInstinctRules.CanRewardCreature(IsExcluded(mark.Prefab), tamed, trackTamed.Value, tamedExperience.Value);
		}

		private static bool IsHuntingName(string name)
		{
			return string.Equals(name, "Hunting", StringComparison.OrdinalIgnoreCase) || string.Equals(name, "Caça", StringComparison.OrdinalIgnoreCase) || string.Equals(name, "Caca", StringComparison.OrdinalIgnoreCase) || name == 1978436211.ToString();
		}

		private void FindTitleFont()
		{
			if ((verifiedTitleFont && Object.op_Implicit((Object)(object)titleFont) && Object.op_Implicit((Object)(object)titleMaterial)) || Time.unscaledTime < nextFontSearch)
			{
				return;
			}
			nextFontSearch = Time.unscaledTime + 1f;
			Transform val = (Object.op_Implicit((Object)(object)InventoryGui.instance) ? ((Component)InventoryGui.instance).transform.Find("root/Texts/Texts_frame/topic") : null);
			TextMeshProUGUI val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<TextMeshProUGUI>() : null);
			if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)((TMP_Text)val2).font) && ((Object)((TMP_Text)val2).font).name == "Valheim-Norsebold")
			{
				titleFont = ((TMP_Text)val2).font;
				titleMaterial = ((TMP_Text)val2).fontSharedMaterial;
			}
			else
			{
				TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
				foreach (TMP_FontAsset val3 in array)
				{
					if (((Object)val3).name == "Valheim-Norsebold")
					{
						titleFont = val3;
						break;
					}
				}
				Material[] array2 = Resources.FindObjectsOfTypeAll<Material>();
				foreach (Material val4 in array2)
				{
					if (((Object)val4).name == "Valheim-Norsebold - Outline")
					{
						titleMaterial = val4;
						break;
					}
				}
			}
			if (Object.op_Implicit((Object)(object)titleFont) && Object.op_Implicit((Object)(object)titleMaterial))
			{
				verifiedTitleFont = true;
			}
		}

		private void UpdateFocusLabel()
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			if (!(focusBarAlpha > 0f) || !Object.op_Implicit((Object)(object)activePlayer) || ((Character)activePlayer).IsDead() || !modEnabled.Value || !Object.op_Implicit((Object)(object)Hud.instance) || UiBlocking())
			{
				if (Object.op_Implicit((Object)(object)focusCanvas))
				{
					focusCanvas.SetActive(false);
				}
				return;
			}
			FindTitleFont();
			TextMeshProUGUI hoverName = Hud.instance.m_hoverName;
			if (Object.op_Implicit((Object)(object)hoverName) && Object.op_Implicit((Object)(object)((TMP_Text)hoverName).font))
			{
				if (!Object.op_Implicit((Object)(object)focusCanvas))
				{
					focusCanvas = new GameObject("HuntersInstinct.FocusLabel", new Type[2]
					{
						typeof(RectTransform),
						typeof(Canvas)
					});
					focusCanvas.transform.SetParent(((Component)this).transform, false);
					Canvas component = focusCanvas.GetComponent<Canvas>();
					component.renderMode = (RenderMode)0;
					component.sortingOrder = 100;
					GameObject val = new GameObject("Label", new Type[3]
					{
						typeof(RectTransform),
						typeof(CanvasRenderer),
						typeof(TextMeshProUGUI)
					});
					val.transform.SetParent(focusCanvas.transform, false);
					focusLabel = val.GetComponent<TextMeshProUGUI>();
					((Graphic)focusLabel).raycastTarget = false;
					((TMP_Text)focusLabel).alignment = (TextAlignmentOptions)514;
					((TMP_Text)focusLabel).enableAutoSizing = false;
				}
				focusCanvas.SetActive(true);
				((TMP_Text)focusLabel).font = (Object.op_Implicit((Object)(object)titleFont) ? titleFont : ((TMP_Text)hoverName).font);
				((TMP_Text)focusLabel).fontSharedMaterial = ((!Object.op_Implicit((Object)(object)titleFont)) ? ((TMP_Text)hoverName).fontSharedMaterial : (Object.op_Implicit((Object)(object)titleMaterial) ? titleMaterial : ((TMP_Asset)titleFont).material));
				float num = (float)Screen.height / 1080f;
				((TMP_Text)focusLabel).fontSize = 20f * num;
				((TMP_Text)focusLabel).fontStyle = (FontStyles)0;
				((Graphic)focusLabel).color = new Color(1f, 0.72f, 0.35f, focusBarAlpha);
				((TMP_Text)focusLabel).text = Localization.instance.Localize("$huntersinstinct_locating");
				RectTransform rectTransform = ((TMP_Text)focusLabel).rectTransform;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(0.5f, 0.5f);
				rectTransform.pivot = val2;
				Vector2 anchorMin = (rectTransform.anchorMax = val2);
				rectTransform.anchorMin = anchorMin;
				rectTransform.anchoredPosition = new Vector2(0f, -69f * num);
				rectTransform.sizeDelta = new Vector2(280f * num, 26f * num);
			}
		}

		private void DrawFocusBar()
		{
			//IL_01dd: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: 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_01c9: Unknown result type (might be due to invalid IL or missing references)
			if (focusBarAlpha <= 0f || UiBlocking())
			{
				return;
			}
			float num = (float)Screen.height / 1080f;
			float num2 = 180f * num;
			float num3 = 6f * num;
			float num4 = ((float)Screen.width - num2) / 2f;
			float num5 = (float)Screen.height / 2f + 42f * num;
			Color color = GUI.color;
			try
			{
				float num6 = Mathf.Max(1f, 2f * num);
				GUI.color = new Color(0.08f, 0.04f, 0.015f, focusBarAlpha);
				GUI.DrawTexture(new Rect(num4 - num6 * 2f, num5 - num6 * 2f, num2 + num6 * 4f, num3 + num6 * 4f), (Texture)(object)Texture2D.whiteTexture);
				GUI.color = new Color(0.72f, 0.47f, 0.19f, focusBarAlpha);
				GUI.DrawTexture(new Rect(num4 - num6, num5 - num6, num2 + num6 * 2f, num3 + num6 * 2f), (Texture)(object)Texture2D.whiteTexture);
				GUI.color = new Color(0.14f, 0.08f, 0.035f, focusBarAlpha);
				GUI.DrawTexture(new Rect(num4, num5, num2, num3), (Texture)(object)Texture2D.whiteTexture);
				float num7 = num2 * focusBarProgress;
				GUI.color = new Color(0.9f, 0.59f, 0.22f, focusBarAlpha);
				GUI.DrawTexture(new Rect(num4, num5, num7, num3), (Texture)(object)Texture2D.whiteTexture);
				GUI.color = new Color(1f, 0.79f, 0.41f, focusBarAlpha);
				GUI.DrawTexture(new Rect(num4, num5, num7, Mathf.Max(1f, num)), (Texture)(object)Texture2D.whiteTexture);
			}
			finally
			{
				GUI.color = color;
			}
		}

		private void Configure()
		{
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0475: Expected O, but got Unknown
			modEnabled = config("01 - General", "01 - Enabled", value: true, "Enable hunting trails and hunting instinct.");
			trackTamed = config("01 - General", "02 - Track Tamed Creatures", value: false, "Allow footprints and instinct marks for tamed creatures.");
			tamedExperience = config("01 - General", "04 - Gain Experience From Tamed Creatures", value: false, "Allow hunting experience from tamed creatures. Requires Track Tamed Creatures.");
			excludedPrefabs = config("01 - General", "05 - Excluded Prefabs", "", "Comma-separated exact prefab names excluded from footprints, instinct marks and hunting experience. Names are case-insensitive.");
			crouchingMultiplier = Range("06 - Localization Movement", "01 - Crouching Time Multiplier", 1f, "Multiply skill-based localization time while crouching. Posture changes preserve charge progress.", 0.1f, 10f);
			walkingMultiplier = Range("06 - Localization Movement", "02 - Walking Time Multiplier", 2f, "Multiply skill-based localization time while walking or standing.", 0.1f, 10f);
			featherFallMultiplier = Range("06 - Localization Movement", "04 - Feather Fall Time Multiplier", 4f, "Multiply localization time while airborne and descending with an active fall-speed-limiting effect. Overrides crouching, walking and running multipliers.", 0.1f, 10f);
			runningMultiplier = Range("06 - Localization Movement", "03 - Running Time Multiplier", 4f, "Multiply skill-based localization time while running.", 0.1f, 10f);
			activationKey = config<KeyCode>("01 - General", "03 - Activation Key", (KeyCode)308, "Hold this key to activate hunting mode. Release to stop. Release and press again after stamina exhaustion or an input-blocking screen.", synchronizedSetting: false);
			trailsEnabled = config("02 - Footprints", "01 - Enabled", value: true, "Detect creatures while hunting mode is active. Tracked creatures keep generating footprints until their tracking timer expires; existing marks retain their own lifetime.");
			markColor = config("02 - Footprints", "02 - Color", "#FF2020", "Footprint color in #RRGGBB format. Invalid values use red.", synchronizedSetting: false);
			focusStart = Range("03 - Hunting Skill", "12 - Localization Time At Level 0", 2f, "Seconds holding the activation key to complete localization at level zero. Releasing or exhaustion cancels progress.", 0.1f, 30f);
			focusEnd = Range("03 - Hunting Skill", "13 - Localization Time At Level 100", 0.5f, "Localization time at level 100. Cannot exceed the starting time.", 0.1f, 30f);
			auraLifeStart = Range("03 - Hunting Skill", "14 - Instinct Mark Duration At Level 0", 5f, "Seconds an instinct mark remains after its last completed localization detection, followed by fade-out.", 0.1f, 120f);
			auraLifeEnd = Range("03 - Hunting Skill", "15 - Instinct Mark Duration At Level 100", 15f, "Instinct mark duration at level 100. Cannot be lower than the starting duration.", 0.1f, 120f);
			trackingStart = Range("03 - Hunting Skill", "10 - Tracking Duration At Level 0", 15f, "Seconds a detected creature keeps generating footprints. ALT detection, remaining in detection range while tracked, or a new AnimalAI flee alert before expiry renews the timer. Expired tracking requires ALT again.", 1f, 120f);
			trackingEnd = Range("03 - Hunting Skill", "11 - Tracking Duration At Level 100", 30f, "Tracking duration at hunting level 100. Cannot be lower than the starting duration. Separate from each footprint lifetime.", 1f, 120f);
			trailLifeStart = Range("03 - Hunting Skill", "01 - Trail Duration At Level 0", 5f, "Ground mark lifetime in seconds at hunting level zero.", 0.1f, 60f);
			trailLifeEnd = Range("03 - Hunting Skill", "02 - Trail Duration At Level 100", 20f, "Lifetime at level 100. Cannot be lower than the starting duration.", 0.1f, 60f);
			trackRangeStart = Range("03 - Hunting Skill", "03 - Trail Range At Level 0", 20f, "Trail recording range in meters at hunting level zero.", 1f, 100f);
			trackRangeEnd = Range("03 - Hunting Skill", "04 - Trail Range At Level 100", 80f, "Trail recording range at level 100. Cannot be lower than the starting range.", 1f, 100f);
			instinctRangeStart = Range("03 - Hunting Skill", "05 - Instinct Range At Level 0", 50f, "Instinct detection distance in meters at hunting level zero.", 1f, 200f);
			instinctRangeEnd = Range("03 - Hunting Skill", "06 - Instinct Range At Level 100", 100f, "Instinct detection distance at level 100. Cannot be lower than the starting range.", 1f, 200f);
			experience = Range("03 - Hunting Skill", "07 - Experience Per Use", 1f, "Experience for following marks or detecting creatures. Requires 2 meters of movement and at least 5 seconds between rewards. Zero disables experience gain.", 0f, 10f);
			staminaStart = Range("03 - Hunting Skill", "08 - Stamina Per Second At Level 0", 5f, "Stamina consumed each second while the activation key is held, even without a target.", 0f, 30f);
			staminaEnd = Range("03 - Hunting Skill", "09 - Stamina Per Second At Level 100", 1f, "Stamina per second at level 100. Cannot exceed the starting cost. The game's world stamina multiplier still applies.", 0f, 30f);
			instinctEnabled = config("04 - Hunting Instinct", "01 - Enabled", value: true, "Show a spectral aura on hostile creatures and passive AnimalAI creatures while hunting mode is active.");
			instinctColor = config("04 - Hunting Instinct", "03 - Aura Color", "#FF4020", "Outer spectral aura color in #RRGGBB format.", synchronizedSetting: false);
			maxGlows = config("05 - Performance", "01 - Maximum Auras", 64, new ConfigDescription("Maximum simultaneous auras, prioritizing nearby eligible creatures.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 256), Array.Empty<object>()));
		}

		private ConfigEntry<float> Range(string section, string key, float value, string description, float min, float max, bool synced = true)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			return config(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()), synced);
		}

		private bool CreateTrailResources()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			Shader val = Shader.Find("Sprites/Default");
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			for (int i = 0; i < footprintMeshes.Length; i++)
			{
				footprintMeshes[i] = MakeFootprintMesh(i);
			}
			trailMaterial = new Material(val)
			{
				name = "HuntersInstinct.RedFootprints",
				renderQueue = 3000
			};
			trailProperties = new MaterialPropertyBlock();
			return true;
		}

		private void SampleTrails(float now)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: 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_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0318: Unknown result type (might be due to invalid IL or missing references)
			//IL_031d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0322: Unknown result type (might be due to invalid IL or missing references)
			if (!trailsEnabled.Value)
			{
				ClearTrails();
				return;
			}
			Vector3 val3 = default(Vector3);
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!Object.op_Implicit((Object)(object)allCharacter))
				{
					continue;
				}
				HuntersInstinctRules.Kind kind = Classify(allCharacter);
				if (kind == HuntersInstinctRules.Kind.Ignore)
				{
					trails.Remove(allCharacter);
					continue;
				}
				Vector3 position = ((Component)allCharacter).transform.position;
				BaseAI baseAI = allCharacter.GetBaseAI();
				if (!(baseAI is AnimalAI))
				{
					trails.Remove(allCharacter);
					continue;
				}
				Vector3 val = position - ((Component)activePlayer).transform.position;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				bool flag = kind == HuntersInstinctRules.Kind.Passive && sqrMagnitude <= trackReach * trackReach;
				bool flag2 = instinctEnabled.Value && HuntersInstinctRules.CanDetectWithInstinct(kind, baseAI is AnimalAI) && sqrMagnitude <= instinctReach * instinctReach;
				bool flag3 = flag || flag2;
				bool flag4 = huntingActive && flag3;
				if (!trails.TryGetValue(allCharacter, out var value))
				{
					if (!flag4)
					{
						continue;
					}
					value = new Trail
					{
						Previous = position,
						Seen = now,
						Style = HuntersInstinctRules.GetFootprintStyle(((Object)((Component)allCharacter).gameObject).name.Replace("(Clone)", "").Trim())
					};
					trails.Add(allCharacter, value);
				}
				bool fleeing = baseAI is AnimalAI && baseAI.IsAlerted();
				if (!value.Tracking.Update(now, trackingDuration, flag4, fleeing, flag3))
				{
					trails.Remove(allCharacter);
					continue;
				}
				value.Seen = now;
				Vector3 val2 = position - value.Previous;
				((Vector3)(ref val3))..ctor(val2.x, 0f, val2.z);
				bool flag5 = !allCharacter.IsSwimming() && !allCharacter.IsFlying();
				if (flag5 && value.Active && ((Vector3)(ref val2)).sqrMagnitude < 36f && ((Vector3)(ref val3)).sqrMagnitude > 0.0001f)
				{
					float magnitude = ((Vector3)(ref val3)).magnitude;
					float num = Mathf.Clamp(0.75f, 0.25f, 3f);
					for (float num2 = num - Mathf.Min(value.Distance, num); num2 <= magnitude; num2 += num)
					{
						Vector3 val4 = val3 / magnitude;
						Vector3 val5 = Vector3.Lerp(value.Previous, position, num2 / magnitude);
						val5 += Vector3.Cross(Vector3.up, val4) * (value.Left ? (-0.1f) : 0.1f) * (value.Style.Size / 0.3f) * 1f;
						EmitMark(val5, val4, now, allCharacter, value.Style);
						value.Left = !value.Left;
					}
					value.Distance = (value.Distance + magnitude) % num;
				}
				else
				{
					value.Distance = 0f;
				}
				value.Previous = position;
				value.Active = flag5;
			}
			staleTrails.Clear();
			foreach (KeyValuePair<Character, Trail> trail in trails)
			{
				if (!Object.op_Implicit((Object)(object)trail.Key) || now - trail.Value.Seen > 0.5f)
				{
					staleTrails.Add(trail.Key);
				}
			}
			foreach (Character staleTrail in staleTrails)
			{
				trails.Remove(staleTrail);
			}
		}

		private void EmitMark(Vector3 position, Vector3 direction, float now, Character source, HuntersInstinctRules.FootprintStyle style)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: 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_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: 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)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(position + Vector3.up * 0.35f, Vector3.down, ref val, 0.85f, groundMask, (QueryTriggerInteraction)1) && !(((RaycastHit)(ref val)).normal.y < 0.4f) && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Character>()))
			{
				while (marks.Count >= 1200)
				{
					RecycleOldest();
				}
				Mark mark;
				if (markPool.Count > 0)
				{
					mark = markPool.Pop();
				}
				else
				{
					GameObject val2 = new GameObject("HuntersInstinct.GroundMark");
					val2.transform.SetParent(((Component)this).transform, false);
					MeshFilter filter = val2.AddComponent<MeshFilter>();
					MeshRenderer val3 = val2.AddComponent<MeshRenderer>();
					((Renderer)val3).sharedMaterial = trailMaterial;
					((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)val3).receiveShadows = false;
					mark = new Mark
					{
						Object = val2,
						Renderer = val3,
						Filter = filter
					};
				}
				mark.Born = now;
				mark.Lifetime = trailLifetime;
				mark.Source = source;
				mark.Prefab = HuntersInstinctExclusions.PrefabName(((Object)((Component)source).gameObject).name);
				mark.WasTamed = source.IsTamed();
				mark.Studied = false;
				mark.Filter.sharedMesh = footprintMeshes[style.Shape];
				mark.Object.transform.position = ((RaycastHit)(ref val)).point + ((RaycastHit)(ref val)).normal * 0.018f;
				mark.Object.transform.rotation = Quaternion.LookRotation(Vector3.ProjectOnPlane(direction, ((RaycastHit)(ref val)).normal), ((RaycastHit)(ref val)).normal);
				mark.Object.transform.localScale = Vector3.one * style.Size * 1f;
				mark.Object.SetActive(true);
				marks.Add(mark);
			}
		}

		private void FadeTrails(float now)
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			Color val = default(Color);
			if (!ColorUtility.TryParseHtmlString(markColor.Value, ref val))
			{
				((Color)(ref val))..ctor(1f, 0.125f, 0.125f);
			}
			for (int num = marks.Count - 1; num >= 0; num--)
			{
				Mark mark = marks[num];
				float num2 = HuntersInstinctRules.Opacity(now - mark.Born, mark.Lifetime, 0.7f);
				if (num2 <= 0f || !trailsEnabled.Value || !CanTrackMark(mark))
				{
					Recycle(mark);
					marks.RemoveAt(num);
				}
				else
				{
					val.a = HuntersInstinctRules.FootprintOpacity(now - mark.Born, mark.Lifetime, 0.7f, 0.25f);
					trailProperties.SetColor(ColorId, val);
					((Renderer)mark.Renderer).SetPropertyBlock(trailProperties);
				}
			}
			while (marks.Count > 1200)
			{
				RecycleOldest();
			}
		}

		private void Recycle(Mark mark)
		{
			mark.Object.SetActive(false);
			mark.Source = null;
			mark.Prefab = null;
			markPool.Push(mark);
		}

		private void RecycleOldest()
		{
			Recycle(marks[0]);
			marks.RemoveAt(0);
		}

		private void ClearTrails()
		{
			foreach (Mark mark in marks)
			{
				Recycle(mark);
			}
			marks.Clear();
			trails.Clear();
		}

		private void DisposeTrailResources()
		{
			foreach (Mark item in markPool)
			{
				if (Object.op_Implicit((Object)(object)item.Object))
				{
					Object.Destroy((Object)(object)item.Object);
				}
			}
			markPool.Clear();
			Mesh[] array = footprintMeshes;
			foreach (Mesh val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					Object.Destroy((Object)(object)val);
				}
			}
			if (Object.op_Implicit((Object)(object)trailMaterial))
			{
				Object.Destroy((Object)(object)trailMaterial);
			}
		}

		private static Mesh MakeFootprintMesh(int shape)
		{
			//IL_01f6: 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_0214: Expected O, but got Unknown
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> vertices = new List<Vector3>();
			List<int> triangles = new List<int>();
			Action<float, float, float, float, float> action = delegate(float x, float z, float rx, float rz, float angle)
			{
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				int count = vertices.Count;
				Quaternion val2 = Quaternion.Euler(0f, angle, 0f);
				vertices.Add(new Vector3(x, 0f, z));
				for (int i = 0; i < 12; i++)
				{
					float num3 = (float)i * (float)Math.PI * 2f / 12f;
					vertices.Add(new Vector3(x, 0f, z) + val2 * new Vector3(Mathf.Cos(num3) * rx, 0f, Mathf.Sin(num3) * rz));
				}
				for (int j = 0; j < 12; j++)
				{
					triangles.Add(count);
					triangles.Add(count + 1 + (j + 1) % 12);
					triangles.Add(count + 1 + j);
				}
			};
			switch (shape)
			{
			case 0:
				action(-0.15f, 0f, 0.12f, 0.36f, -8f);
				action(0.15f, 0f, 0.12f, 0.36f, 8f);
				break;
			case 1:
			{
				action(0f, -0.12f, 0.26f, 0.23f, 0f);
				for (int num = 0; num < 4; num++)
				{
					action(((float)num - 1.5f) * 0.17f, 0.22f + ((num == 1 || num == 2) ? 0.08f : 0f), 0.085f, 0.12f, 0f);
				}
				break;
			}
			case 2:
				action(0f, -0.08f, 0.16f, 0.38f, 0f);
				action(-0.09f, 0.3f, 0.065f, 0.11f, 0f);
				action(0.09f, 0.3f, 0.065f, 0.11f, 0f);
				break;
			default:
				action(0f, -0.12f, 0.07f, 0.25f, 0f);
				action(-0.14f, 0.1f, 0.055f, 0.28f, -35f);
				action(0f, 0.17f, 0.055f, 0.3f, 0f);
				action(0.14f, 0.1f, 0.055f, 0.28f, 35f);
				break;
			}
			Mesh val = new Mesh
			{
				name = "HuntersInstinct.Shape" + shape
			};
			val.SetVertices(vertices);
			val.SetTriangles(triangles, 0);
			Color[] array = (Color[])(object)new Color[vertices.Count];
			for (int num2 = 0; num2 < array.Length; num2++)
			{
				array[num2] = Color.white;
			}
			val.colors = array;
			val.RecalculateNormals();
			val.RecalculateBounds();
			return val;
		}

		public static bool IsLocalPlayerAdmin()
		{
			return ConfigSync != null && ConfigSync.IsAdmin;
		}

		public void SetupServerSyncAndWatcher()
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			ConfigSync = new ConfigSync(((BaseUnityPlugin)this).Info.Metadata.GUID)
			{
				DisplayName = ((BaseUnityPlugin)this).Info.Metadata.Name,
				CurrentVersion = ((BaseUnityPlugin)this).Info.Metadata.Version.ToString(),
				MinimumRequiredVersion = ((BaseUnityPlugin)this).Info.Metadata.Version.ToString()
			};
			_serverConfigLocked = ((BaseUnityPlugin)this).Config.Bind<bool>("01 - General", "LockConfiguration", true, new ConfigDescription("If true, the server locks synchronized configs.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
			ConfigSync.AddLockingConfigEntry<bool>(_serverConfigLocked);
		}

		[<10b1878f-e44c-4d09-839e-a1dff4722204>NullableContext(1)]
		private ConfigEntry<T> config<[<520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(2)] T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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)this).Config.Bind<T>(group, name, value, val);
			if (ConfigSync == null)
			{
				throw new InvalidOperationException("ServerSync has not been initialized.");
			}
			ConfigSync.AddConfigEntry<T>(val2).SynchronizedConfig = synchronizedSetting;
			return val2;
		}

		[<10b1878f-e44c-4d09-839e-a1dff4722204>NullableContext(1)]
		private ConfigEntry<T> config<[<520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(2)] T>(string group, string name, T value, string description, bool synchronizedSetting = true)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			return config(group, name, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting);
		}

		private void SetupConfigWatcher()
		{
			try
			{
				_watcherReady = false;
				_configWatcher?.Dispose();
				_configWatcher = new FileSystemWatcher(Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath), Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath))
				{
					IncludeSubdirectories = false,
					NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite),
					SynchronizingObject = ThreadingHelper.SynchronizingObject
				};
				_configWatcher.Changed += OnConfigFileChanged;
				_configWatcher.Created += OnConfigFileChanged;
				_configWatcher.Renamed += delegate(object _, RenamedEventArgs args)
				{
					OnConfigFileChanged(_, args);
				};
				_watcherReady = true;
				_configWatcher.EnableRaisingEvents = true;
			}
			catch (Exception)
			{
				_watcherReady = false;
				_configWatcher?.Dispose();
				_configWatcher = null;
			}
		}

		[<10b1878f-e44c-4d09-839e-a1dff4722204>NullableContext(1)]
		private void OnConfigFileChanged(object sender, FileSystemEventArgs args)
		{
			if (_watcherReady)
			{
				_lastCfgWrite = Stopwatch.GetTimestamp();
				if (!_reloadScheduled)
				{
					_reloadScheduled = true;
					((MonoBehaviour)this).StartCoroutine(ReloadConfigAfterQuietPeriod());
				}
			}
		}

		[<10b1878f-e44c-4d09-839e-a1dff4722204>NullableContext(1)]
		private IEnumerator ReloadConfigAfterQuietPeriod()
		{
			try
			{
				for (int attempt = 0; attempt < 3; attempt++)
				{
					if (!_watcherReady)
					{
						break;
					}
					while (_watcherReady && (double)(Stopwatch.GetTimestamp() - _lastCfgWrite) / (double)Stopwatch.Frequency < 0.75)
					{
						yield return null;
					}
					if (!_watcherReady || ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()))
					{
						break;
					}
					bool saveOnSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
					bool retry = false;
					try
					{
						((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
						((BaseUnityPlugin)this).Config.Reload();
					}
					catch (IOException)
					{
						retry = true;
					}
					catch (Exception)
					{
					}
					finally
					{
						((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnSet;
					}
					if (!retry)
					{
						break;
					}
					_lastCfgWrite = Stopwatch.GetTimestamp();
				}
			}
			finally
			{
				_reloadScheduled = false;
			}
		}

		private void SampleInstinctTargets()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			if (!InstinctActive)
			{
				return;
			}
			Vector3 origin = ((Component)activePlayer).transform.position;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!Object.op_Implicit((Object)(object)allCharacter))
				{
					continue;
				}
				Vector3 val = ((Component)allCharacter).transform.position - origin;
				if (!(((Vector3)(ref val)).sqrMagnitude > instinctReach * instinctReach) && HuntersInstinctRules.CanDetectWithInstinct(Classify(allCharacter), allCharacter.GetBaseAI() is AnimalAI))
				{
					if (!instinctMarks.TryGetValue(allCharacter, out var value))
					{
						value = new HuntersInstinctMark();
						instinctMarks.Add(allCharacter, value);
						instinctTargets.Add(allCharacter);
					}
					value.Refresh(Time.time, auraLifetime);
				}
			}
			instinctTargets.Sort(delegate(Character a, Character b)
			{
				//IL_0006: 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_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val2 = ((Component)a).transform.position - origin;
				float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
				val2 = ((Component)b).transform.position - origin;
				return sqrMagnitude.CompareTo(((Vector3)(ref val2)).sqrMagnitude);
			});
			while (instinctTargets.Count > maxGlows.Value)
			{
				Character key = instinctTargets[instinctTargets.Count - 1];
				instinctMarks.Remove(key);
				instinctTargets.RemoveAt(instinctTargets.Count - 1);
			}
		}

		private void UpdateInstinctMarks(float now)
		{
			for (int num = instinctTargets.Count - 1; num >= 0; num--)
			{
				Character val = instinctTargets[num];
				if (!Object.op_Implicit((Object)(object)val) || Classify(val) == HuntersInstinctRules.Kind.Ignore || !instinctEnabled.Value || !instinctMarks[val].Tick(now, Time.unscaledDeltaTime, 0.25f, 0.35f))
				{
					instinctMarks.Remove(val);
					instinctTargets.RemoveAt(num);
				}
			}
		}

		private void TrainHunting(float now)
		{
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: 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_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: 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_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			oldDetections.Clear();
			foreach (KeyValuePair<Character, float> item in lastDetection)
			{
				if (!Object.op_Implicit((Object)(object)item.Key) || now - item.Value > 120f)
				{
					oldDetections.Add(item.Key);
				}
			}
			foreach (Character oldDetection in oldDetections)
			{
				lastDetection.Remove(oldDetection);
			}
			if (now < nextExperience || experience.Value <= 0f)
			{
				return;
			}
			Vector3 val = ((Component)activePlayer).transform.position - trainingOrigin;
			if (((Vector3)(ref val)).sqrMagnitude < 4f || UiBlocking())
			{
				return;
			}
			Camera main = Camera.main;
			if (!Object.op_Implicit((Object)(object)main))
			{
				return;
			}
			bool flag = false;
			if (trailsEnabled.Value)
			{
				foreach (Mark mark in marks)
				{
					if (CanRewardMark(mark) && !mark.Studied && !(now - mark.Born >= mark.Lifetime))
					{
						Vector3 position = mark.Object.transform.position;
						val = position - ((Character)activePlayer).GetCenterPoint();
						if (!(((Vector3)(ref val)).sqrMagnitude > 9f) && OnScreen(main, position) && !Physics.Linecast(((Component)main).transform.position, position + Vector3.up * 0.08f, groundMask, (QueryTriggerInteraction)1))
						{
							mark.Studied = true;
							flag = true;
							break;
						}
					}
				}
			}
			if (!flag)
			{
				foreach (Character instinctTarget in instinctTargets)
				{
					if (Object.op_Implicit((Object)(object)instinctTarget) && !instinctTarget.IsDead() && HuntersInstinctRules.CanRewardCreature(IsExcluded(((Object)((Component)instinctTarget).gameObject).name), instinctTarget.IsTamed(), trackTamed.Value, tamedExperience.Value))
					{
						val = ((Component)instinctTarget).transform.position - ((Component)activePlayer).transform.position;
						if (!(((Vector3)(ref val)).sqrMagnitude > instinctReach * instinctReach) && OnScreen(main, instinctTarget.GetCenterPoint()) && (!lastDetection.TryGetValue(instinctTarget, out var value) || !(now - value < 60f)))
						{
							lastDetection[instinctTarget] = now;
							flag = true;
							break;
						}
					}
				}
			}
			if (flag)
			{
				((Character)activePlayer).GetSkills().RaiseSkill((SkillType)1978436211, experience.Value);
				nextExperience = now + 5f;
				trainingOrigin = ((Component)activePlayer).transform.position;
			}
		}

		private static bool OnScreen(Camera camera, Vector3 position)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = camera.WorldToViewportPoint(position);
			return val.z > 0f && val.x >= 0f && val.x <= 1f && val.y >= 0f && val.y <= 1f;
		}

		private static bool UiBlocking()
		{
			return InventoryGui.IsVisible() || Menu.IsVisible() || Console.IsVisible();
		}

		private void OnGUI()
		{
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			if (!modEnabled.Value || !Object.op_Implicit((Object)(object)activePlayer) || ((Character)activePlayer).IsDead() || (int)Event.current.type != 7 || UiBlocking())
			{
				return;
			}
			DrawFocusBar();
			if (!instinctEnabled.Value || instinctTargets.Count == 0)
			{
				return;
			}
			Camera main = Camera.main;
			if (!Object.op_Implicit((Object)(object)main))
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)auraTexture))
			{
				auraTexture = MakeAuraTexture();
			}
			if (!Object.op_Implicit((Object)(object)pulseTexture))
			{
				pulseTexture = MakeAuraTexture(pulse: true);
			}
			Color color = default(Color);
			if (!ColorUtility.TryParseHtmlString(instinctColor.Value, ref color))
			{
				((Color)(ref color))..ctor(1f, 0.25f, 0.125f);
			}
			Color color2 = GUI.color;
			Matrix4x4 matrix = GUI.matrix;
			try
			{
				Vector2 center = default(Vector2);
				foreach (Character instinctTarget in instinctTargets)
				{
					if (Object.op_Implicit((Object)(object)instinctTarget) && !instinctTarget.IsDead())
					{
						float distance = Vector3.Distance(((Component)instinctTarget).transform.position, ((Component)activePlayer).transform.position);
						Vector3 val = main.WorldToScreenPoint(instinctTarget.GetCenterPoint());
						if (!(val.z <= 0f) && !(val.x < 0f) && !(val.x > (float)Screen.width) && !(val.y < 0f) && !(val.y > (float)Screen.height))
						{
							float num = 60f * HuntersInstinctRules.AuraDistanceScale(distance, instinctReach) * 1.8f * (float)Screen.height / 1080f;
							((Vector2)(ref center))..ctor(val.x, (float)Screen.height - val.y);
							float num2 = HuntersInstinctRules.SmoothFade(instinctMarks[instinctTarget].Phase);
							color.a = 0.7225f * num2;
							GUI.color = color;
							DrawCentered((Texture)(object)auraTexture, center, num, num);
							float progress = HuntersInstinctVisuals.PulseProgress(Time.time, ((Object)instinctTarget).GetInstanceID());
							float num3 = num * HuntersInstinctVisuals.PulseScale(progress);
							color.a = 0.85f * HuntersInstinctVisuals.PulseOpacity(progress) * num2;
							GUI.color = color;
							DrawCentered((Texture)(object)pulseTexture, center, num3, num3);
						}
					}
				}
			}
			finally
			{
				GUI.color = color2;
				GUI.matrix = matrix;
			}
		}

		private static void DrawCentered(Texture texture, Vector2 center, float width, float height)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			GUI.DrawTexture(new Rect(center.x - width / 2f, center.y - height / 2f, width, height), texture);
		}

		private static Texture2D MakeAuraTexture(bool pulse = false)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(192, 192, (TextureFormat)4, false)
			{
				name = (pulse ? "HuntersInstinct.InwardPulse" : "HuntersInstinct.SoftHalo"),
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			Color[] array = (Color[])(object)new Color[36864];
			for (int i = 0; i < 192; i++)
			{
				for (int j = 0; j < 192; j++)
				{
					float x = ((float)j + 0.5f - 96f) / 96f;
					float y = ((float)i + 0.5f - 96f) / 96f;
					array[i * 192 + j] = new Color(1f, 1f, 1f, pulse ? HuntersInstinctVisuals.PulseRingAlpha(x, y) : HuntersInstinctVisuals.AuraAlpha(x, y));
				}
			}
			val.SetPixels(array);
			val.Apply(false, true);
			return val;
		}

		private static void RegisterSkill(Skills skills)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)skills) && !skills.m_skills.Exists((SkillDef def) => (int)def.m_skill == 1978436211))
			{
				SkillDef val = skills.m_skills.Find((SkillDef def) => (int)def.m_skill == 101) ?? skills.m_skills.Find((SkillDef def) => (int)def.m_skill == 8);
				skills.m_skills.Add(new SkillDef
				{
					m_skill = (SkillType)1978436211,
					m_icon = val?.m_icon,
					m_description = "$skill_hunting_description",
					m_increseStep = 1f
				});
			}
		}
	}
	internal sealed class HuntersInstinctExclusions
	{
		private string cached;

		private readonly HashSet<string> prefabs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		internal static string PrefabName(string name)
		{
			string text = (name ?? "").Trim();
			return text.EndsWith("(Clone)", StringComparison.Ordinal) ? text.Substring(0, text.Length - "(Clone)".Length).TrimEnd(Array.Empty<char>()) : text;
		}

		internal bool Contains(string configuration, string name)
		{
			if (cached != configuration)
			{
				cached = configuration;
				prefabs.Clear();
				string[] array = (configuration ?? "").Split(new char[1] { ',' });
				foreach (string name2 in array)
				{
					string text = PrefabName(name2);
					if (text.Length > 0)
					{
						prefabs.Add(text);
					}
				}
			}
			return prefabs.Contains(PrefabName(name));
		}
	}
	internal sealed class HuntersInstinctFocus
	{
		internal float Progress { get; private set; }

		internal bool Advance(bool active, float dt, float duration)
		{
			if (!active)
			{
				Progress = 0f;
				return false;
			}
			Progress = Math.Min(1f, Progress + Math.Max(0f, dt) / Math.Max(0.1f, duration));
			return Progress >= 1f;
		}

		internal void Reset()
		{
			Progress = 0f;
		}
	}
	internal sealed class HuntersInstinctMark
	{
		private float expiresAt;

		internal float Phase { get; private set; }

		internal void Refresh(float now, float duration)
		{
			expiresAt = now + duration;
		}

		internal bool Tick(float now, float dt, float fadeIn, float fadeOut)
		{
			bool flag = now < expiresAt;
			Phase = HuntersInstinctRules.StepFade(Phase, flag, dt, fadeIn, fadeOut);
			return flag || Phase > 0f;
		}
	}
	internal sealed class HuntersInstinctTracking
	{
		private float expiresAt;

		private bool wasFleeing;

		internal bool Update(float now, float duration, bool detected, bool fleeing, bool withinRange = false)
		{
			bool flag = now < expiresAt;
			if (detected || (flag && (withinRange || (fleeing && !wasFleeing))))
			{
				expiresAt = now + duration;
				flag = true;
			}
			wasFleeing = fleeing;
			return flag;
		}
	}
	public sealed class HuntersInstinctActivation
	{
		public struct Result
		{
			public bool Active;

			public float StaminaCost;
		}

		private bool releaseRequired;

		public Result Tick(bool held, bool allowed, float available, float rate, float dt, float worldMultiplier)
		{
			if (!held)
			{
				releaseRequired = false;
				return default(Result);
			}
			if (!allowed)
			{
				releaseRequired = true;
				return default(Result);
			}
			if (releaseRequired || dt <= 0f)
			{
				return default(Result);
			}
			float num = Math.Max(0f, rate) * dt;
			float num2 = num * Math.Max(0f, worldMultiplier);
			if (num2 > 0f && available < num2)
			{
				releaseRequired = true;
				return default(Result);
			}
			return new Result
			{
				Active = true,
				StaminaCost = ((num2 > 0f) ? num : 0f)
			};
		}

		public void Reset()
		{
			releaseRequired = false;
		}
	}
	public static class HuntersInstinctRules
	{
		public readonly struct FootprintStyle
		{
			public readonly int Shape;

			public readonly float Size;

			public FootprintStyle(int shape, float size)
			{
				Shape = shape;
				Size = size;
			}
		}

		public enum Kind
		{
			Ignore,
			Passive,
			Hostile
		}

		public static FootprintStyle GetFootprintStyle(string prefab)
		{
			switch ((prefab ?? "").ToLowerInvariant())
			{
			case "boar":
				return new FootprintStyle(0, 0.3f);
			case "deer":
				return new FootprintStyle(0, 0.32f);
			case "wolf":
				return new FootprintStyle(1, 0.36f);
			case "hare":
				return new FootprintStyle(2, 0.24f);
			case "neck":
				return new FootprintStyle(3, 0.25f);
			case "hen":
			case "chicken":
				return new FootprintStyle(3, 0.22f);
			case "bear":
			case "bjorn":
				return new FootprintStyle(1, 0.6f);
			default:
				return new FootprintStyle(1, 0.32f);
			}
		}

		public static bool CanTrackCreature(bool excluded, bool tamed, bool trackTamed)
		{
			return !excluded && (!tamed || trackTamed);
		}

		public static bool CanRewardCreature(bool excluded, bool tamed, bool trackTamed, bool tamedExperience)
		{
			return CanTrackCreature(excluded, tamed, trackTamed) && (!tamed || tamedExperience);
		}

		public static float PostureMultiplier(bool crouching, bool running, float crouch, float walk, float run, bool featherFalling = false, float featherFall = 4f)
		{
			return Math.Max(0.1f, featherFalling ? featherFall : (crouching ? crouch : (running ? run : walk)));
		}

		public static float AuraDistanceScale(float distance, float range)
		{
			return 1f - 0.5f * Math.Max(0f, Math.Min(1f, distance / Math.Max(1f, range)));
		}

		public static Kind Classify(bool valid, bool animalAI, bool enemy)
		{
			if (!valid)
			{
				return Kind.Ignore;
			}
			return (animalAI || !enemy) ? Kind.Passive : Kind.Hostile;
		}

		public static bool CanDetectWithInstinct(Kind kind, bool animalAI)
		{
			return kind != Kind.Ignore && (kind == Kind.Hostile || animalAI);
		}

		public static float Reach(float level, float minimum, float maximum)
		{
			float num = Math.Max(0f, Math.Min(100f, level)) / 100f;
			return minimum + (Math.Max(minimum, maximum) - minimum) * num;
		}

		public static float Opacity(float age, float lifetime, float visibility)
		{
			float num = Math.Max(0f, Math.Min(1f, 1f - age / Math.Max(0.1f, lifetime)));
			return num * num * Math.Max(0f, Math.Min(1f, visibility));
		}

		public static float StaminaRate(float level, float initial, float final)
		{
			float num = Math.Max(0f, initial);
			float num2 = Math.Min(num, Math.Max(0f, final));
			float num3 = Math.Max(0f, Math.Min(100f, level)) / 100f;
			return num + (num2 - num) * num3;
		}

		public static float StepFade(float current, bool active, float dt, float fadeIn, float fadeOut)
		{
			current = Math.Max(0f, Math.Min(1f, current));
			float num = Math.Max(0f, dt) / Math.Max(0.05f, active ? fadeIn : fadeOut);
			return active ? Math.Min(1f, current + num) : Math.Max(0f, current - num);
		}

		public static float SmoothFade(float phase)
		{
			phase = Math.Max(0f, Math.Min(1f, phase));
			return phase * phase * (3f - 2f * phase);
		}

		public static float FootprintOpacity(float age, float lifetime, float visibility, float fadeIn)
		{
			return Opacity(age, lifetime, visibility) * SmoothFade(age / Math.Max(0.05f, fadeIn));
		}
	}
	public static class HuntersInstinctVisuals
	{
		public static float PulseProgress(float time, int targetId)
		{
			int num = (int)((uint)targetId % 997u);
			double num2 = (double)time / 1.0 + (double)num / 997.0;
			return (float)(num2 - Math.Floor(num2));
		}

		public static float PulseScale(float progress)
		{
			return 1f - 0.45f * progress;
		}

		public static float PulseOpacity(float progress)
		{
			if (progress <= 0f || progress >= 1f)
			{
				return 0f;
			}
			double num = Math.Sin(Math.PI * (double)progress);
			return (float)(0.42 * num * num);
		}

		public static float PulseRingAlpha(float x, float y)
		{
			double num = Math.Sqrt(x * x + y * y);
			if (num <= 0.55 || num >= 1.0)
			{
				return 0f;
			}
			double num2 = Math.Min(1.0, Math.Min((num - 0.55) / 0.08, (1.0 - num) / 0.08));
			return (float)(Math.Exp(0.0 - Math.Pow((num - 0.8) / 0.09, 2.0)) * num2);
		}

		public static float AuraAlpha(float x, float y)
		{
			double num = Math.Sqrt(x * x + y * y);
			if (num >= 1.0)
			{
				return 0f;
			}
			double num2 = Math.Exp(0.0 - Math.Pow((num - 0.48) / 0.13, 2.0)) * 0.72;
			double num3 = Math.Exp(0.0 - Math.Pow((num - 0.48) / 0.23, 2.0)) * 0.12;
			return (float)Math.Max(0.0, Math.Min(1.0, (num2 + num3) * Math.Min(1.0, (1.0 - num) * 6.0)));
		}
	}
}
namespace LocalizationManager
{
	[<10b1878f-e44c-4d09-839e-a1dff4722204>NullableContext(1)]
	[<520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(0)]
	[PublicAPI]
	public class Localizer
	{
		private static readonly Action<Localization, string, string> AddWord;

		private static readonly FieldRef<Localization, Dictionary<string, string>> Translations;

		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;

		[<520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(2)]
		private static BaseUnityPlugin _plugin;

		private static readonly List<string> fileExtensions;

		private static BaseUnityPlugin plugin
		{
			get
			{
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: 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([<10b1878f-e44c-4d09-839e-a1dff4722204>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		[<520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(2)]
		[method: <10b1878f-e44c-4d09-839e-a1dff4722204>NullableContext(2)]
		[field: <520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(2)]
		public static event Action OnLocalizationComplete;

		private static void UpdatePlaceholderText(Localization localization, string key)
		{
			localizationLanguage.TryGetValue(localization, out var value);
			string text = loadedTexts[value][key];
			if (PlaceholderProcessors.TryGetValue(key, out var value2))
			{
				text = value2.Aggregate(text, [<10b1878f-e44c-4d09-839e-a1dff4722204>NullableContext(0)] (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			AddWord(localization, key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, [<520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(new byte[] { 2, 1, 1 })] Func<T, string> convertConfigValue = null)
		{
			if (convertConfigValue == null)
			{
				convertConfigValue = (T val) => val.ToString();
			}
			if (!PlaceholderProcessors.ContainsKey(key))
			{
				PlaceholderProcessors[key] = new Dictionary<string, Func<string>>();
			}
			config.SettingChanged += [<10b1878f-e44c-4d09-839e-a1dff4722204>NullableContext(0)] (object _, EventArgs _) =>
			{
				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 (!Translations.Invoke(target).ContainsKey(key))
					{
						dictionary[key] = text;
						AddWord(target, key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

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

		public static void LoadLocalizationLater()
		{
			LoadLocalization(Localization.instance, Localization.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 key = array[1];
					if (!dictionary.ContainsKey(key))
					{
						dictionary[key] = 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 text = null;
			if (language != "English")
			{
				if (dictionary.TryGetValue(language, out var value))
				{
					text = File.ReadAllText(value);
				}
				else
				{
					byte[] array3 = LoadTranslationFromAssembly(language);
					if (array3 != null)
					{
						text = Encoding.UTF8.GetString(array3);
					}
				}
			}
			if (text == null && dictionary.TryGetValue("English", out var value2))
			{
				text = File.ReadAllText(value2);
			}
			if (text != null)
			{
				foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text) ?? 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			AddWord = AccessTools.MethodDelegate<Action<Localization, string, string>>(AccessTools.Method(typeof(Localization), "AddWord", (Type[])null, (Type[])null), (object)null, true);
			Translations = AccessTools.FieldRefAccess<Localization, Dictionary<string, string>>("m_translations");
			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);
		}

		[return: <520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(2)]
		private static byte[] LoadTranslationFromAssembly(string language)
		{
			foreach (string fileExtension in fileExtensions)
			{
				byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension);
				if (array != null)
				{
					return array;
				}
			}
			return null;
		}

		[<10b1878f-e44c-4d09-839e-a1dff4722204>NullableContext(2)]
		public static byte[] ReadEmbeddedFileBytes([<520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(1)] string resourceFileName, Assembly containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault([<10b1878f-e44c-4d09-839e-a1dff4722204>NullableContext(0)] (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
	{
		[<520c740c-0a0b-4506-a2a4-96b0bb152a58>Nullable(1)]
		public const string Version = "1.4.1";
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<65dd6d53-5cb1-42d6-ae6f-5e4a3c1c90ac>Embedded]
	internal sealed class <65dd6d53-5cb1-42d6-ae6f-5e4a3c1c90ac>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	[<65dd6d53-5cb1-42d6-ae6f-5e4a3c1c90ac>Embedded]
	[CompilerGenerated]
	internal sealed class <aa07bf1c-2e11-48dd-860b-ef3b66ec3053>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <aa07bf1c-2e11-48dd-860b-ef3b66ec3053>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <aa07bf1c-2e11-48dd-860b-ef3b66ec3053>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[<65dd6d53-5cb1-42d6-ae6f-5e4a3c1c90ac>Embedded]
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class <120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[<65dd6d53-5cb1-42d6-ae6f-5e4a3c1c90ac>Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class <a2d9cf3a-1c07-496f-bee5-842b61fac3ff>RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public <a2d9cf3a-1c07-496f-bee5-842b61fac3ff>RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ServerSync
{
	[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(0)]
	[PublicAPI]
	[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(1)]
	internal abstract class OwnConfigEntryBase
	{
		[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(2)]
		public object LocalBaseValue;

		public bool SynchronizedConfig = true;

		public abstract ConfigEntryBase BaseConfig { get; }
	}
	[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(0)]
	[PublicAPI]
	[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(1)]
	internal class SyncedConfigEntry<[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(2)] T>(ConfigEntry<T> sourceConfig) : OwnConfigEntryBase()
	{
		public readonly ConfigEntry<T> SourceConfig = sourceConfig;

		public override ConfigEntryBase BaseConfig => (ConfigEntryBase)(object)SourceConfig;

		public T Value
		{
			get
			{
				return SourceConfig.Value;
			}
			set
			{
				SourceConfig.Value = value;
			}
		}

		public void AssignLocalValue(T value)
		{
			if (LocalBaseValue == null)
			{
				Value = value;
			}
			else
			{
				LocalBaseValue = value;
			}
		}
	}
	[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(2)]
	[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(0)]
	internal abstract class CustomSyncedValueBase
	{
		public object LocalBaseValue;

		[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(1)]
		public readonly string Identifier;

		[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(1)]
		public readonly Type Type;

		private object boxedValue;

		protected bool localIsOwner;

		public readonly int Priority;

		public object BoxedValue
		{
			get
			{
				return boxedValue;
			}
			set
			{
				boxedValue = value;
				this.ValueChanged?.Invoke();
			}
		}

		public event Action ValueChanged;

		[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(1)]
		protected CustomSyncedValueBase(ConfigSync configSync, string identifier, Type type, int priority)
		{
			Priority = priority;
			Identifier = identifier;
			Type = type;
			configSync.AddCustomValue(this);
			localIsOwner = configSync.IsSourceOfTruth;
			configSync.SourceOfTruthChanged += delegate(bool truth)
			{
				localIsOwner = truth;
			};
		}
	}
	[PublicAPI]
	[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(1)]
	[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(0)]
	internal sealed class CustomSyncedValue<[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(2)] T> : CustomSyncedValueBase
	{
		public T Value
		{
			get
			{
				return (T)base.BoxedValue;
			}
			set
			{
				base.BoxedValue = value;
			}
		}

		public CustomSyncedValue(ConfigSync configSync, string identifier, T value = default(T), int priority = 0)
			: base(configSync, identifier, typeof(T), priority)
		{
			Value = value;
		}

		public void AssignLocalValue(T value)
		{
			if (localIsOwner)
			{
				Value = value;
			}
			else
			{
				LocalBaseValue = value;
			}
		}
	}
	internal class ConfigurationManagerAttributes
	{
		[UsedImplicitly]
		public bool? ReadOnly = false;
	}
	[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(1)]
	[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(0)]
	[PublicAPI]
	internal class ConfigSync
	{
		[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(0)]
		[HarmonyPatch(typeof(ZRpc), "HandlePackage")]
		private static class SnatchCurrentlyHandlingRPC
		{
			[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(2)]
			public static ZRpc currentRpc;

			[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(1)]
			[HarmonyPrefix]
			private static void Prefix(ZRpc __instance)
			{
				currentRpc = __instance;
			}
		}

		[HarmonyPatch(typeof(ZNet), "Awake")]
		[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(0)]
		internal static class RegisterRPCPatch
		{
			[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(1)]
			[HarmonyPostfix]
			private static void Postfix(ZNet __instance)
			{
				isServer = __instance.IsServer();
				foreach (ConfigSync configSync2 in configSyncs)
				{
					ZRoutedRpc.instance.Register<ZPackage>(configSync2.Name + " ConfigSync", (Action<long, ZPackage>)configSync2.RPC_FromOtherClientConfigSync);
					if (isServer)
					{
						configSync2.InitialSyncDone = true;
						Debug.Log((object)("Registered '" + configSync2.Name + " ConfigSync' RPC - waiting for incoming connections"));
					}
				}
				if (isServer)
				{
					((MonoBehaviour)__instance).StartCoroutine(WatchAdminListChanges());
				}
				[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(1)]
				static void SendAdmin(List<ZNetPeer> peers, bool isAdmin)
				{
					ZPackage package = ConfigsToPackage(null, null, new PackageEntry[1]
					{
						new PackageEntry
						{
							section = "Internal",
							key = "lockexempt",
							type = typeof(bool),
							value = isAdmin
						}
					});
					ConfigSync configSync = configSyncs.First();
					if (configSync != null)
					{
						((MonoBehaviour)ZNet.instance).StartCoroutine(configSync.sendZPackage(peers, package));
					}
				}
				[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(1)]
				static IEnumerator WatchAdminListChanges()
				{
					MethodInfo listContainsId = AccessTools.DeclaredMethod(typeof(ZNet), "ListContainsId", (Type[])null, (Type[])null);
					SyncedList adminList = (SyncedList)AccessTools.DeclaredField(typeof(ZNet), "m_adminList").GetValue(ZNet.instance);
					List<string> CurrentList = new List<string>(adminList.GetList());
					while (true)
					{
						yield return (object)new WaitForSeconds(30f);
						if (!adminList.GetList().SequenceEqual(CurrentList))
						{
							CurrentList = new List<string>(adminList.GetList());
							List<ZNetPeer> adminPeer = ZNet.instance.GetPeers().Where(delegate(ZNetPeer p)
							{
								string hostName = p.m_rpc.GetSocket().GetHostName();
								return ((object)listContainsId == null) ? adminList.Contains(hostName) : ((bool)listContainsId.Invoke(ZNet.instance, new object[2] { adminList, hostName }));
							}).ToList();
							List<ZNetPeer> nonAdminPeer = ZNet.instance.GetPeers().Except(adminPeer).ToList();
							SendAdmin(nonAdminPeer, isAdmin: false);
							SendAdmin(adminPeer, isAdmin: true);
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(ZNet), "OnNewConnection")]
		[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(0)]
		private static class RegisterClientRPCPatch
		{
			[HarmonyPostfix]
			[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(1)]
			private static void Postfix(ZNet __instance, ZNetPeer peer)
			{
				if (__instance.IsServer())
				{
					return;
				}
				foreach (ConfigSync configSync in configSyncs)
				{
					peer.m_rpc.Register<ZPackage>(configSync.Name + " ConfigSync", (Action<ZRpc, ZPackage>)configSync.RPC_FromServerConfigSync);
				}
			}
		}

		[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(0)]
		private class ParsedConfigs
		{
			[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(new byte[] { 1, 1, 2 })]
			public readonly Dictionary<OwnConfigEntryBase, object> configValues = new Dictionary<OwnConfigEntryBase, object>();

			[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(new byte[] { 1, 1, 2 })]
			public readonly Dictionary<CustomSyncedValueBase, object> customValues = new Dictionary<CustomSyncedValueBase, object>();
		}

		[<120cc715-d4bc-4d60-bc4c-a2a2ea103b9b>NullableContext(0)]
		[HarmonyPatch(typeof(ZNet), "Shutdown")]
		private class ResetConfigsOnShutdown
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				ProcessingServerUpdate = true;
				foreach (ConfigSync configSync in configSyncs)
				{
					configSync.resetConfigsFromServer();
					configSync.IsSourceOfTruth = true;
					configSync.InitialSyncDone = false;
				}
				ProcessingServerUpdate = false;
			}
		}

		[HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")]
		[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(0)]
		private class SendConfigsAfterLogin
		{
			[<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(0)]
			private class BufferingSocket : ZPlayFabSocket, ISocket
			{
				public volatile bool finished = false;

				public volatile int versionMatchQueued = -1;

				public readonly List<ZPackage> Package = new List<ZPackage>();

				public readonly ISocket Original;

				public BufferingSocket(ISocket original)
				{
					Original = original;
					((ZPlayFabSocket)this)..ctor();
				}

				public bool IsConnected()
				{
					return Original.IsConnected();
				}

				public ZPackage Recv()
				{
					return Original.Recv();
				}

				public int GetSendQueueSize()
				{
					return Original.GetSendQueueSize();
				}

				public int GetCurrentSendRate()
				{
					return Original.GetCurrentSendRate();
				}

				public bool IsHost()
				{
					return Original.IsHost();
				}

				public void Dispose()
				{
					Original.Dispose();
				}

				public bool GotNewData()
				{
					return Original.GotNewData();
				}

				public void Close()
				{
					Original.Close();
				}

				public string GetEndPointString()
				{
					return Original.GetEndPointString();
				}

				public void GetAndResetStats(out int totalSent, out int totalRecv)
				{
					Original.GetAndResetStats(ref totalSent, ref totalRecv);
				}

				public void GetConnectionQuality(out float localQuality, out float remoteQuality, out int ping, out float outByteSec, out float inByteSec)
				{
					Original.GetConnectionQuality(ref localQuality, ref remoteQuality, ref ping, ref outByteSec, ref inByteSec);
				}

				public ISocket Accept()
				{
					return Original.Accept();
				}

				public int GetHostPort()
				{
					return Original.GetHostPort();
				}

				public bool Flush()
				{
					return Original.Flush();
				}

				public string GetHostName()
				{
					return Original.GetHostName();
				}

				public void VersionMatch()
				{
					if (finished)
					{
						Original.VersionMatch();
					}
					else
					{
						versionMatchQueued = Package.Count;
					}
				}

				public void Send(ZPackage pkg)
				{
					//IL_0057: Unknown result type (might be due to invalid IL or missing references)
					//IL_005d: Expected O, but got Unknown
					int pos = pkg.GetPos();
					pkg.SetPos(0);
					int num = pkg.ReadInt();
					if ((num == StringExtensionMethods.GetStableHashCode("PeerInfo") || num == StringExtensionMethods.GetStableHashCode("RoutedRPC") || num == StringExtensionMethods.GetStableHashCode("ZDOData")) && !finished)
					{
						ZPackage val = new ZPackage(pkg.GetArray());
						val.SetPos(pos);
						Package.Add(val);
					}
					else
					{
						pkg.SetPos(pos);
						Original.Send(pkg);
					}
				}
			}

			[HarmonyPrefix]
			[HarmonyPriority(800)]
			private static void Prefix([<aa07bf1c-2e11-48dd-860b-ef3b66ec3053>Nullable(new byte[] { 2, 1, 1 })] ref Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc)
			{
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Invalid comparison between Unknown and I4
				if (!__instance.IsServer())
				{
					return;
				}
				BufferingSocket bufferingSocket = new BufferingSocket(rpc.GetSocket());
				AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket);
				object? obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc });
				ZNetPeer val = (ZNetPeer)((obj is ZNetPeer) ? obj : null);
				if (val != null && (int)ZNet.m_onlineBackend > 0)
				{
					FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket");
					object? value = fieldInfo.GetValue(val);
					ZPlayFabSocket val2 = (ZPlayFabSocket)((value is ZPlayFabSocket) ? value : null);
					if (val2 != null)
					{
						typeof(ZPlayFabSocket).GetField("m_remotePlayerId").SetValue(bufferingSocket, val2.m_remotePlayerId);
					}
					fieldInfo.SetValue(val, bufferingSocket);
				}
				if (__state == null)
				{
					__state = new Dictionary<Assembly, BufferingSocket>();
				}
				__state[Assembly.GetExecutingAssembly()] = bufferingSocket;
			}

			[HarmonyPostfix]
			private static void Postfix(Dictionary<Assembly, BufferingSocket> __state, ZNet __instance, ZRpc rpc)
			{
				ZNetPeer peer;
				if (__instance.IsServer())
				{
					object obj = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc });
					peer = (ZNetPeer)((obj is ZNetPeer) ? obj : null);
					if (peer == null)
					{
						SendBufferedData();
					}
					else
					{
						((MonoBehaviour)__instance).StartCoroutine(sendAsync());
					}
				}
				void SendBufferedData()
				{
					if (rpc.GetSocket() is BufferingSocket bufferingSocket)
					{
						AccessTools.DeclaredField(typeof(ZRpc), "m_socket").SetValue(rpc, bufferingSocket.Original);
						object? obj2 = AccessTools.DeclaredMethod(typeof(ZNet), "GetPeer", new Type[1] { typeof(ZRpc) }, (Type[])null).Invoke(__instance, new object[1] { rpc });
						ZNetPeer val = (ZNetPeer)((obj2 is ZNetPeer) ? obj2 : null);
						if (val != null)
						{
							AccessTools.DeclaredField(typeof(ZNetPeer), "m_socket").SetValue(val, bufferingSocket.Or